Vue生命周期详解 对应代码解析

-使用GitHub阅览

对于Vue的实例,比如

const app = new Vue({...})

浏览器解析到这段代码的时候,自动执行beforeCreate => created => beforeMount => mounted方法,每当data的某个属性值更改了,比如==app.mes = "hi"==,自动执行beforeUpdate => updated方法。

beforeCreate:

el     : undefined
data   : undefined
message: undefined

created:

el     : undefined
data   : [object Object]
message: hi

beforeMount:

el     : [object HTMLDivElement]
<div id="app"><p>{{ message }}</p></div>
data   : [object Object]
message: hi

mounted:

el     : [object HTMLDivElement]
<div id="app"><p>hi</p></div>
data   : [object Object]
message: hi

当需要销毁这个实例的时候,需要手动执行app.$destroy()。然后Vue此时会自动调用beforeDestroy、destroyed方法。

一旦组件被销毁,它将不再响应式,即更改data的属性值,比如app.mes = "hello",页面不会同时被更新,页面上的数据任然显示的是 hi

此时需要手动调用app.$mount(),这个方法在这个时候被手动调用的时候,Vue会自动按照下面的顺序执行以下方法: beforeMount => beforeUpdate => updated => mounted。

此时,我们会发现页面变成了hello 我的理解是,虽然之前app被销毁了,但是对于mes属性的dep里面,通过监控它的watcher,仍然是变成了“hello”,但是不会调用底层的compile(this.cb)来渲染视图。而当手动调用app.$mount()的时候,它的compile方法被激活,又变成响应式的了。 当我们调用destroy方法的时候,其实调用了app._watcher的teardown方法,下面代码所示(在执行这个destroy之前,我们调用了callHook这个钩子函数):

 Vue.prototype.$destroy = function () {var vm = this;if (vm._isBeingDestroyed) {return}callHook(vm, 'beforeDestroy');if (vm._watcher) {vm._watcher.teardown();}var i = vm._watchers.length;while (i--) {vm._watchers[i].teardown();}
}

_watcher的active值被置为false,然后调用removeSub将该watcher所依赖的订阅器全都退订(从每个dep的subs数组中移除)。

