博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue实现原理初探
阅读量:5989 次
发布时间:2019-06-20

本文共 5171 字,大约阅读时间需要 17 分钟。

Vue是当今热门的框架,他可以进行数据双向绑定,为什么vue会大受欢迎,我知道的原因大致如下?

1.传统改变dom结构的操作是非常浪费性能的操作(就是慢)
2.把dom结构改变的逻辑放在js层来做可以提高性能。
3.数据和视图的分离更符合面向对象的编程,mvvm

vue的实现也是和react一样用虚拟dom来实现的,至于什么是虚拟dom,就是用js通过模板渲染而成的dom。

vue实现的步骤大概是这三步:

1、响应式:vue怎么监听到dota的每个属性值的变化?

2、模板引擎:vue的模板如何解析的,指令是如何处理的?
3、模板渲染:如何把data里的数据加入模板并渲染成html?

第一步:响应式

响应式的实现主要是依靠一个对象的方法:

Object.defineProperty
这个方法能够监听对象中属性的变化而进行逻辑处理
dome如下:

var obj={}    var _name ='zhangsan'    Object.defineProperty(obj,'name',{        get:function() {            console.log('get')            return _name        },        set: function(newVal) {            console.log('set')            _name=newVal        }    })

这里你改变name的值或者访问name的值就会有打印信息

而在vue中模拟实现,大概是这样的:

var vm ={}        var data={name:'张三',age:20}        var key,value;        for(key in data) {            (function(key){                Object.defineProperty(vm,key,{  //绑定到vm上                    get:function(){                        console.log('get')                        return data[key];                    },                    set:function(newVal){                        console.log('set');                        data[key]=newVal                    }                })            })(key)  //闭包处理        }

其实学过java的同学肯定对这个不陌生,java的类里面可以直接生成get和set方法

第二步:解析模板

模板必须要转化成js代码,因为:

1.逻辑判断(v-if,v-for),必须要用js才能实现.
2.虚拟dom的渲染,必须要使用js才能实现。(render函数)

  • 模板1

{

{price}}

  • 模板1转化的render
with(this) { //this就是vm                return _c(                    'div',                    {                        attrs:{'id':'app'}                    },                    [                        // _c是createElement                        // _v是createTextVNode                        // _s是toString方法                        _c('p',[_v(_s(price))])                    ]                )            }
  • 模板2
  • {
    {item}}
  • 模板2转化的render
with (this) {                return _c(                    'div',                    { attrs: { "id": "app" } },                    [                        _c(                            'div',                            [                                _c(                                    'input',                                    {                                        //指令                                        directives: [                                            {                                                name: "model",                                                rawName: "v-model",                                                value: (title),    //vm.title                                                expression: "title"                                            }                                        ],                                        domProps: {                                            "value": (title) //vm.title                                         },                                        on: {                                            "input": function ($event) {                                                if ($event.target.composing) return;                                                title = $event.target.value                                            }                                        }                                    }                                ),                                _v(" "),                                _c(                                    'button',                                    {                                        on: { "click": add }  //vm.add                                    },                                    [                                        _v("submit")                                    ]                                )                            ]                        ),                        _v(" "),                        _c(                            'div',                            [                                _c(                                    'ul',                                    _l(                                        (list), function (item) {                                            return _c(                                                'li',                                                [                                                    _v(_s(item))                                                ]                                            )                                        }                                    )                                )                            ]                        )                    ]                )            }

这就是用于渲染的render函数

第三步:把模板加上数据渲染成html

vm._update(Vnode) {    const prevVonde=vm._Vnode    vm._Vnode=Vnode;    if(!prevVnode) {  //如果没有之前的vnode,第一次渲染        vm.$el=vm._patch_(vm.$el,Vnode)    }else {        vm.$el=vm._patch_(prevVnode,Vnode)    }}function updataComponent() {    //vm._reander就是解析模板的rende函数,返回了一个vnode    vm._update(vm._render())}

这里的vm_.patch_里面就是复杂的diff算法了。根据dom的差别来渲染,里面使用来很多的递归调用,而且里面最要涉及到很多效率问题,天下武功为快不破嘛。

转载地址:http://msnlx.baihongyu.com/

你可能感兴趣的文章
ACdream 速攻组~
查看>>
《暗黑世界V1.6》服务器代码执行图
查看>>
Libgdx多线程与渲染线程
查看>>
SQL Server 对象
查看>>
超过响应缓冲区限制
查看>>
exec 临时表,报错
查看>>
CSS3 实现的一个简单的"动态主菜单" 示例[转]
查看>>
关于 IOS code signe 和 Provisioning Files 机制 浅析
查看>>
Programmer in Google Code
查看>>
后缀数组
查看>>
D的小L
查看>>
怎样使用SetTimer MFC 够具体
查看>>
兴趣决定你成为什么样的人
查看>>
你有什么资格去说自己已经很努力?
查看>>
UVA 1524 - Hot or Cold?(数学)
查看>>
[AngularJS] $scope.$warchCollection
查看>>
HDU 1426 Sudoku Killer
查看>>
关于编写性能高效的javascript事件的技术
查看>>
Android学习笔记:ListView简单应用--显示文字列表
查看>>
【转】对排序算法的深入探究
查看>>