vue简单实现原理(二)

本文详细解析Vue的模板编译过程,包括如何使用compileToFunction将模板转换为函数,生成AST树,以及generate函数如何生成函数字符串。同时介绍了mountComponent方法的实现,包括render和_update方法在组件挂载中的作用,以及数据初始化和DOM更新的流程。
摘要由CSDN通过智能技术生成

模板编译

  • 渲染模板的时候需要一个方法用数据代替模板中的变量(方法:render)
  1. 先把模板变成一个render方法 reder(){return _l(3,_c(‘li’,name))}
  2. 需要去当前实例上取值 width
  3. 虚拟dom对象=》可描述dom结构 (diff算法)
  4. 生成真实dom扔到页面中

  1. 模板编译原理,AST语法树,先表示出html来=>js语法
  • 先看实例化的时候有没有el选项,如果有就直接挂载,挂载的时候需要一个方法mount
Vue.prototype.$mount = function (el){
   
    el = document.getElementById(el),
    const vm = this
    const options = vm.$options
    vm.$options.el = el // 将el挂到$options上备用
    // 如果有render 就直接使用 render
    // 没有render看有没有template属性
    // 没有template就直接找外部模板
    if(!options.render){
   
        let template = options.template
        if(!template && el){
   
            template = el.outerHTML
        }
        // 如何将模板编译成函数
        const render = compileToFunction(template)
        options.render = render
    }
}

接下来实现compileToFunction方法,用来将模板变成函数

1. vue中会通过一些正则表达式匹配template中的字符串
```js
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
```
function createASTElement(tag,attrs){
   
    return {
   
        tag,
        type:1,
        children:[],
        attrs,
        parent:null
    }
}
let root = null;
let currentParent
let stack = []
function parseHTML(html){
   
    // 根据开始标签结束标签文本,生成一个ast语法树

    function start(targName,attrs){
   
        let element = createASTElement(targName,attrs)
        if(!root){
   
            root = element
        }
        currentParent = element
        stack.push(element)
    }
    function end(tagName){
   
        element = stack.pop()
        currentParent = stack[stack.length-1]
        if(currentParent){
   
            element.parent = currentParent
            currentParent.children.push(element)
        }
        

    }
    function chars(text){
   
        text = text.replace(/\s/g,'');
        currentParent.children.push({
   
            type:3,
            text,
        })
    }
    // 删掉已经匹配到的长度的字符并赋值为新的字符串
    function advance(len){
   
        html = html.substring(len)
    }
    function parseStartTag(){
   
        const start = html.match(startTagOpen)
        if(start){
   
            let match = {
   
                tagName:start[0],
                attrs:[]
            }
            advance(start[0].length)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值