模板编译。

1.模板引擎 (性能差 )需要正则匹配替换 1.0的时候没有引入虚拟Dom的改变

2.采用虚拟DOm ,数据变化后比较虚拟dom差异,最后更新需要更新的地方

3.核心就是我们需要将,模板变成我们的js语法,通过js语法去生成虚拟dom

从一个东西,变成另一个东西 语法之间的转化 es6-> es5

从css压缩 我们需要先变成语法树在重新组装代码成为新的语法,将template语法转换成render函数

模板:

<body>
    <div id="app">
        <div>
            {{name}}
        </div>
        <span>{{age}}</span>
    </div>
    <script src="vue.js"></script>
    <script>
        //响应式的数据,数据变化了我可以监控数据
        const vm = new Vue({
            //代理数据
            data: {
                name: 'bozi',
                age: 18,
                adress: {
                    number: 30,
                    content: '西安'
                },
                hobby: ['eat', 'drink', { a: 1 }]
            },
            template: `<div>hello</div>`

            // el:'#app', //我们要将数据 解析到el元素上
        });
        vm.$mount('#app')

 手动实现挂载,并先进行查找有没有render函数,没有render看一下是否写了template,没写template采用外部的template,判断有没有模板

export function initMixin (Vue) {//给vue上增加init方法
    Vue.prototype._init = function (options) {//用于初始化操作

        const vm = this
        vm.$options = options

        //初始化状态
        initstate(vm)
        if (options.el) {
            vm.$mount(options.el);//实现数据的挂载
        }
    }
    Vue.prototype.$mount = function (el) {
        const vm = this;
       el= document.querySelector(el);
        let ops = vm.$options
        if (!ops.render) {//先进行查找有没有render函数
            let template;//没有render看一下是否写了template,
                          //没写template采用外部的template
            if (!ops.template && el) {//没有模板 但是写了el
              template = el.outerHTML
            } else {
                if (el) {
                    template = ops.template
                }
            }
            console.log(template);
            //写了template 就用 写了template   
            // console.log(template);
            if(template) {
                //有模板就需要进行编译
                const render = compileToFunction(template);
                ops.render = render //jx 最终会被编译成h('XXX')
            }
        }
        ops.render ;//最终就可以获取render方法


        //script 标签引用的vue.global.js 这个编译过程是在浏览器运行的
        //runtime是不包含编译的,整个编译是打包的时候通过loader来转义.vue文件的runtime的时候不能使用tempate
    }

 对模板进行编译处理

const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const starTagOpen = new RegExp(`^<${qnameCapture}`); //他匹配到的分组是一个标签名 <xxx 匹配到的是开始 标签的名字

const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*`); //他匹配到的是 </xxx  最终匹配到的是结束标签的名字

const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>']+)))?/; //匹配属性
//第一个分组就是属性key value 就是 分组3/分组4/分组5
const starTagClose = /^\s*(\/?)>/;

const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g //{{asdsads}} //匹配到的内容就是我们表达式的变量
//vue3采用的不是正则
//对模板进行编译处理
function parseHTML (html) {
    function start(tag,attrs) {
        console.log(tag,attrs,'开始');
    }
    function chars(text) {
        console.log(text,'文本');
    }
    function end(tag) {
        console.log(tag,'结束');
    }
    function advnce (n) {
        html.substring(n);
    }
    function parseStarTag () {
        const start = html.match(starTagOpen);
        if (start) {
            const match = {
                tagName: start[1],//标签名
                attr: []
            }
            advnce(start[0].length);
            let attr, end
            while (!(end = html.match(starTagClose)) && (attr = html.match(attribute))) {
                advnce(attr[0].length)
                match.attrs.push({ name: attr[1], value: attr[3] || attr[4] || attr[5] })
            }
            if (end) {
                advnce(end[0].length)
            }
            return match
        }
        return false; //不是开始标签
    }
    while (html) {//zhtml最开始是一个<di>hello</div>
        //如果textend为0说明是一个开始标签或者结束标签
        //如果textend > 0 说明就是文本结束的位置
        let textEnd = html.indexOf('<'); //如果indexof中的索引是0,则说明是个标签
        if ( textEnd== 0) {
            const startTagMatch = parseStarTag();//开始标签的结果
            start(startTagMatch,tagName,startTagMatch.attrs)
            if (startTagMatch) {//解析到的开始标签
                continue
            }
            let endTagMatch = html.match(endTag);
            if (endTagMatch) {
                advnce(endTagMatch[0].length);
                end(endTagMatch[1])
                continue
            }
            html.match(endTag)
        }
        if (textEnd >0) {
            let text = html.substring(0, textEnd);//文本内容
            if (text) {
                advnce(text.length);//解析到的文本
                chars()
            }
        }
    }
    console.log(html);
}
export function compileToFunction (template) {
    //1.就是将template 转化成ast语法树
    let ast = parseHTML(template);
    //2.生成render方法,(render)方法执行后的返回结果就是 虚拟dom 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值