Vue在处理指令时,会首先判断指令是新的还是旧的。也就是需要对比旧节点和新节点上的指令。比如新节点比旧节点上多了一个指令。
// 新节点上指令如下
newDirectives = {
'v-test': {
name: 'test',
rawName: 'v-test',
},
'v-test2': {
name: 'test2',
rawName: 'v-test2'
}
}
// 旧节点上指令如下
newDirectives = {
'v-test': {
name: 'test',
rawName: 'v-test',
}
}
可以看到新节点上增加了一个指令v-test2
, 当我们遍历发现v-test2
不存在与旧节点指令中是,表明v-test2
是新指令,需要被初始化。
// 伪代码如下
for (let i in newDirectives) {
var dir = newDirectives[i];
if (!oldDirectives[i]) {
// 如果不存在与旧指令中,那新指令就要执行bind方法来初始化
dir.bind()
}
}
指令另外一个钩子是inserted
, 这个钩子会在节点插入父节点时调用,所有节点指令的inserted钩子会在同一时间处理,并不是插入一个节点,就执行一个节点的inserted
钩子。inserted
分为保存和执行两个步骤,因为需要在节点插入之后才执行,而处理inserted
是在节点插入之前,所以只能先保存起来,用于后面执行。
// 1、使用一个dirInserted数组 保存 本 DOM 的 所有新指令的 inserted 钩子
var dirInserted = []
for(i in newDir){
var dir = newDir[i]
if( !oldDir[i]){
dir.bind(....参数)
dirInserted.push(dir.inserted)
}
}
// 2、新建一个函数,专门遍历这个数组,逐个执行 inserted 钩子
var callback = function(){
for(var i=0;i=dirInserted.length;i++){
dirInserted[i](....参数)
}
}
// 3、 把 callback 保存进当前节点的一个地方,为了后面使用
dom.insert = callback
// 4、把 所有含有 callback 的节点,也放到一个数组
var insertedVnodeQueue=[]
if( 存在inserted 的 dom ){
insertedVnodeQueue.push( dom )
}
// 5、当节点插入后,开始遍历insertedVnodeQueue
for (var i = 0; i <insertedVnodeQueue.length; ++i) {
insertedVnodeQueue[i].insert();
}
对于上面例子中的v-test
,它之前就存在于旧的节点指令集合中,需要更新
for (let i in newDir) {
var dir = newDir[i];
if (!oldDir[i]) {
dir.bind(参数);
} else {
// 如果是旧指令,那就需要调用update方法
dir.update(...参数);
}
}
componentUpdated
的保存方式和inserted
差不多,但是执行方式却不一样,这个钩子,更新一个节点,就马上执行该节点的钩子。
unbind
,当某个指令只存在于旧节点中,新节点中被移除时,会调用unbind
方法。