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 )(代码片段