Vue的生命周期
生命周期:Vue实例从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是Vue的生命周期,各个阶段有相对应的事件钩子。
beforeCreate(创建前),在数据观测和初始化事件还未开始
created(创建后),完成数据观测,属性和方法的运算,初始化事件,$el
属性还没有显示出来
beforeMount(载入前),在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
mounted(载入后),在el
被新创建的vm.$el
替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el
属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
beforeUpdate(更新前),在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后),在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前),在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后),在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
注意:
created
阶段的ajax请求与mounted
请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态。
mounted
不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick
。
2. 单个组件的生命周期
初始化组件时,仅执行了beforeCreate/Created/beforeMount/mounted
四个钩子函数
当改变data
中定义的变量(响应式变量)时,会执行beforeUpdate/updated
钩子函数
当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed
钩子函数
初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated
可多次执行
3. 父子组件的生命周期
仅当子组件完成挂载后,父组件才会挂载
当子组件完成挂载后,父组件会主动执行一次beforeUpdate/updated钩子函数(仅首次)
父子组件在data变化中是分别监控的,但是在更新props中的数据是关联的
销毁父组件时,先将子组件销毁后才会销毁父组件
4. 兄弟组件的生命周期
组件的初始化(mounted之前)分开进行,挂载是从上到下依次进行
当没有数据关联时,兄弟组件之间的更新和销毁是互不关联的
5. 宏mixin的生命周期
mixin中的生命周期与引入该组件的生命周期是仅仅关联的,且mixin的生命周期优先执行
1、什么是vue生命周期?
答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
2、vue生命周期的作用是什么?
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3、vue生命周期总共有几个阶段?
答:它可以总共分为8个阶段:创建前/后、载入前/后、更新前/后、销毁前/销毁后。
5、DOM 渲染在哪个周期中就已经完成?
答:DOM 渲染在 mounted 中就已经完成了。
Vue实现数据双向绑定的原理:Object.defineProperty()
vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter,getter
,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的data
选项时,Vue 将遍历它的属性,用 Object.defineProperty()
将它们转为getter/setter
。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer
,Compile和Watcher
三者,通过Observer
来监听自己的model
的数据变化,通过Compile
来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher
搭起observer和Compile
之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input
)—>数据model
变更双向绑定效果。
js实现简单的双向绑定:
<body>
<div id="app">
<input type="text" id="txt">
<p id="show"></p>
</div>
</body>
<script type="text/javascript">
var obj = {}
Object.defineProperty(obj, 'txt', {
get: function () {
return obj
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
</script>
Vue组件间的参数传递
1、父组件与子组件传值
父组件传给子组件:子组件通过props
方法接受数据;
子组件传给父组件:$emit
方法传递参数
2、非父子组件间的数据传递,兄弟组件传值eventBus
,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。
Vue的路由实现:hash模式 和 history模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用 window.location.hash 读取。特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式:history采用HTML5的新特性;且提供了两个新方法: pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
Vue 实现前进刷新,后退不刷新的效果
需求一:
在一个列表页中,第一次进入的时候,请求获取数据。
点击某个列表项,跳到详情页,再从详情页后退回到列表页时,不刷新。
也就是说从其他页面进到列表页,需要刷新获取数据,从详情页返回到列表页时不要刷新。
解决方案
在 App.vue设置:
<keep-alive include="list">
<router-view/>
</keep-alive>
假设列表页为list.vue
,详情页为detail.vue
,这两个都是子组件。
我们在keep-alive
添加列表页的名字,缓存列表页。
然后在列表页的created
函数里添加ajax请求,这样只有第一次进入到列表页的时候才会请求数据,当从列表页跳到详情页,再从详情页回来的时候,列表页就不会刷新。
这样就可以解决问题了。
需求二:
在需求一的基础上,再加一个要求:可以在详情页中删除对应的列表项,这时返回到列表页时需要刷新重新获取数据。
我们可以在路由配置文件上对detail.vue
增加一个meta
属性。
{
path: '/detail',
name: 'detail',
component: () => import('../view/detail.vue'),
meta: {isRefresh: true}
},
这个meta
属性,可以在详情页中通过this.$route.meta.isRefresh
来读取和设置。
设置完这个属性,还要在App.vue
文件里设置watch
一下$route
属性。
watch: {
$route(to, from) {
const fname = from.name
const tname = to.name
if (from.meta.isRefresh || (fname != 'detail' && tname == 'list')) {
from.meta.isRefresh = false
// 在这里重新请求数据
}
}
},
这样就不需要在列表页的created
函数里用 ajax 来请求数据了,统一放在App.vue
里来处理。
触发请求数据有两个条件:
从其他页面(除了详情页)进来列表时,需要请求数据。
从详情页返回到列表页时,如果详情页 meta 属性中的isRefresh
为true
,也需求重新请求数据。
当我们在详情页中删除了对应的列表项时,就可以将详情页meta
属性中的isRefresh
设为true
。这时再返回到列表页,页面会重新刷新。
其它小知识点
1、css只在当前组件起作用
答:在style
标签中写入scoped
即可 例如: <style scoped></style>
2、v-if 和 v-show 区别
答:v-if
按照条件是否渲染,v-show
是display
的block
或none
;
3、$route
和$router
的区别
答:$route
是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name
等路由信息参数。而$router
是“路由实例”对象包括了路由的跳转方法,钩子函数等。