欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 前端技术 > vue >内容正文

vue

vue生命周期详解 对应代码解析 -凯发k8官方网

发布时间:2023/12/2 vue 33 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 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]

{{ message }}

data : [object object] message: hi

mounted:

el : [object htmldivelement]

hi

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

总结

以上是凯发k8官方网为你收集整理的vue生命周期详解 对应代码解析的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

  • 上一篇:
  • 下一篇:
网站地图