[Vue源码解析] 代码生成器

14 篇文章 0 订阅

[Vue源码解析] 代码生成器

代码生成器:将AST节点转换为代码字符串,代码字符串就是我们交给渲染函数的内容。

代码字符串中具有生成VNode的方法,我们先罗列出这三种方法:

1、createElement,创建元素VNode,别名_c,参数1:tag名称,参数2:包含属性的对象,参数三:子节点列表

2、createTextVNode, 创建文本VNode,别名_v,参数:文本

3、createEmptyVNode, 创建注释VNode,别名_e,参数:文本

假如有一个模版为:

<div id="el">
  <div>
    <p>
      Hello {{name}}
    </p>
  </div>
</div>

先将其解析为AST树(由于太长就不写了),然后通过代码生成器将其根节点生成代码字符串:

with (this) {
  return _c(
  	'div',
    {attrs:{"id":"el"}},
    [_c(['div',[_c('p',[_v("Hello"+_s(name))])]])]
  )
}

然后就可以将它交给渲染函数生成VNode了

代码生成器的原理:

生成元素节点代码字符串:

/**
 * 生成元素节点代码字符串
 */

function genElement (el, state) {
  //如果el.plain是true,则说明该节点没有属性
  const data = el.plain ? undefined : genData(el, state)

  const children = genChildren(el, state)
  code = `_c('${el.tag}'${
    data ? `,${data}` : ''
  }${
    children ? `,${children}` : ''
  })`
}

生成data:

//生成data

function genData (el:ASTElement, state: CodegenState): string {
  let data = '{'
  if (el.key) {
    data += `key:${el.key}`
  }
  if (el.ref) {
    data += `key:${el.ref}`
  }
  //。。。。。。el的属性还有很多种情况
  data = data.replace(/,$/,'') + '}'
  return data
}

生成子节点列表字符串

//生成子节点列表字符串

function genChildren (el, state) {
  const children = el.children
  if (children.length) {
    return `[${children.map(c => genNode(c,state)).join(',')}]`
  }
}

function genNode (node, state) {
  if (node.type === 1) {
    return genElement(node, state)
  } if (node.type === 3 && node.isComment) {
    return genComment(node)
  } else {
    return genNode(node)
  }
}

生成文本节点代码字符串:

/**
 * 生成文本节点代码字符串
 */

function genText (text) {
  return `_v($(text.type === 2
    ? text.expression
    : JSON.stringify(text.text)   //
    ))`
}

注释节点代码字符串:

/**
 * 注释节点代码字符串
 */

function genComment (comment) {
  return `_e(${JSON.stringify(comment.text)})`
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值