08 支持指令2
xwjie opened this issue · 0 comments
xwjie commented
这里的实现和vue不太一样
修改生成的渲染函数的value为表达式
生成渲染函数的时候,使指令的value改成一个表达式(如 value:(count>1)
),指令的update回调函数
里面,就可以直接拿到指令的value
来计算。
需要注意没有表达式的场景(就是没有=,如 x-red
指令)的场景。这个时候直接赋值一个true即可。
D:\OutPut\VUE\VueStudyNote\Xiao\src\compiler\ast2render.js
/**
* 解析指令
* @param {*} node
*/
function getDirectiveStr(node: any) {
let dirs = node.directives
let str = '';
if (dirs && dirs.length > 0) {
str += 'directives:['
// why not use for..in, see eslint `no-restricted-syntax`
dirs.forEach(dir => {
str += '{'
for (let key in dir) {
str += JSON.stringify(key) + ':'
const val = dir[key]
// 把value的值修改为表达式,render的时候就可以计算
if (key == 'value') {
// 如果有value(表达式)
if (val) {
str += `(${val}),`
}
else {
str += 'true,'
}
} else {
str += JSON.stringify(val) + ','
}
}
str += '},'
})
str += '],'
}
return str;
}
最终生成的render函数
注意value为 "value":(see)
和"value":(count>1)
,这样直接 snabbdom.h
函数之后,函数返回的虚拟节点上的 value
就是计算后的值。
(function() {
with(this){return
h("div",{attrs:{},},[h("h1",{attrs:{},},["show指令",]),
h("div",{attrs:{},directives:[{"name":"x-show","rawName":"x-show","value":(see),"arg":null,"modifiers":undefined,},],},["当see不为false的时候,这个元素会显示",]),
h("h1",{attrs:{},},["show指令 count大于1",]),
h("div",{attrs:{},directives:[{"name":"x-show","rawName":"x-show","value":(count>1),"arg":null,"modifiers":undefined,},],},["当see不为false的时候,这个元素会显示",]),])}
})
当有指令的时候,设置实例到虚拟节点的context
上
D:\OutPut\VUE\VueStudyNote\Xiao\src\lifecycle.js
/**
* [递归设置] 如果当前节点有指令,增设置context到当前节点
* 注意: vue不是这样实现的,vue只有根节点有context
* @param {*} vnode
* @param {*} vm
*/
function setContext(vnode: any, vm: Xiao) {
// 如果当前节点有指令,设置context
if (!vnode.context) {
if (vnode.data && vnode.data.directives) {
vnode.context = vm
}
}
if (vnode.children) {
vnode.children.forEach(function (e) {
setContext(e, vm)
}, this)
}
}
默认的show指令
Xiao.directive('show', function (el, binding) {
const originalDisplay = el.__vOriginalDisplay =
el.style.display === 'none' ? '' : el.style.display
el.style.display = binding.value ? originalDisplay : 'none'
})