vue从使用到源码实现教程详解


Posted in Javascript onSeptember 19, 2016

搭建环境

项目github地址

项目中涉及了json-server模拟get请求,用了vue-router;

关于Vue生命周期以及vue-router钩子函数详解

生命周期

1.0版本

1.哪些生命周期接口

init
Created
beforeCompile
Compiled
Ready
Attatched
Detached
beforeDestory
destoryed

2.执行顺序

1. 不具有keep-alive

进入:

init->create->beforeCompile->complied->attatched->ready

移出:

beforeDestory->detached->destoryed;

2. 具有keep-alive

第一次的时候

进入:

init->create->beforeCompile->complied->attatched->ready

移出:

detached;

之后的每次

进入:

attatched

移出:

detached

钩子函数

3.钩子函数有哪些

data
activete
deactivate
canactivate
candeactivate

4.执行顺序

进入:

canactivate->actiavte->date

移出:

candeactivate->deactiavte

两者一起出现

5.对于一个组件A里面有子组件B,当这个组件A进行移入和移出操作时,组件之间的生命周期喝钩子函数的执行顺序参考如下:

例如

A.vue

<div>
<B></B>
</div>

备注:下面括号里的是嵌套的子组件

1. 不具有keep-alive:

移入:

1. canActivate;
2. init;
3. create;
4. beforeCompile;
5. (嵌套子组件:init,create,beforeCompile,compile);
6. compile;
7. activate;
8. data;
9. attached;
10. (子组件attached);
11. (子组件ready);
12. ready;

移出:

13. canDeactivate;
14. deactivate;
15. beforeDestroy;
16. (子组件beforeDestroy);
17. (子组件destoryed);
18. detached;
19. (子组件detached);
20. destoryed;

2. 具有keep-alive:

移入:

1. canActivate;
2. activate;
3. data;
4. attached;
5. (子组件attached);

移出:

6. canDeactivate;
7. deactivate;
8. detached;
9. (子组件detached);

6.钩子函数activate和data的执行顺序

涉及钩子函数异步 resolve 规则:

1.如果钩子返回一个 Promise,则钩子何时 resolve 取决于该 Promise 何时 resolve。

2.如果钩子既不返回 Promise,也没有任何参数,则该钩子将被同步 resolve。

3.如果钩子不返回 Promise,但是有一个参数(transition),则钩子会等到transition.next(),transition.abort()或是transition.redirect()之一被调用才 resolve。

4.在验证类的钩子,比如canActivate,canDeactivate以及全局 beforeEach 钩子中,如果返回值是一个布尔值 (Boolean),也会使得钩子同步 resolve。

vue从使用到源码实现教程详解 
vue从使用到源码实现教程详解 
vue从使用到源码实现教程详解

7.根据什么可以确保界面已经更新完成,也就是说挂在完成

执行生命周期attached说明已挂载

双向绑定与渲染机制

1.数据的监听和触发(订阅和发布observer)

src目录下observer:

1. array.js

2. dep.js;(实现一个发布订阅对象)

3. index.js;(利用Object.defineProperty这个API,并为此属性设计一个特殊的 getter/setter,然后在 setter 里触发一个函数,达到监听的效果);

下面是这部分的源码

Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
}
if (isArray(value)) {
for (var e, i = 0, l = value.length; i < l; i++) {
e = value[i]
e && e.__ob__ && e.__ob__.dep.depend()
}
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val
if (newVal === value) {
return
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = observe(newVal)
dep.notify()
}
})

简化上面的监听与触发代码如下:

function notidy(obj,key){
console.log(key+" has changed");
console.log(key+" now is: "+obj[key]);
}
function ToData(key,val){
var ob=this;
Object.defineProperty(ob,key,{
enumerable:true,
configurable:true,
get:function(){
return val;
},
set:function(newval){
if(newval==val){
return;
}
val=newval;
notidy(this,key);
}
})
}

src目录下directive.js

在directive中可以看到一系列解析出来的属性,而directive的实例化可以在utils/lifecycle.js中看到。

下面这段代码在Directive.prototype._bind中

var watcher = this._watcher = new Watcher(
this.vm,
this.expression,
this._update, // callback
{
filters: this.filters,
twoWay: this.twoWay,
deep: this.deep,
preProcess: preProcess,
postProcess: postProcess,
scope: this._scope
}
)
// v-model with inital inline value need to sync back to
// model instead of update to DOM on init. They would
// set the afterBind hook to indicate that.
if (this.afterBind) {
this.afterBind()
} else if (this.update) {
this.update(watcher.value)
}
Directive.prototype.set = function (value) {
/* istanbul ignore else */
if (this.twoWay) {
this._withLock(function () {
this._watcher.set(value)
})
} else if (process.env.NODE_ENV !== 'production') {
warn(
'Directive.set() can only be used inside twoWay' +
'directives.'
)
}
}

src目录下Watch.js:

从下面的代码可以找到watcher对象通过addDep方法实现订阅

Watcher.prototype.addDep = function (dep) {
var id = dep.id
if (!this.newDepIds.has(id)) {
this.newDepIds.add(id)
this.newDeps.push(dep)
if (!this.depIds.has(id)) {
dep.addSub(this)
}
}
}

2.前面说那么多关于双向绑定,其实这也是VUE内部的渲染机制,总结如下

1. 通过 observer 对 data 进行了监听,并且提供订阅某个数据项的变化的能力

2. 把 template 解析成一段 document fragment,然后解析其中的 directive,得到每一个 directive 所依赖的数据项及其更新方法。比如 v-text="message" 被解析之后 (这里仅作示意,实际程序逻辑会更严谨而复杂):所依赖的数据项this.$data.message,以及相应的视图更新方法 node.textContent = this.$data.message

