working on new observer

This commit is contained in:
Evan You 2014-07-09 01:35:20 -04:00
parent c225f8c3b8
commit b5bfc59a70
9 changed files with 256 additions and 7 deletions

View File

@ -26,10 +26,13 @@ Hi! Im really excited that you are interested in contributing to Vue.js. Befo
## Code Style
- [No semicolons unless necessary](http://inimino.org/~inimino/blog/javascript_semicolons).
- Follow JSDoc.
- 2 spaces indentation.
- multiple var declarations.
- align equal signs where possible.
- Return early in one line if possible.
- align equal signs where appropriate.
- Return early.
- 1 space after `function`
- 1 space between arguments, but not between parens.
- When in doubt, read the source code.
- Break long ternary conditionals like this:

View File

@ -26,9 +26,9 @@
"src/instance/dom.js",
"src/instance/events.js",
"src/instance/lifecycle.js",
"src/observer/array.js",
"src/observer/object.js",
"src/observer/observer.js",
"src/observer/watch-array.js",
"src/observer/watch-object.js",
"src/parsers/directive.js",
"src/parsers/expression.js",
"src/parsers/path.js",

View File

@ -1 +0,0 @@
module.exports = 123

View File

@ -0,0 +1,137 @@
/**
* Simple event emitter based on component/emitter.
*
* @constructor
* @param {Object} ctx - the context to call listners with.
*/
function Emitter (ctx) {
this._ctx = ctx || this
}
var p = Emitter.prototype
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
*/
p.on = function (event, fn) {
this._cbs = this._cbs || {}
;(this._cbs[event] = this._cbs[event] || [])
.push(fn)
return this
}
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
*/
p.once = function (event, fn) {
var self = this
this._cbs = this._cbs || {}
function on () {
self.off(event, on)
fn.apply(this, arguments)
}
on.fn = fn
this.on(event, on)
return this
}
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
*/
p.off = function (event, fn) {
this._cbs = this._cbs || {}
// all
if (!arguments.length) {
this._cbs = {}
return this
}
// specific event
var callbacks = this._cbs[event]
if (!callbacks) return this
// remove all handlers
if (arguments.length === 1) {
delete this._cbs[event]
return this
}
// remove specific handler
var cb
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i]
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1)
break
}
}
return this
}
/**
* The internal, faster emit with fixed amount of arguments
* using Function.call.
*
* @param {Object} event
* @return {Emitter}
*/
p.emit = function (event, a, b, c) {
this._cbs = this._cbs || {}
var callbacks = this._cbs[event]
if (callbacks) {
callbacks = callbacks.slice(0)
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i].call(this._ctx, a, b, c)
}
}
return this
}
/**
* The external emit using Function.apply, used
* by Vue instance event methods.
*
* @param {Object} event
* @return {Emitter}
*/
p.applyEmit = function (event) {
this._cbs = this._cbs || {}
var callbacks = this._cbs[event], args
if (callbacks) {
callbacks = callbacks.slice(0)
args = callbacks.slice.call(arguments, 1)
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i].apply(this._ctx, args)
}
}
return this
}
module.exports = Emitter

View File

@ -0,0 +1,75 @@
var _ = require('../util')
var Emitter = require('../emitter')
/**
* Observer class that are attached to each observed
* object. They are essentially event emitters, but can
* connect to each other and relay the events up the nested
* object chain.
*
* @constructor
* @extends Emitter
* @private
*/
function Observer () {
Emitter.call(this)
this.connections = Object.create(null)
}
var p = Observer.prototype = Object.create(Emitter.prototype)
/**
* Observe an object of unkown type.
*
* @param {*} obj
* @return {Boolean} - returns true if successfully observed.
*/
p.observe = function (obj) {
if (obj && obj.$observer) {
// already observed
return
}
if (_.isArray(obj)) {
this.observeArray(obj)
return true
}
if (_.isObject(obj)) {
this.observeObject(obj)
return true
}
}
/**
* Connect to another Observer instance,
* capture its get/set/mutate events and relay the events
* while prepending a key segment to the path.
*
* @param {Observer} target
* @param {String} key
*/
p.connect = function (target, key) {
}
/**
* Disconnect from a connected target Observer.
*
* @param {Observer} target
* @param {String} key
*/
p.disconnect = function (target, key) {
}
/**
* Mixin Array and Object observe methods
*/
_.mixin(p, require('./array'))
_.mixin(p, require('./object'))
module.exports = Observer

View File

@ -1,4 +1,9 @@
// common utils
/**
* Mix properties into target object.
*
* @param {Object} target
* @param {Object} mixin
*/
exports.mixin = function (target, mixin) {
for (var key in mixin) {
@ -6,4 +11,27 @@ exports.mixin = function (target, mixin) {
target[key] = mixin[key]
}
}
}
/**
* Object type check. Only returns true
* for plain JavaScript objects.
*
* @param {*} obj
* @return {Boolean}
*/
exports.isObject = function (obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
/**
* Array type check.
*
* @param {*} obj
* @return {Boolean}
*/
exports.isArray = function (obj) {
return Array.isArray(obj)
}

View File

@ -2,13 +2,18 @@ var _ = require('./util')
var Compiler = require('./compiler/compiler')
/**
* The exposed Vue constructor.
* The exposed Vue constructor.
*
* @constructor
* @public
*/
function Vue (options) {
this._compiler = new Compiler(this, options)
}
// mixin instance methods
var p = Vue.prototype
_.mixin(p, require('./instance/lifecycle'))
_.mixin(p, require('./instance/data'))
@ -16,9 +21,11 @@ _.mixin(p, require('./instance/dom'))
_.mixin(p, require('./instance/events'))
// mixin asset registers
_.mixin(Vue, require('./api/asset-register'))
// static methods
Vue.config = require('./api/config')
Vue.use = require('./api/use')
Vue.require = require('./api/require')