vue源码分析

Posted wenwenli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue源码分析相关的知识,希望对你有一定的参考价值。

双向数据绑定

1. js的eventloop

micro 微队列,promise的then,async await,observer, 优先级高于宏队列。window.MutationObserver属于observer

macro 宏队列,setTimeout,setInterval, click,event事件,ajax,

    var MutationObserver = window.MutationObserver;
        var target = document.querySelector(#some-id);
        var observer = new MutationObserver(function(mutations){
            mutations.forEach(function(mutation){
                console.log(mutation.type);
            })
        })
        var config = {
            attributes: true
        };
        observer.observe(target, config);
setTimeout(function(){
            console.log(15);
        },0)
        document.querySelector(#some-id).setAttribute(data-test,6);
        new Promise(function(resolve){
            console.log(1);
            resolve();
            console.log(2);
        }).then(function(){
            console.log(9);
        });

        new Promise(function(resolve){
            console.log(3);
            resolve();
            console.log(4);
        }).then(function(){
            console.log(10);
        });

        function fn(){
            return new Promise((resolve,reject)=>{
                resolve(12);
            })
        }

        function fn1(){
            return new Promise((resolve,reject)=>{
                resolve(14);
            })
        }
        //async 是等待的,promise是顺序执行的,然后then最后执行,类似setTimeout 0,但是要比setTimeout 0先执行
        (async function(){
            console.log(5);
            console.log(await fn()); //这里的微队列将后面的代码都压入队列中,是这么理解的,或者说后面是同步的了,执行完了才执行微队列
            console.log(13);
        })();

        (async function(){
            console.log(await fn1()); //这里等待fn执行完成,才执行下一行
        })();

        //微队列是先进先出的,符合队列的规则,但是如果await 后面不是promise对象的话会有区别,会将后面的语句压入微队列中
        (async function(){
            console.log(6);
            await console.log(7); //这里这么写会有问题,打乱了微队列的队形,11是所有的await中的前面,其他异步微队列的后面
            console.log(11);
        })();

2. nextTick就是使用微队列或是宏队列来实现的dom元素的异步更新,那为什么显示的内容改变了呢

这里使用$refs获取元素的innerhtml或value值,this.$refs是vue的一个属性,并不直接对应dom结构,可以理解为虚拟dom,但是,dom的更新不是根据虚拟dom的更新来的吗,为什么显示变了,虚拟dom反而没有变呢。

也就是说vue在创建的时候会生成vdom,和watcher,当有属性变化时,对比该dom节点和虚拟dom,不同的话直接更新dom,然后在微队列中更新vdom,也就是refs的值,所以直接使用是没有的?这里需要看下virtual dom是怎么更新的,dom diff是怎么比较的

 

新版本的vue的实现原理

proxy, reflect

vdom,dom遍历慢的原因是因为dom对象的属性和方法太多了,

dom diff

比较两颗dom树的差异,两个树完全的diff算法是一个时间复杂度为o(n^3)的问题,但是当在前端当中,你很少会跨越层级的移动dom,所以virtual dom只会对统一层级的元素进行对比,这样的算法复杂度就可以达到o(n)。

节点的拆一指的是什么呢,

a。替换原来的节点,例如把div换成section

b。移动、删除、新增子节点,例如,把子节点的p和ul的顺序互换

c。修改了节点的属性

d。对于文本节点,文本内容可能会改变

最好使用key标记dom,提高效率

专业版 patch和diff  https://github.com/snabbdom/sanbbdom

简陋版的diff和patch,https://github.com/livoras/simple-virtual-dom/blob/master/lib/diff.js  ,    https://github.com/livoras/simple-virtual-dom/blob/master/lib/patch.js

双向数据绑定的库   hyperapp, kbrsh/moon

2. vuex

view 驱动actions 然后驱动state,state再驱动view

核心模块

state,

Getters:纯操作,对state里的属性进行的操作,没有传进数据,

Mutations:和外部的交互方法,用store.commit(‘name‘)调用,

Actions:可以操作Mutations,可以实现异步调用,使用dispatch调用,可以设置调用次数,还可以使用async和await

Modules(合并用的)

 

vuex-router-sync

 

https://vuex.vuejs.org/guide/plugins.html

3. vue运行时的优化

静态的优化,循环优化,ssr的输出,ssr的优化(preload,prefetch)

增加新的优化,

css的抽象原子css

Prepack

4. 路由的实现,或者说spa的实现

三种模式,我们用到的是两种hash和history,history在h5中新增加了 pushState和repalceState方法,

window.history.pushState(stateObject,title,url)
window.history,replaceState(stateObject,title,url)

2个方法有个共同的特点:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会立即发送请求该url,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础。

修改之后监听修改就可实现视图的修改,在HTML5History中添加对修改浏览器地址栏URL的监听popstate是直接在构造函数中执行的

https://segmentfault.com/a/1190000014822765

 

以上是关于vue源码分析的主要内容,如果未能解决你的问题,请参考以下文章

Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段

vue源码构建代码分析

vue3源码分析——ast生成代码 - 掘金

vue3源码分析——ast生成代码 - 掘金

vue3源码分析——ast生成代码 - 掘金

vue3源码分析——ast生成代码 - 掘金