vue实现流程整理

栏目: JavaScript · 发布时间: 7年前

内容简介:本文通过一个示例,描述了vue的编译及运行过程。例子:如果是使用vue的compiler+runtime版本,首先在mount之前会有一个编译流程,会通过new Vue时传入的el或者template里面的元素编译为一个render函数。该步骤主要思路是将template视为一个字符串,通过正则表达式不断匹配tag和attr等,parse生成AST树,之后再将优化后转化为render函数。Vue._init => Vue.$mount => compileToFunctions => compile

本文通过一个示例,描述了vue的编译及运行过程。例子:

<div id="app">
    {{ message }}
    <input type="text" v-model="message"/>
    <ul>
        <li v-for="item in list">{{ item }}</li>
    </ul>
    <div @click="onClick">
        点击
    </div>
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!',
            list: [1, 2, 3]
        },
        methods: {
            onClick () {
                this.list.push(2);
            }
        }
    })
</script>

编译

如果是使用vue的compiler+runtime版本,首先在mount之前会有一个编译流程,会通过new Vue时传入的el或者template里面的元素编译为一个render函数。该步骤主要思路是将template视为一个字符串,通过正则表达式不断匹配tag和attr等,parse生成AST树,之后再将优化后转化为render函数。

Vue._init => Vue.$mount => compileToFunctions => compile

vue实现流程整理

最终生成的render函数如下:

with(this){return _c('div',{attrs:{"id":"app"}},[_v("\n            "+_s(message)+"\n            "),_c('input',{directives:[{name:"model",rawName:"v-model",value:(message),expression:"message"}],attrs:{"type":"text"},domProps:{"value":(message)},on:{"input":function($event){if($event.target.composing)return;message=$event.target.value}}}),_v(" "),_c('ul',_l((list),function(item){return _c('li',[_v(_s(item))])}),0),_v(" "),_c('div',{on:{"click":onClick}},[_v("\n                点击\n            ")])])}

一般来说,v-model就是:value和@input="function($event){message=$event.target.value}"的语法糖。从编译结果看,input使用v-model时多了一句$event.target.composing的判断,这句判断的主要作用是使用中文输入法还没有确定输入时,不会更新DOM,具体见 v-model指令到底做了什么

渲染

根据传入的data和render函数,生成对应的VNode Tree

vue实现流程整理

这期间会有一次依赖收集过程,且v-if为false的元素不会出现在生成的VNode Tree中。最后调用patch,因为没有oldVnode,会直接将VNode渲染为真实的DOM

update

当点击元素或者触发输入框改变时,触发派发更新,会再次调用updateComponent并重新生成新的vnode。例如点击元素,增加list长度时

vue实现流程整理

再次调用patch时,会对比新旧VNode并将差异应用到真实的DOM上。虚拟DOM

事件的实现

对于原生事件,vue使用的原生addEventListener添加事件。对于自定义事件,vue采用的是事件中心的设计模式,调用on时注册事件,调用emit时触发事件。如下

var Event = (function(){
    var listeners = {}, on, emit;
    on = function( key, fn ){ 
        if ( !listeners[ key ] ){
            listeners[ key ] = []; 
        }
        listeners[ key ].push( fn ); 
    };
    emit = function() {
        var key = Array.prototype.shift.call( arguments ),
        fns = listeners[ key ];
        if ( !fns || fns.length === 0 ){
            return false; 
        }
        for( var i = 0, fn; fn = fns[ i++ ]; ){ 
            fn.apply( this, arguments );
        }
    }
    return {
        on: on,
        emit: emit
    }
})();

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Rework

Rework

Jason Fried、David Heinemeier Hansson / Crown Business / 2010-3-9 / USD 22.00

"Jason Fried and David Hansson follow their own advice in REWORK, laying bare the surprising philosophies at the core of 37signals' success and inspiring us to put them into practice. There's no jarg......一起来看看 《Rework》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具