3. 通过 watcher 把上述两部分结合起来,即把 directive 中的数据依赖订阅在对应数据的 observer 上,这样当数据变化的时候,就会触发 observer,进而触发相关依赖对应的视图更新方法,最后达到模板原本的关联效果。

3.vue是如何改进了v-for具有相同数据渲染出错的?

数组的渲染

未使用track-by的数组渲染内部缓存的默认id是数组的值value,意味着如果数组中存在相同的值,通过id获取的是相同的一个fragement片段,最后通过insertBefore操作DOM由于是相同的一个实例,故不会生效。

<div>
<ul id='test'>
<li id="child1">child1</li>
<li id="child">child2</li>
</ul>
</div>
<script>
_element1=document.getElementById('child1');
_element2=document.getElementById('child2');
document.getElementById('test').insertBefore(_element1,_element2);
</script>

渲染的结果是child2在child1前面

使用track-by目的是自定义这个内部的id,使得数组中具有相同的值的几项都不会选择到相同的实例,对于使用track-by='$index'还是其他唯一区分的id值有一定的区别,各有好处。

使用$index使得反转的数据没有移动操作,而对于使用其他的id在顺序不一样的时候会有相应的移动操作。

对象的渲染

对象一般使用键作为内部缓存对象的id,通过track-by也可以自定义这个id提高性能。

vm.model = {
a: { id: 1, val: "model1"},
b: { id: 2, val: "model2"},
c: { id: 3, val: "model2"},
}

列表更新

vm.model = {
d: { id: 1, val: "model1"},
e: { id: 2, val: "model2"},
f: { id: 3, val: "model2"}
}

以上所述是小编给大家介绍的vue从使用到源码实现教程详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
formvalidator验证插件中有关ajax验证问题
Jan 04 Javascript
jquery获取特定name所有选中的checkbox,支持IE9标准模式
Mar 18 Javascript
js 弹出框只弹一次(二次修改之后的)
Nov 26 Javascript
jQuery插件分享之分页插件jqPagination
Jun 06 Javascript
js交换排序 冒泡排序算法(Javascript版)
Oct 04 Javascript
js实现的黑背景灰色二级导航菜单效果代码
Aug 24 Javascript
JS+Canvas绘制时钟效果
Aug 20 Javascript
javascript 中的console.log和弹出窗口alert
Aug 30 Javascript
flexslider.js实现移动端轮播
Feb 05 Javascript
Vue2.0使用过程常见的一些问题总结学习
Apr 10 Javascript
JavaScript选取(picking)和反选(rejecting)对象的属性方法
Aug 16 Javascript
在vue中根据光标的显示与消失实现下拉列表
Sep 29 Javascript
浅谈js内置对象Math的属性和方法(推荐)
Sep 19 #Javascript
jquery事件绑定解绑机制源码解析
Sep 19 #Javascript
JavaScript学习笔记整理_setTimeout的应用
Sep 19 #Javascript
Node.js + Redis Sorted Set实现任务队列
Sep 19 #Javascript
JavaScript学习笔记整理_用于模式匹配的String方法
Sep 19 #Javascript
JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用
Sep 19 #Javascript
JavaScript学习笔记整理_关于表达式和语句
Sep 19 #Javascript
You might like
php 保留小数点
2009/04/21 PHP
Yii使用find findAll查找出指定字段的实现方法
2014/09/05 PHP
PHP简单获取视频预览图的方法
2015/03/12 PHP
php实现网页缓存的工具类分享
2015/07/14 PHP
php实现Session存储到Redis
2015/11/11 PHP
PHP 5.6.11 访问SQL Server2008R2的几种情况详解
2016/08/08 PHP
几行代码轻松实现PHP文件打包下载zip
2017/03/01 PHP
纯js实现瀑布流展现照片(自动适应窗口大小)
2013/04/08 Javascript
jQuery表单验证功能实例
2015/08/28 Javascript
BootStrap框架中的data-[ ]自定义属性理解(推荐)
2017/02/14 Javascript
原生javascript实现分页效果
2017/04/21 Javascript
使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)
2018/10/23 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
JavaScript前后端JSON使用方法教程
2020/11/23 Javascript
手写Vue源码之数据劫持示例详解
2021/01/04 Vue.js
jQuery实现穿梭框效果
2021/01/19 jQuery
Python聚类算法之DBSACN实例分析
2015/11/20 Python
深入解析Python编程中super关键字的用法
2016/06/24 Python
详解Python进程间通信之命名管道
2017/08/28 Python
用Python写王者荣耀刷金币脚本
2017/12/21 Python
Python中asyncio与aiohttp入门教程
2018/10/16 Python
详解python之heapq模块及排序操作
2019/04/04 Python
解决Django生产环境无法加载静态文件问题的解决
2019/04/23 Python
详解Python Matplotlib解决绘图X轴值不按数组排序问题
2019/08/05 Python
Python Matplotlib绘图基础知识代码解析
2020/08/31 Python
Python实现邮件发送的详细设置方法(遇到问题)
2021/01/18 Python
解决Pycharm 运行后没有输出的问题
2021/02/05 Python
移动端适配 使px自动转换rem
2019/08/26 HTML / CSS
使用html2canvas实现将html内容写入到canvas中生成图片
2020/01/03 HTML / CSS
Ann Taylor官方网站:美国最大的女性产品制造商之一
2016/09/14 全球购物
苏宁红孩子母婴商城:redbaby
2017/02/12 全球购物
产品生产计划书
2014/05/07 职场文书
副处级干部考察材料
2014/05/17 职场文书
2015年度保密工作总结
2015/04/24 职场文书
化妆品促销活动总结
2015/05/07 职场文书
Python各协议下socket黏包问题原理
2022/04/12 Python