每个前端框架都有自己的优势和特点,真的没有一个标准可以判断哪个框架更好一点,只能说哪个框架更适合你要做的业务。希望 FEer 们不要为了哪个框架更牛逼再起硝烟,我们期盼世界和平。
2014 年 2 月,尤雨溪先生(Evan You)开源了一个前端开发库 Vue.js 。从 1.0 版本到 2.0 版本 ,Vue 在轻量和功能之间找到更佳科学的平衡点,不仅性能上得到极大的提升,同时也拓展了更多的使用场景。 Vue 的核心思想就是:数据驱动的组件系统,而组件的本质就是一个拥有预定义选项的 Vue 实例。在实例化 Vue 的过程中,需要传入一个包含数据、模板、挂载元素、方法、生命周期钩子等的选项对象,这篇文章将用通俗易懂的语言让 Vue 初学者全面了解 Vue 生命周期钩子。
初识 Vue 生命周期钩子
每个 Vue 实例在被创建之前都要经过一系列的初始化过程。在这个过程中, Vue 实例会调用一些生命周期钩子,给开发者提供执行自定义逻辑的机会。在Vue 2.0中,生命周期钩子相比之前的版本发生了很大的变化。下面先看一张图,这是Vue 官方文档中关于 Vue 生命周期的解释图。
相信很多初学者看到这张图都会一脸懵逼,从内心里发出“ What are you 弄啥嘞? ”的咆哮。现在不懂没关系,如果你对 Vue 实例拥有一定了解,可以接着往下看。如果你对 Vue 实例了解不多,建议对 Vue 官方文档中“ Vue 实例”小节进行系统学习。如果看完这篇文章后,你还不懂 Vue 生命周期钩子vue的生命周期,那就一定是我的锅!
每个钩子都有自己的职责
就像我们人这一辈子,幼年玩土,少年读书,青年加班,中年得子,晚年跳跳广场舞,每个 Vue 实例从创建到销毁也要经历不同的阶段,每个钩子也只做特定的事情。就像雇佣童工是非法的,在beforeCreate钩子中调用data对象中的属性也不行。下面,我们结合具体代码去理解钩子的执行。
在chrome浏览器的控制台里,只输出4个钩子的执行结果:
① beforecreated 钩子会在 Vue 实例初始化之后,数据观测和 event / watcher 事件配置之前被调用。在控制台中可以看到 el 和 data 并未初始化。② created 钩子会在 Vue 实例创建完成之后被调用。在控制台中可以看到 data 已经初始化,但是 el 却依然没有初始化。③ beforeMount 钩子会在模版编译之后执行,在此期间 Vue 实例挂载还未开始,相关的 render 函数首次被调用。在控制台中可以看到 data 和 el 都已经初始化,此时 message 的值还没有渲染。④ mounted 钩子会在 el 被新创建的 vm.$el 替换,并且 Vue 实例挂载之后被调用。在控制台中可以看到
标签的内容已经发生变化,此时模板中的HTML在Web页面中渲染。
接下来,我们在控制台再执行一些代码,触发剩下的钩子陆续执行。
app.message= '用科技让复杂的世界更简单';
可以看到当我们修改 data 对象的属性值时,会相继触发 beforeUpdate 钩子和 updated 钩子的执行。数据更新会引发 Virtual DOM 重新渲染和打补丁,这便是 beforeUpdate 钩子和 updated 钩子的分界线。
app.$destroy();
关于销毁,会依次触发 beforeDestroy 钩子和 destroyed 钩子。实例销毁之前,在 beforeDestroy 钩子里 Vue 实例依然完全可用。Vue 实例销毁之后,在 destroyed 钩子里 Vue 实例指示的所有东西都会解绑vue的生命周期,所有的事件监听器都会被移除,所有的子实例也会被销毁。
Vue 实例销毁后,再修改 message 的值,你会有惊喜的发现。虽然数据变了,但是并没有驱动视图进行更新。
最后,还有2个成对出现的钩子没有向大家介绍,那就是activated 钩子和 deactivated 钩子。所以,我们要再来一波代码。如果有对 vue-router 不熟悉的同学,需要先行了解这个构建 Vue 单页面应用的神器,这样可以更好的理解组件缓存机制。
在 Vue 的设计中, 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。当组件在 内被切换,它的 activated 钩子和 deactivated 钩子会被对应执行。下面,我们开始实验:先从 FE 小哥哥切换到 FE 小姐姐,然后再切换回 FE 小哥哥。
我们继续看控制台:Boy 组件和 Girl 组件只有在第一次渲染时,created 、mounted 和 activated 这3个钩子全部被调用,后面再进行组件切换时就只有activated 钩子和 deactivated 钩子分别执行。
转变操作DOM的思维
现在思考一个问题:如果在某个钩子中修改了数据,而DOM元素还没有来得及渲染,我们如何获取这个DOM元素?
思考30s …
要不要再给你一点时间?
首先,这个问题本身就有问题。Vue 的中心思想是用数据驱动视图的变化,这就需要我们转变利用原生 JavaScript 或者 Jquery 开发时操作DOM元素的惯性思维。如果业务中真的出现这样的需求,必须先思考是不是代码设计上出现不妥,或者思考能否在其他钩子中进行相关逻辑的操作?不过凡事都有例外,如果你真的要手动操作DOM元素,Vue 还是提供的一个 API ,就是 Vue.nextTick 。现在我们对上面提到的第一波代码进行一点小小的改造,在 beforeCreate 钩子中再加入这个 API 的调用。
运行代码之后,我们再次观察控制台。正常情况下,在 beforeCreate 钩子中 el 和 data 都应该是undefined,这会导致我们无法修改 message 的值。Vue.nextTick 可以做到在下次 DOM 元素更新循环结束之后执行延迟回调。修改数据之后立即使用这个方法,可以获取更新后的 DOM 元素,就巧妙地解决了这个尴尬的问题。
西二旗,不相信眼泪
讲了这么多,就是希望每个初学者都可以在 Vue 生命周期中的不同时机,选择合适的钩子执行相关业务逻辑的操作。比如:可以在 beforecreate 钩子中添加 loading 效果和其它等待动画。在 created 钩子中而不是mounted 钩子中开始请求 server 接口数据,或者执行一些初始化操作。在 destoryed 钩子中回滚某些操作,或者清空相关的数据设置。合理地使用框架确实可以达到事半功倍的效果,同时也建议各位同学不要过分依赖框架。毕竟熟练地使用各种框架只能让你沦为一个完成需求的流水工,而深入了解框架的实现原理、夯实 JavaScript 编程基础才能让你成长为一个既懂得用轮子也可以造轮子的前端 Coder 。