diff --git a/src/compiler/compile.js b/src/compiler/compile.js index 777397a51..b611fa7ae 100644 --- a/src/compiler/compile.js +++ b/src/compiler/compile.js @@ -87,29 +87,26 @@ function linkAndCapture (linker, vm) { var originalDirCount = vm._directives.length linker() var dirs = vm._directives.slice(originalDirCount) - var dir + dirs.sort(directiveComparator) for (var i = 0, l = dirs.length; i < l; i++) { - dir = dirs[i] - if (dir.name === 'if' || - dir.name === 'for' || - dir.name === 'repeat') { - dir._bind() - } - } - for (var i = 0, l = dirs.length; i < l; i++) { - dir = dirs[i] - if (dir.name === 'component' || - dir.name === 'el') { - dir._bind() - } - } - for (var i = 0, l = dirs.length; i < l; i++) { - dir = dirs[i] - if (!dir._bound) dir._bind() + dirs[i]._bind() } return dirs } +/** + * Directive priority sort comparator + * + * @param {Object} a + * @param {Object} b + */ + +function directiveComparator (a, b) { + a = a._def.priority || 0 + b = b._def.priority || 0 + return a > b ? -1 : a === b ? 0 : 1 +} + /** * Linker functions return an unlink function that * tearsdown all directives instances generated during @@ -264,8 +261,10 @@ function compileElement (el, options) { // textarea treats its text content as the initial value. // just bind it as a v-attr directive for value. if (el.tagName === 'TEXTAREA') { - if (textParser.parse(el.value)) { - el.setAttribute('value', el.value) + var tokens = textParser.parse(el.value) + if (tokens) { + el.setAttribute('bind-value', textParser.tokensToExp(tokens)) + el.value = '' } } var linkFn @@ -629,7 +628,6 @@ function compileDirectives (attrs, options) { } // sort by priority, LOW to HIGH if (dirs.length) { - dirs.sort(directiveComparator) return makeNodeLinkFn(dirs) } } @@ -717,16 +715,3 @@ function collectAttrDirective (name, value, options) { } } } - -/** - * Directive priority sort comparator - * - * @param {Object} a - * @param {Object} b - */ - -function directiveComparator (a, b) { - a = a.def.priority || 0 - b = b.def.priority || 0 - return a > b ? 1 : -1 -} diff --git a/src/directives/component.js b/src/directives/component.js index 03403969c..c64d04b1a 100644 --- a/src/directives/component.js +++ b/src/directives/component.js @@ -5,6 +5,7 @@ var templateParser = require('../parsers/template') module.exports = { isLiteral: true, + priority: 1500, /** * Setup. Two possible usages: diff --git a/src/directives/el.js b/src/directives/el.js index cbe57d7d9..b23f2a3da 100644 --- a/src/directives/el.js +++ b/src/directives/el.js @@ -3,7 +3,7 @@ var _ = require('../util') module.exports = { isLiteral: true, - priority: 1000, + priority: 1500, bind: function () { var scope = this._scope || this.vm diff --git a/src/directives/for.js b/src/directives/for.js index 59bbe6adf..0924cbb4d 100644 --- a/src/directives/for.js +++ b/src/directives/for.js @@ -7,6 +7,8 @@ var uid = 0 module.exports = { + priority: 2000, + bind: function () { // some helpful tips... diff --git a/src/directives/if.js b/src/directives/if.js index c7dd8a3a7..4be209096 100644 --- a/src/directives/if.js +++ b/src/directives/if.js @@ -3,6 +3,8 @@ var FragmentFactory = require('../fragment/factory') module.exports = { + priority: 2000, + bind: function () { var el = this.el if (!el.__vue__) { diff --git a/src/directives/repeat.js b/src/directives/repeat.js index c27d19f93..e137e90dc 100644 --- a/src/directives/repeat.js +++ b/src/directives/repeat.js @@ -17,6 +17,8 @@ var ABORTED = 3 module.exports = { + priority: 2000, + /** * Setup. */ diff --git a/src/element-directives/partial.js b/src/element-directives/partial.js index 35a46dcca..09bfe54f8 100644 --- a/src/element-directives/partial.js +++ b/src/element-directives/partial.js @@ -5,6 +5,8 @@ var vIf = require('../directives/if') module.exports = { + priority: 1750, + bind: function () { var el = this.el this.anchor = _.createAnchor('v-partial') diff --git a/src/element-directives/slot.js b/src/element-directives/slot.js index e2fe5d053..5754b87ce 100644 --- a/src/element-directives/slot.js +++ b/src/element-directives/slot.js @@ -9,6 +9,8 @@ var templateParser = require('../parsers/template') module.exports = { + priority: 1750, + bind: function () { this.isSlot = this.el.tagName === 'SLOT' diff --git a/test/unit/specs/compiler/compile_spec.js b/test/unit/specs/compiler/compile_spec.js index 1cdad36a6..faa0d7f16 100644 --- a/test/unit/specs/compiler/compile_spec.js +++ b/test/unit/specs/compiler/compile_spec.js @@ -19,10 +19,13 @@ if (_.inBrowser) { vm = { _data: {}, _directives: [], - _bindDir: function (name) { + _bindDir: function (name, node, desc, def) { this._directives.push({ name: name, - _bind: directiveBind, + _def: def, + _bind: function () { + directiveBind(this.name) + }, _teardown: directiveTeardown }) }, @@ -68,8 +71,11 @@ if (_.inBrowser) { expect(vm._bindDir).toHaveBeenCalledWith('b', el.firstChild, descriptorB, defB, undefined, undefined, undefined, undefined) expect(vm._bindDir).toHaveBeenCalledWith('b', el.lastChild, descriptorB, defB, undefined, undefined, undefined, undefined) // check the priority sorting - // the "b" on the firstNode should be called first! - expect(vm._bindDir.calls.argsFor(1)[0]).toBe('b') + // the "b"s should be called first! + expect(directiveBind.calls.argsFor(0)[0]).toBe('b') + expect(directiveBind.calls.argsFor(1)[0]).toBe('b') + expect(directiveBind.calls.argsFor(2)[0]).toBe('a') + expect(directiveBind.calls.argsFor(3)[0]).toBe('a') }) it('bind- syntax', function () { diff --git a/test/unit/specs/directives/el_spec.js b/test/unit/specs/directives/el_spec.js index e011ab70a..f65153c33 100644 --- a/test/unit/specs/directives/el_spec.js +++ b/test/unit/specs/directives/el_spec.js @@ -13,7 +13,7 @@ if (_.inBrowser) { it('normal', function () { var vm = new Vue({ el: el, - template: '
' + template: '
' }) expect(vm.$$.test).toBeTruthy() expect(vm.$$.test.id).toBe('test') @@ -21,6 +21,27 @@ if (_.inBrowser) { expect(vm.$$.test).toBeNull() }) + it('normal (new syntax)', function (done) { + var vm = new Vue({ + el: el, + data: { + ok: true + }, + template: '
' + }) + expect(vm.$$.test).toBeTruthy() + expect(vm.$$.test.id).toBe('test') + vm.ok = false + _.nextTick(function () { + expect(vm.$$.test).toBeNull() + vm.ok = true + _.nextTick(function () { + expect(vm.$$.test.id).toBe('test') + done() + }) + }) + }) + it('with v-repeat', function (done) { var vm = new Vue({ el: el,