implement scope-wise directive priority

This commit is contained in:
Evan You 2015-08-30 16:15:28 -04:00
parent f4af9f685e
commit a9af6c05fe
10 changed files with 63 additions and 40 deletions

View File

@ -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
}

View File

@ -5,6 +5,7 @@ var templateParser = require('../parsers/template')
module.exports = {
isLiteral: true,
priority: 1500,
/**
* Setup. Two possible usages:

View File

@ -3,7 +3,7 @@ var _ = require('../util')
module.exports = {
isLiteral: true,
priority: 1000,
priority: 1500,
bind: function () {
var scope = this._scope || this.vm

View File

@ -7,6 +7,8 @@ var uid = 0
module.exports = {
priority: 2000,
bind: function () {
// some helpful tips...

View File

@ -3,6 +3,8 @@ var FragmentFactory = require('../fragment/factory')
module.exports = {
priority: 2000,
bind: function () {
var el = this.el
if (!el.__vue__) {

View File

@ -17,6 +17,8 @@ var ABORTED = 3
module.exports = {
priority: 2000,
/**
* Setup.
*/

View File

@ -5,6 +5,8 @@ var vIf = require('../directives/if')
module.exports = {
priority: 1750,
bind: function () {
var el = this.el
this.anchor = _.createAnchor('v-partial')

View File

@ -9,6 +9,8 @@ var templateParser = require('../parsers/template')
module.exports = {
priority: 1750,
bind: function () {
this.isSlot = this.el.tagName === 'SLOT'

View File

@ -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 () {

View File

@ -13,7 +13,7 @@ if (_.inBrowser) {
it('normal', function () {
var vm = new Vue({
el: el,
template: '<div el="test" id="test"></div>'
template: '<div v-el="test" id="test"></div>'
})
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: '<div v-if="ok" el="test" id="test"></div>'
})
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,