Vue2.0 源码解析 003 之入门 AST 语法树转换为render函数

const defautTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
function genProps(attrs) {
  //属性处理 将属性的键值拼接成字符串
  let str = "";
  for (let i = 0; i < attrs.length; i++) {
    let attr = attrs[i];
    if (attr.name == "style") {
      //如果属性的名称是style 那么可能会有多个键值 如 style="{color:red;background:green}"
      let obj = {};
      attr.value.split(";").forEach((item) => {
        let [key, value] = item.split(":");
        obj[key] = value;
      });
      attr.value = obj;
    }
    str += `${attr.name}:${JSON.stringify(attr.value)},`;
  }
  return `{${str.slice(0, -1)}}`;
}
function genChildren(el) {
  const children = el.children;
  console.log("children", children);
  if (children) {
    return children.map((child) => gen(child)).join(",");
  }
}
function gen(node) {
  console.log("node", node);
  if (node.type == 1) {
    return generate(node);//如果是元素节点,递归处理
  } else {
    // 文本  逻辑  不能用 _c 处理
    // 有{{}}普通文本   混合文本 {{aa}}  aa{{bbb}} cccss
    let text = node.text;
    if (defautTagRE.test(text)) {//由于索引后移动
      let tokens = [];
      let match;
      let index = 0;
      let lastIndex = (defautTagRE.lastIndex = 0);//将索引重置为0

      while ((match = defautTagRE.exec(text))) {
        index = match.index;
        if (index > lastIndex) {
          //匹配到的正则的索引
          tokens.push(JSON.stringify(text.slice(lastIndex, index)));
        }
        tokens.push(`_s(${match[1].trim()})`);
        // 索引往后移
        lastIndex = index + match[0].length;
      }
      if (lastIndex < text.length) {
        tokens.push(JSON.stringify(text.slice(lastIndex, index)));
      }
      return `_v(${tokens.join("+")})`;
      //是带有{{}} 的
    } else {
      return `_v(${JSON.stringify(text)})`;
    }
  }
}
export function generate(el) {
  console.log(el); //转换成 render代码
  let children = genChildren(el);
  console.log(children);
  let code = `_c('${el.tag}',${
    el.attrs.length ? genProps(el.attrs) : "undefined"
  }${children ? "," + children : ""})`;
  return code;
}
export function compileToFunctions(template) {
  console.log("tmplate", template);
  let ast = parseHTML(template);
  //   每解析一块就删除一块
  console.log("ast", ast);
  let code = generate(ast);
  console.log("code000", code);
  
  let render = new Function(`with(this){return ${code}}`);
  console.log(render);
  return render;//render函数  已经ok
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值