Watcher.prototype.teardown = function teardown () {var this$1 = this;if (this.active) {// remove self from vm's watcher list// this is a somewhat expensive operation so we skip it// if the vm is being destroyed.if (!this.vm._isBeingDestroyed) {remove(this.vm._watchers, this);}var i = this.deps.length;while (i--) {this$1.deps[i].removeSub(this$1);}this.active = false;}
};

看到这里,我们知道,尽管被destroy,_watcher还是那个_watcher(此时,如果调用$mount,就不是了)。什么意思呢?就是说每个属性值还是被放在它们各自的watcher中被监控着的。只不过,由于这些watcher都从deps里面被退订了,那么一旦它们的值被更改,将不会调用watcher的update(因为每个watcher的update方法是在dep的notify里面被调用的)。

我们看到update被调用的时候,实际是调用了run方法,也就是说真正的update(this.cb)实在run里面被调用。

在run里面,先判断active,如果是false就不更新视图(不再响应式了)

Watcher.prototype.update = function update () {/* istanbul ignore else */if (this.lazy) {this.dirty = true;} else if (this.sync) {this.run();} else {queueWatcher(this);}
};//
Watcher.prototype.run = function run () {if (this.active) {var value = this.get();if (value !== this.value ||// Deep watchers and watchers on Object/Arrays should fire even// when the value is the same, because the value may// have mutated.isObject(value) ||this.deep) {// set new valuevar oldValue = this.value;this.value = value;/..../{this.cb.call(this.vm, value, oldValue);}}}
};

好了,当我们再次调用app.$mount(),其实我们此时是重新编译了一遍节点。此时经历了这么个过程: beforeMount => beforeUpdate => updated => mounted

查看源码,我们发现$mount方法里面调用了compileToFunctions方法,而compileToFunctions方法里面调用了compile方法,也就是说,此时我们为app.mes属性,重新new了一个Watcher。

var mount = Vue.prototype.$mount;
Vue.prototype.$mount = function (el,hydrating){//.......var ref = compileToFunctions(template, {shouldDecodeNewlines: shouldDecodeNewlines,shouldDecodeNewlinesForHref: shouldDecodeNewlinesForHref,delimiters: options.delimiters,comments: options.comments}, this);//....}
//...
function compileToFunctions(){//....var compiled = compile(template, options);//...
}

如果读者对以上分析感到疑惑,我们可以测试一下:

在调用destroy之前,我们先声明一个变量p来保持对此时的watcher对象的引用(由于jvm是根据对对象的持有,来决定是否从内存中删除此对象。所以这个旧的watcher不会被删除)

// teardown之前
p=app._watcher.deps[0].subs[0];
// teardown之后,又调用$mount()
pp = app._watcher.deps[0].subs[0];// 比较
p === pp //输出false,说明这个watcher是新new出来的

-轻松掌握-vue-实例的生命周期/

-Vue2.0 探索之路——生命周期和钩子函数的一些理解


更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366690.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

所有其他指标均无用

对于队列&#xff0c;无论是实现为JMS &#xff0c;数据库表&#xff08;即Ruby的Delayed :: Job用于队列的什么&#xff09;&#xff0c;甚至是Amazon的SQS &#xff0c;用于评估队列状态的最常见指标是其长度。 从本质上讲&#xff0c;可以基于在任何给定时间队列中驻留多少消…

类似苹果数据线的android,除了常见的安卓、苹果、Type-c,还有哪些你不知道的手机数据线?...

随着智能手机日益发展&#xff0c;辅助智能手机的数据线配件也越来越多样。现在我们最常见的无非就是标准Micro usb口、正反随便插的Type-c接口、还有苹果Lightning数据线&#xff0c;那么除了这些类型数据线&#xff0c;你知道如今市面上还有哪些更方便好用的手机数据线吗&…

团体程序设计天梯赛L3-019 代码排版(23分)

打算学完编译原理后再次实现它。。。 以下为比较“杂乱”的方法&#xff1a; 海量数据&#xff1a; https://pan.baidu.com/s/1Prd0ZqNLoCLLvXyJjCef3w 如果大家有发现这个程序的问题&#xff0c;请联系我&#xff0c;谢谢啦~~~ 我很疑惑&#xff0c;不知道错在哪里&#xff0c…

canvas入门实战--邀请卡生成与下载

1.前言 写了很多的javascript和css3的文章&#xff0c;是时候写一篇canvas的了。canvas是html5提供的一个新的功能&#xff01;至于作用&#xff0c;就是一个画布。然后画笔就是javascript。canvas的用途非常的广&#xff0c;特别是html5游戏以及数据可视化这两个方面。现在can…

javascript 数组求交集/差集/并集/过滤重复

最近在小一个小程序项目,突然发现 javscript 对数组支持不是很好,连这些基本的功能,都还要自己封装.网上查了下,再结合自己的想法,封装了一下,代码如下. //数组交集 Array.prototype.intersect function(){let mine this.concat();for (var i 0; i < arguments.length; …

Apache ActiveMQ 5.9发布

Apache ActiveMQ团队刚刚发布了新的ActiveMQ 5.9版本 。 Apache ActiveMQ 5.9发布 自从先前的5.8版本以来&#xff0c;此版本是8个月的辛苦工作。 在此发行版中&#xff0c;我们将像往常一样对代理进行增强&#xff0c;并使用最新的协议&#xff08;例如AMQP和MQTT&#xff…

android 美颜录像,Android 关于美颜/滤镜 利用PBO从OpenGL录制视频

前言上次我写了一遍文章《Android 关于美颜/滤镜 从OpenGl录制视频的一种方案》&#xff0c;里面利用ImageReader来从获取Surface上获取数据&#xff0c;但是经过熊皮皮的提醒&#xff0c;我发现多PBO的确可以实现跟ImageReader一样的效果&#xff0c;并且版本要求仅为Android4…

DAY77-Django框架(八)

今日内容&#xff1a;创建多表模型、多表数据操作、基于对象的跨表查询、基于双下划线的跨表查询 一、创建多表模型 class Author(models.Model):# id如果不写,会自动生成,名字叫nid,并且自增id models.AutoField(primary_keyTrue)name models.CharField(max_length32)sex m…

Async Await

接着上一篇Generator co的使用 https://juejin.im/post/5ab51336f265da239d493ff4 这里继续说说js异步处理的方法 async await( 即Generator的语法糖) async 是“异步”的简写&#xff0c;async 用于申明一个 function 是异步的&#xff0c;而 await 用于等待一个异步方法执行…

Java对象到对象映射器

我在该项目上使用了Dozer一段时间。 但是&#xff0c;最近我遇到了一个非常有趣的错误&#xff0c;它促使我环顾四周&#xff0c;并尝试使用其他“对象到对象”映射器。 这是我找到的工具列表&#xff1a; 推土机&#xff1a;推土机是Java Bean到Java Bean的映射器&#xff…

android媒体播放框架,Android 使用超简单的多媒体播放器JiaoZiVideoPlayer

在之前的项目中用到了视频播放的功能&#xff0c;在网上看了看使用了大家用的比较多的一个开源项目JiaoZiVideo可以迅速的实现视频播放的相关功能。JiaoZiVideo的简单使用集成了JiaoZiVideo后仅需这几行代码就可以实现播放视频JZVideoPlayerStandard jzVideoPlayerStandard (J…

送福利:ROKID 语音开发板免费送,开启你的物联网之旅

都让一让&#xff0c;我说个事情&#xff1a;掘金联合 Rokid 开发者社区给大家发福利啦&#xff01; 掘金联合 Rokid 开发者社区为大家准备了一些福利&#xff0c;只要秀出你的 skill 和技术栈&#xff0c;就有可能获得 Rokid 全栈语音智能开发套件。 ? Rokid开箱试用活动 活…

点击复制文本

点击按钮&#xff0c;进行文本复制操作。实现这个功能需要二点&#xff1b; 一&#xff1a;用window.getSelection().selectAllChildren(“”)获取要复制的内容 二&#xff1a;用document.execCommand ("Copy");进行复制操作 关键代码 window.getSelection().selec…

6.25

TEXT 94 Cancer biology 肿瘤生物学 Cramping tumours 断了肿瘤的活路&#xff08;陈继龙编译&#xff09; Jan 18th 2007 From The Economist print edition An old observation about cancer cells may lead to a new treatment 早年发现的肿瘤细胞的一个特征可能为治疗肿瘤打…

Java Lambdas简介

Java 8的主题是lambdas。 我已经注意到&#xff0c;对于许多Java程序员来说&#xff0c;lambda都是非常难的材料。 因此&#xff0c;让我们尝试对它们有一个基本的了解。 首先&#xff0c;lambda到底是什么&#xff1f; Lambda是一个匿名函数&#xff0c;与常规函数不同&#…

ios html清除缓存图片,iOS,如何清理缓存的图片

通常&#xff0c;在我们加载图片的时候&#xff0c;一般都会做缓存处理&#xff0c;像SDWebImage&#xff0c;YYWebImage都是有的&#xff0c;但是有缓存&#xff0c;当然也需要清理缓存,如果没有这个功能的话&#xff0c;显得app太没人性化。获取总的缓存大小// 获取某个路径下…

搭建一个项目的前期准备

后端&#xff1a;node(驱动) mogodb(数据库) express(node框架) mongoose(快速建模工具) moment.js(时间和日期格式化) jade(模板引擎)前端&#xff1a; jquery(类库) bootstrsop(样式框架) bower(npm模块)本地环境&#xff1a;less cssmin jshint uglifyjs mocha …

ZOJ1081 Points Within

在解析几何中&#xff0c;我们大量的使用列方程求解未知量。但是在计算机计算的时候&#xff0c;解析几何的算法因为使用除法过多可能会带来严重的精度误差&#xff0c;所以简单来说&#xff0c;计算几何使用了一些其他的等效的方法来解决这些问题。 这里先说一个比较基础的题目…

如何使用JavaScript控制台改进工作流程

作为Web开发人员&#xff0c;很有必要了解如何调试代码。后台开发我们经常使用外部库来记录日志&#xff0c;并在某些情况下格式化显示日志&#xff0c;前端我们会使用断点和控制台&#xff0c;但是我们浏览器的控制台比我们想象的要强大得多。 当我们考虑控制台时&#xff0c…

如何在OpenJDK中使用ECC

曾经试图在Java和OpenJDK中使用椭圆曲线密码术 &#xff08;ECC&#xff09;的每个人要么被迫使用Bouncy Castle&#xff0c;要么被SunEC提供者弄糊涂了 。 SunEC提供程序根据文档 &#xff08;报价&#xff09;提供以下算法&#xff1a; AlgorithmParameters 欧共体 KeyAgr…