美文网首页
vue对模板的编译

vue对模板的编译

作者: 冷暖自知_zjz | 来源:发表于2021-04-25 10:51 被阅读0次

vue的编译是什么

编译是把我们写的.vue文件里的template标签包含的html标签变为render函数,可以这么理解template模板是对render的封装,template在vue源码里面会变转化为render函数

// 在传入的选项对象中判断有没有render函数,没有的话就获取template模板最后通过compileToFunctions编译为render函数
if (!options.render) {
    let template = options.template
    if (template) {
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          template = idToTemplate(template)
        }
      } else if (template.nodeType) {
        template = template.innerHTML
      } else {
        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }
    if (template) {
      const { render, staticRenderFns } = compileToFunctions(template, {
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns
    }
}    

那么compileToFunctions函数里面到底做了什么,为什么能把template模板转化为render函数

// 核心代码是把tempalte转化为ast语法树,在把转化出来的ast语法树做一个静态标记(optimize),最后转化为code
export const createCompiler = createCompilerCreator(function baseCompile (
  template: string,
  options: CompilerOptions
): CompiledResult {
  const ast = parse(template.trim(), options)
  if (options.optimize !== false) {
    optimize(ast, options)
  }
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})

template如何转化为ast呢,一个普通的标签的形式为 <div class="item" v-if="flag">zs</div>,在转化为ast的时候通过正则和一个栈结构,把标签名 div 类型 children分离出来转化后的ast大概的样子为

ast = {
  'type': 1,
  'tag': 'div',
  'attrsList': [],
  'attrsMap': {
    'class': 'item',
    'v-if': 'flag'
  },
  'parent': undefined,
  'children': [{
    'type': 2,
    'text':zs
    }
    ]
  }]
}

optimize(ast, options)做的事是吧ast的这个js对象做静态标记,在标签上有vue的指令的使用到组件的data里面的数据可能会相应的都为动态的,所谓的静态是在新老两颗虚拟dom数做比较的时候可以不用比较,他是不会改变的,静态化后的ast样子为

 
 ast = {
  'type': 1,
  'tag': 'div',
  'attrsList': [],
  'attrsMap': {
    'class': 'item',
    'v-if': 'flag'
  },
  'parent': undefined,
  'static': false,
  'children': [{
    'type': 2,
    'text':zs,
    'static': false
    }
    ]
  }]
}

最后一步执行 const code = generate(ast, options)

export function generate (
  ast: ASTElement | void,
  options: CompilerOptions
): CodegenResult {
  const state = new CodegenState(options)
  const code = ast ? genElement(ast, state) : '_c("div")'
  return {
    render: `with(this){return ${code}}`,//这就是最后生成的render函数
    staticRenderFns: state.staticRenderFns
  }
}
_c('div', {
    staticClass: "item"
    },
    [_v("zs")]
)

相关文章

网友评论

      本文标题:vue对模板的编译

      本文链接:https://www.haomeiwen.com/subject/pncdrltx.html