restructure

This commit is contained in:
Evan You 2014-07-14 10:43:48 -04:00
parent 49ad4ca7d1
commit 706c67d1d0
24 changed files with 199 additions and 26 deletions

View File

@ -1,6 +1,6 @@
console.log('\nObserver\n')
var Observer = require('../src/observer/observer')
var Observer = require('../src/observe/observer')
var Emitter = require('../src/emitter')
var OldObserver = require('../../vue/src/observer')
var sideEffect = true

View File

@ -1,4 +1,4 @@
var Observer = require('../src/observer/observer')
var Observer = require('../src/observe/observer')
var _ = require('../src/util')
function Vue (options) {
@ -87,9 +87,7 @@ function Vue (options) {
// also proxy newly added keys.
var self = this
ob.on('added', function (key) {
if (!self.hasOwnProperty(key)) {
_.proxy(self, scope, key)
}
_.proxy(self, scope, key)
})
}

View File

View File

@ -6,10 +6,26 @@ exports.$set = function () {
}
exports.$add = function () {
}
exports.$delete = function () {
}
exports.$watch = function () {
}
exports.$unwatch = function () {
}
exports.$toJSON = function () {
}
exports.$log = function () {
}

View File

61
src/api/global.js Normal file
View File

@ -0,0 +1,61 @@
var _ = require('../util')
var config = require('../config')
/**
* Configuration
*/
exports.config = function () {
}
/**
* Class inehritance
*/
exports.extend = function () {
}
/**
* Plugin system
*/
exports.use = function () {
}
/**
* Expose some internal utilities
*/
exports.require = function () {
}
/**
* Define asset registries and registration
* methods on a constructor.
*/
config.assetTypes.forEach(function (type) {
var registry = '_' + type + 's'
exports[registry] = {}
/**
* Asset registration method.
*
* @param {String} id
* @param {*} definition
*/
exports[type] = function (id, definition) {
this[registry][id] = definition
}
})
/**
* This is pretty useful so we expose it as a global method.
*/
exports.nextTick = _.nextTick

View File

View File

View File

@ -1 +1,11 @@
module.exports = {}
module.exports = {
assetTypes: [
'directive',
'filter',
'partial',
'effect',
'component'
]
}

90
src/internal/init.js Normal file
View File

@ -0,0 +1,90 @@
exports._init = function (options) {
var data = options.data
var parent = options.parent
var scope = this._scope = parent
? Object.create(parent._scope)
: {}
// copy instantiation data into scope
for (var key in data) {
if (key in scope) {
// key exists on the scope prototype chain
// cannot use direct set here, because in the parent
// scope everything is already getter/setter and we
// need to overwrite them with Object.defineProperty.
_.define(scope, key, data[key], true)
} else {
scope[key] = data[key]
}
}
// create observer
// pass in noProto:true to avoid mutating the __proto__
var ob = this._observer = Observer.create(scope, { noProto: true })
var dob = Observer.create(data)
var locked = false
// sync scope and original data.
ob
.on('set', guard(function (key, val) {
data[key] = val
}))
.on('added', guard(function (key, val) {
data.$add(key, val)
}))
.on('deleted', guard(function (key) {
data.$delete(key)
}))
// also need to sync data object changes to scope...
// this would cause cycle updates, so we need to lock
// stuff when one side updates the other
dob
.on('set', guard(function (key, val) {
scope[key] = val
}))
.on('added', guard(function (key, val) {
scope.$add(key, val)
}))
.on('deleted', guard(function (key) {
scope.$delete(key)
}))
function guard (fn) {
return function (key, val) {
if (locked || key.indexOf(Observer.pathDelimiter) > -1) {
return
}
locked = true
fn(key, val)
locked = false
}
}
// relay change events from parent scope.
// this ensures the current Vue instance is aware of
// stuff going on up in the scope chain.
if (parent) {
var po = parent._observer
;['set', 'mutate', 'added', 'deleted'].forEach(function (event) {
po.on(event, function (key, a, b) {
if (!scope.hasOwnProperty(key)) {
ob.emit(event, key, a, b)
}
})
})
}
// proxy everything on self
for (var key in scope) {
_.proxy(this, scope, key)
}
// also proxy newly added keys.
var self = this
ob.on('added', function (key) {
_.proxy(self, scope, key)
})
}

View File

@ -85,7 +85,7 @@ Observer.create = function (value, options) {
return value.$observer
} if (_.isArray(value)) {
return new Observer(value, ARRAY, options)
} else if (_.isObject(value)) {
} else if (_.isObject(value) && !value._scope) { // avoid Vue instance
return new Observer(value, OBJECT, options)
}
}

View File

@ -36,6 +36,7 @@ exports.deepMixin = function (to, from) {
*/
exports.proxy = function (to, from, key) {
if (to.hasOwnProperty(key)) return
Object.defineProperty(to, key, {
enumerable: true,
configurable: true,

View File

@ -1,5 +1,4 @@
var _ = require('./util')
var Compiler = require('./compiler/compiler')
var _ = require('./util')
/**
* The exposed Vue constructor.
@ -10,33 +9,31 @@ var Compiler = require('./compiler/compiler')
*/
function Vue (options) {
this._compiler = new Compiler(this, options)
this._init(options)
}
/**
* Mixin instance methods
*/
var p = Vue.prototype
_.mixin(p, require('./instance/lifecycle'))
_.mixin(p, require('./instance/data'))
_.mixin(p, require('./instance/dom'))
_.mixin(p, require('./instance/events'))
/**
* Mixin asset registers
* Mixin internal instance methods
*/
_.mixin(Vue, require('./api/asset-register'))
_.mixin(p, require('./internal/init'))
_.mixin(p, require('./internal/compile'))
/**
* Static methods
* Mixin API instance methods
*/
Vue.config = require('./api/config')
Vue.use = require('./api/use')
Vue.require = require('./api/require')
Vue.extend = require('./api/extend')
Vue.nextTick = require('./util').nextTick
_.mixin(p, require('./api/data'))
_.mixin(p, require('./api/dom'))
_.mixin(p, require('./api/events'))
_.mixin(p, require('./api/lifecycle'))
/**
* Mixin global API
*/
_.mixin(Vue, require('./api/global'))
module.exports = Vue