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

08 支持指令2 #10

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

08 支持指令2 #10

xwjie opened this issue Jan 13, 2018 · 0 comments

Comments

@xwjie
Copy link
Owner

xwjie commented Jan 13, 2018

这里的实现和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'
  })
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