15 实现if/else指令
xwjie opened this issue · comments
测试代码
<!DOCTYPE html>
<html>
<head>
<title>Xiao框架之helloworld</title>
<script src="../dist/xiao.js"></script>
</head>
<body>
<h1>if, else指令测试</h1>
<div id="demo1">
<h1 x-if="ok">Yes</h1>
<h1 x-else>No</h1>
<h1 x-if="ok">只有if</h1>
</div>
<script>
var app = new Xiao({
data:{
ok:true
}
});
app.$mount("#demo1");
setTimeout(function(){
app.ok = false;
}, 2000);
</script>
</body>
</html>
实现
if指令和show指令不一样,我们最终需要把渲染函数修改为类似这样的?三元表达式。注意:这里不用用if-else,必须用?表达式。
要注意处理只有if没有else的场景。
(function() {
with(this){return h("div",{props:{"id":"demo1",},},
[(ok)?h("h1",{props:{"x-if":"ok",},directives:[],},["Yes"]):h("h1",{props:{"x-else":"",},directives:[],},["No"]),
(ok)?h("h1",{props:{"x-if":"ok",},directives:[],},["只有if"]):"",])}
})
修改render生成函数
function createRenderStrElemnet(node: any): string {
log('createRenderStrElemnet', node)
// snabbdom 的语法,类名放在tag上。'div#container.two.classes'
let tag = getTagAndClassName(node)
let str: string = `h(${tag},{`
// 解析属性
str += genAttrStr(node)
// 解析指令
str += getDirectiveStr(node)
str += "}"
if (node.children) {
str += ',['
// 保存上一次if指令,处理只有if没有else的场景
let lastDir
node.children.forEach(child => {
// 如果这里节点有if指令
let dir = getIfElseDirective(child)
console.log('dir:', dir)
if (dir) {
if (dir.name == 'if') {
str += `(${dir.exp})?`
lastDir = dir
} else if (dir.name == 'else') {
str += `:`
}
}
str += createRenderStr(child)
if (dir) {
if (dir.name == 'else') {
str += `,`
lastDir = null
}
}
else if (lastDir) {
str += `:"",`
lastDir = null
}
})
if (lastDir) {
str += `:"",`
}
str += ']'
}
str += ')'
return str
}
/**
* 得到该节点的if/else指令
* @param {*} node
*/
function getIfElseDirective(node: any): ?Object {
let attrs = node.attrsMap
if (!attrs) {
return
}
let dir
// why not use for..in, see eslint `no-restricted-syntax`
Object.keys(attrs).some(attrname => {
// 如果是数据绑定,则后面的是表达式
if (attrname == 'x-if') {
dir = {
name: 'if',
exp: attrs[attrname].trim()
}
return true
} else if (attrname == 'x-else') {
dir = {
name: 'else'
}
return true
}
return false
})
return dir
}