Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

15 实现if/else指令 #17

Open
xwjie opened this issue Jan 18, 2018 · 0 comments
Open

15 实现if/else指令 #17

xwjie opened this issue Jan 18, 2018 · 0 comments

Comments

@xwjie
Copy link
Owner

xwjie commented Jan 18, 2018

测试代码

<!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
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant