mirror of https://github.com/vuejs/vue.git
clean up get binding owner compiler logic
This commit is contained in:
parent
1fb885b9fa
commit
9a45f63f34
|
|
@ -44,30 +44,23 @@ function Compiler (vm, options) {
|
|||
|
||||
// set compiler properties
|
||||
compiler.vm = vm
|
||||
compiler.bindings = makeHash()
|
||||
compiler.dirs = []
|
||||
compiler.exps = []
|
||||
compiler.computed = []
|
||||
compiler.childCompilers = []
|
||||
compiler.emitter = new Emitter()
|
||||
|
||||
// inherit parent bindings
|
||||
var parent = compiler.parentCompiler
|
||||
compiler.bindings = parent
|
||||
? Object.create(parent.bindings)
|
||||
: makeHash()
|
||||
compiler.rootCompiler = parent
|
||||
? getRoot(parent)
|
||||
: compiler
|
||||
|
||||
// set inenumerable VM properties
|
||||
def(vm, '$', makeHash())
|
||||
def(vm, '$el', el)
|
||||
def(vm, '$compiler', compiler)
|
||||
def(vm, '$root', compiler.rootCompiler.vm)
|
||||
def(vm, '$root', getRoot(compiler).vm)
|
||||
|
||||
// set parent VM
|
||||
// and register child id on parent
|
||||
var childId = utils.attr(el, 'component-id')
|
||||
var parent = compiler.parentCompiler,
|
||||
childId = utils.attr(el, 'component-id')
|
||||
if (parent) {
|
||||
parent.childCompilers.push(compiler)
|
||||
def(vm, '$parent', parent.vm)
|
||||
|
|
@ -204,7 +197,7 @@ CompilerProto.setupObserver = function () {
|
|||
})
|
||||
|
||||
function check (key) {
|
||||
if (!hasOwn.call(bindings, key)) {
|
||||
if (!bindings[key]) {
|
||||
compiler.createBinding(key)
|
||||
}
|
||||
}
|
||||
|
|
@ -405,31 +398,23 @@ CompilerProto.bindDirective = function (directive) {
|
|||
|
||||
// otherwise, we got more work to do...
|
||||
var binding,
|
||||
compiler = this,
|
||||
key = directive.key,
|
||||
baseKey = key.split('.')[0]
|
||||
compiler = this,
|
||||
key = directive.key
|
||||
|
||||
if (directive.isExp) {
|
||||
// expression bindings are always created on current compiler
|
||||
binding = compiler.createBinding(key, true, directive.isFn)
|
||||
} else {
|
||||
// recursively locate where to place the binding
|
||||
// recursively locate which compiler owns the binding
|
||||
while (compiler) {
|
||||
if (
|
||||
hasOwn.call(compiler.data, baseKey) ||
|
||||
hasOwn.call(compiler.vm, baseKey)
|
||||
) {
|
||||
// If a compiler has the base key, the directive should
|
||||
// belong to it. Create the binding if it's not created already.
|
||||
binding = hasOwn.call(compiler.bindings, key)
|
||||
? compiler.bindings[key]
|
||||
: compiler.createBinding(key)
|
||||
if (compiler.hasKey(key)) {
|
||||
break
|
||||
} else {
|
||||
compiler = compiler.parentCompiler
|
||||
}
|
||||
}
|
||||
if (!binding) binding = this.createBinding(key)
|
||||
compiler = compiler || this
|
||||
binding = compiler.bindings[key] || compiler.createBinding(key)
|
||||
}
|
||||
|
||||
binding.instances.push(directive)
|
||||
|
|
@ -484,7 +469,7 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
|
|||
// ensure path in data so it can be observed
|
||||
Observer.ensurePath(compiler.data, key)
|
||||
var parentKey = key.slice(0, key.lastIndexOf('.'))
|
||||
if (!hasOwn.call(bindings, parentKey)) {
|
||||
if (!bindings[parentKey]) {
|
||||
// this is a nested value binding, but the binding for its parent
|
||||
// has not been created yet. We better create that one too.
|
||||
compiler.createBinding(parentKey)
|
||||
|
|
@ -585,6 +570,15 @@ CompilerProto.execHook = function (id, alt) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a compiler's data contains a keypath
|
||||
*/
|
||||
CompilerProto.hasKey = function (key) {
|
||||
var baseKey = key.split('.')[0]
|
||||
return hasOwn.call(this.data, baseKey) ||
|
||||
hasOwn.call(this.vm, baseKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind and remove element
|
||||
*/
|
||||
|
|
@ -626,8 +620,8 @@ CompilerProto.destroy = function () {
|
|||
|
||||
// unbind/unobserve all own bindings
|
||||
for (key in bindings) {
|
||||
if (hasOwn.call(bindings, key)) {
|
||||
binding = bindings[key]
|
||||
binding = bindings[key]
|
||||
if (binding) {
|
||||
if (binding.root) {
|
||||
Observer.unobserve(binding.value, binding.key, compiler.observer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
var utils = require('./utils'),
|
||||
hasOwn = Object.prototype.hasOwnProperty,
|
||||
stringSaveRE = /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g,
|
||||
stringRestoreRE = /"(\d+)"/g
|
||||
|
||||
|
|
@ -54,38 +53,25 @@ function getVariables (code) {
|
|||
*/
|
||||
function getRel (path, compiler) {
|
||||
var rel = '',
|
||||
has = false,
|
||||
nest = 0,
|
||||
vm = compiler.vm,
|
||||
dot = path.indexOf('.'),
|
||||
key = dot > -1
|
||||
? path.slice(0, dot)
|
||||
: path
|
||||
while (true) {
|
||||
if (
|
||||
hasOwn.call(vm.$data, key) ||
|
||||
hasOwn.call(vm, key)
|
||||
) {
|
||||
has = true
|
||||
dist = 0,
|
||||
self = compiler
|
||||
while (compiler) {
|
||||
if (compiler.hasKey(path)) {
|
||||
break
|
||||
} else {
|
||||
if (vm.$parent) {
|
||||
vm = vm.$parent
|
||||
nest++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
compiler = compiler.parentCompiler
|
||||
dist++
|
||||
}
|
||||
}
|
||||
if (has) {
|
||||
while (nest--) {
|
||||
if (compiler) {
|
||||
while (dist--) {
|
||||
rel += '$parent.'
|
||||
}
|
||||
if (!hasOwn.call(vm.$compiler.bindings, path) && path.charAt(0) !== '$') {
|
||||
vm.$compiler.createBinding(path)
|
||||
if (!compiler.bindings[path] && path.charAt(0) !== '$') {
|
||||
compiler.createBinding(path)
|
||||
}
|
||||
} else {
|
||||
compiler.createBinding(path)
|
||||
self.createBinding(path)
|
||||
}
|
||||
return rel
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ describe('UNIT: Expression Parser', function () {
|
|||
var caughtMissingPaths = [],
|
||||
compilerMock = {
|
||||
createBinding: createBinding,
|
||||
hasKey: function () {},
|
||||
vm:{
|
||||
$data: {},
|
||||
$compiler:{
|
||||
|
|
@ -120,12 +121,14 @@ describe('UNIT: Expression Parser', function () {
|
|||
utils.warn = function () {
|
||||
warned = true
|
||||
}
|
||||
function noop () {}
|
||||
ExpParser.parse('a + "fsef', {
|
||||
createBinding: function () {},
|
||||
createBinding: noop,
|
||||
hasKey: noop,
|
||||
vm: {
|
||||
$compiler: {
|
||||
bindings: {},
|
||||
createBinding: function () {}
|
||||
createBinding: noop
|
||||
},
|
||||
$data: {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -371,8 +371,7 @@ describe('UNIT: ViewModel', function () {
|
|||
expUnbindCalled = false,
|
||||
bindingUnbindCalled = false,
|
||||
unobserveCalled = 0,
|
||||
elRemoved = false,
|
||||
externalBindingUnbindCalled = false
|
||||
elRemoved = false
|
||||
|
||||
var dirMock = {
|
||||
binding: {
|
||||
|
|
@ -385,26 +384,21 @@ describe('UNIT: ViewModel', function () {
|
|||
}
|
||||
dirMock.binding.instances.push(dirMock)
|
||||
|
||||
var bindingsMock = Object.create({
|
||||
'test2': {
|
||||
unbind: function () {
|
||||
externalBindingUnbindCalled = true
|
||||
}
|
||||
}
|
||||
})
|
||||
bindingsMock.test = {
|
||||
root: true,
|
||||
key: 'test',
|
||||
value: {
|
||||
__observer__: {
|
||||
off: function () {
|
||||
unobserveCalled++
|
||||
return this
|
||||
var bindingsMock = {
|
||||
test: {
|
||||
root: true,
|
||||
key: 'test',
|
||||
value: {
|
||||
__observer__: {
|
||||
off: function () {
|
||||
unobserveCalled++
|
||||
return this
|
||||
}
|
||||
}
|
||||
},
|
||||
unbind: function () {
|
||||
bindingUnbindCalled = true
|
||||
}
|
||||
},
|
||||
unbind: function () {
|
||||
bindingUnbindCalled = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -487,10 +481,6 @@ describe('UNIT: ViewModel', function () {
|
|||
assert.strictEqual(unobserveCalled, 3)
|
||||
})
|
||||
|
||||
it('should not unbind external bindings', function () {
|
||||
assert.notOk(externalBindingUnbindCalled)
|
||||
})
|
||||
|
||||
it('should remove self from parentCompiler', function () {
|
||||
var parent = compilerMock.parentCompiler
|
||||
assert.ok(parent.childCompilers.indexOf(compilerMock), -1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue