updated && beforeUpdate() 和 Updated()鈎子函數 && 生命周期-銷毀階段-外部銷毀 && 生命周期-銷毀階段-内部銷毀 && vuejs 的 nextTick
updated 鈎子函數
- 頁面資料已更新
- 任務通過diff算法對比新舊DOM,生成patch更新檔對象,然後将更新檔對象渲染為真實DOM,
- 渲染的是變化部分
- 得到真實DOM,可以進行DOM操作
<body>
<div id="app">
<Hello></Hello>
</div>
<template id="hello">
<div>
<button @click = "changeInfo"> changeInfo </button>
<p> {{ info }} </p>
</div>
</template>
</body>
<script src="../../lib/vue.js"></script>
<script>
new Vue({
el: '#app',
components: {
'Hello': {
template: '#hello',
data() {
return {
info: 'hello'
}
},
methods: {
changeInfo() {
this.info = '距離國慶沒幾天了'
}
},
beforeupdate() { //執行個體未完全建立出來執行
console.log(this.info);
console.log('beforeCreate');
},
updated() { //頁面資料已更新
//任務通過diff算法對比新舊DOM,生成patch更新檔對象,然後将更新檔對象渲染為真實DOM,
//渲染的是變化部分
//得到真實DOM,可以進行DOM操作
document.querySelector('p').style.background = 'blue'
console.log('updated')
},
},
}
})
</script>
beforeUpdate() 和 Updated()鈎子函數
----Swiper執行個體動态,但是還是有點小問題(後面會解決的)
在mounted()鈎子函數時是Swiper靜态的
<body>
<div id="app">
<Swiper></Swiper>
</div>
<template id="swiper">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide"
v-for="banner in banners"
:key="banner.id">
<img :src="banner.img"
alt="error">
</div>
</div>
<!-- 如果需要分頁器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要導航按鈕 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滾動條 -->
<div class="swiper-scrollbar"></div>
</div>
</template>
</body>
<script src="../../lib/vue.js"></script>
<script>
new Vue({
el: '#app',
components: {
'Swiper': {
template: '#swiper',
data() {
return {
banners: []
}
},
beforeCreate() { //執行個體未完全建立出來執行
console.log('beforeCreate');
},
created() { //methods和data已經初始化,常用于操作資料,發起ajax請求
fetch('./mock/banner.json', {
method: 'get'
})
.then((response) => {
return response.json()
})
.then((result) => {
this.banners = result;
})
.catch(err => console.log(err));
},
beforeMount() { //挂載資料之前
console.log('beforeMount');
},
mounted() { //記憶體中的模闆已挂載到頁面中
// var mySwiper = new Swiper('.swiper-container', {
// loop: true, // 循環模式選項
// // 如果需要分頁器
// pagination: {
// el: '.swiper-pagination',
// },
// // 如果需要前進後退按鈕
// navigation: {
// nextEl: '.swiper-button-next',
// prevEl: '.swiper-button-prev',
// },
// // 如果需要滾動條
// scrollbar: {
// el: '.swiper-scrollbar',
// },
// })
},
beforeUpdate() { //資料更新之前
//資料更新,但是頁面上還是舊資料
console.log('beforeUpdate');
},
updated() { //頁面資料已更新
var mySwiper = new Swiper('.swiper-container', {
loop: true, // 循環模式選項
// 如果需要分頁器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前進後退按鈕
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滾動條
scrollbar: {
el: '.swiper-scrollbar',
},
})
},
beforeDestroy() { //vue銷毀之前
console.log('beforeDestroy');
},
destroyed() { //已完全銷毀
},
}
}
})
</script>
3-生命周期-銷毀階段-外部銷毀
destroy()
作用
- 善後: 清除Vue無法自動删除的副作用,比如: 計時器、滾動事件、第三方執行個體
<body>
<div id="app">
<button @click="destroy"> 銷毀 </button>
<Hello v-if="flag"></Hello>
</div>
<template id="hello">
<div>
Hello
</div>
</template>
</body>
<script src="../../lib/vue.js"></script>
<script>
Vue.component('Hello', {
template: '#hello',
mounted() { //記憶體中的模闆已挂載到頁面中
this.timer = setInterval(() => {
console.log(1)
}, 1000);
window.onscroll = function() {
console.log('scroll')
}
},
destroyed() { //已完全銷毀
// 2. 作用
// - 善後: 清除Vue無法自動删除的副作用,比如: 計時器、滾動事件、第三方執行個體
clearInterval(this.timer);
window.onscroll = null;
},
})
new Vue({
el: '#app',
data: {
flag: true
},
methods: {
destroy() {
this.flag = !this.flag;
}
},
})
</script>
生命周期-銷毀階段-内部銷毀
<body>
<div id="app">
<Hello></Hello>
</div>
<template id="hello">
<div class="hello-box">
<button @click="destroy"> 内部銷毀 </button>
Hello
</div>
</template>
</body>
<script src="../../lib/vue.js"></script>
<script>
Vue.component('Hello', {
template: '#hello',
methods: {
destroy() {
this.$destroy();
}
},
mounted() { //記憶體中的模闆已挂載到頁面中
this.timer = setInterval(() => {
console.log(1)
}, 1000);
window.onscroll = function() {
console.log('scroll')
}
},
beforeDestroy() { //vue銷毀之前
console.log('beforeDestroy');
},
destroyed() { //已完全銷毀
clearInterval(this.timer);
window.onscroll = null;
document.querySelector('.hello-box').remove();
//delete this.arg
//用delete 删除變量
},
})
new Vue({
el: '#app'
})
</script>
總結 - 銷毀階段
- beforeDestroy 和 destroyed 沒啥差别
- 作用
- 善後: 清除Vue無法自動删除的副作用 ,比如: 計時器、滾動事件、第三方執行個體
- 形式
- 外部銷毀
- 内部銷毀
- 差別: 都可以删除元件,但是内部銷毀會留有元件真實DOM
銷毀 觸發條件:元件被删除
銷毀
觸發條件:元件被删除
-
銷毀
觸發條件:元件被删除
- 外部開關銷毀
-
内部調用$destroy()
這兩個鈎子函數沒有太大差別,是以我們統一說
- beforeDestroy
- destroyed
- 外部銷毀
- 通過開關完成
- DOM被删除了,元件也被删除了
- 通過開關完成
- 内部銷毀
- 通過調用$destroy()來完成
- DOM沒有被删除,但是元件被删除了
- Dom需要手動删除
- 通過調用$destroy()來完成
swiper-vuejs 的 nextTick
![](http://www.jqhtml.com/wp-content/uploads/2017/10/swiper1017-17.gif)
- 靜态資料
- 動态資料
- updated中寫式,會有重複執行個體化問題
- 第一個解決方案: 加判斷條件
- 第二個解決方案: setTimout
- 放在主線程後執行,異步隊列中,保證真實DOM渲染完成
- 第三種解決方案: 推薦 Vue内部提供的 nextTick
- ==nextTick表示真實DOM渲染完成之後才執行==
- Vue.nextTick( callback )
- this.$nextTick( callback )
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>vuejs的nextTick </title>
<link href="https://cdn.bootcss.com/Swiper/4.5.1/css/swiper.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/Swiper/4.5.1/js/swiper.min.js"></script>
<link rel="shortcut icon" href="../img/pikaqiu.jpg" type="image/x-icon" />
<!--IE 位址欄前的圖示-->
<link rel="Bookmark" href="../img/pikaqiu.jpg" type="image/x-icon">
<!--收藏夾的圖示-->
<style>
.swiper-container {
width: 600px;
height: 300px;
}
</style>
</head>
<body>
<div id="app">
<Hello></Hello>
</div>
<template id="hello">
<div>
<input type="text" v-model = "num">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide"
v-for = "item in banners"
:key = "item.id"
>
<img :src = "item.img" alt="">
</div>
</div>
<!-- 如果需要分頁器 -->
<div class="swiper-pagination"></div>
<!-- 如果需要導航按鈕 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- 如果需要滾動條 -->
<div class="swiper-scrollbar"></div>
</div>
</div>
</template>
</body>
<script src="../../lib/vue.js"></script>
<script>
// nextTick 表示真是dom渲染結束
Vue.component('Hello', {
template: '#hello',
data() {
return {
banners: [],
num: 0
}
},
created() {
fetch('./mock/banner.json')
.then(data => data.json())
.then(res => {
this.banners = res
// Vue.nextTick(function() {
this.$nextTick(function() { // 推薦
/*
好處:
1. 執行個體化執行一次
2. 真實DOM渲染結束之後才執行
*/
var mySwiper = new Swiper('.swiper-container', {
loop: true, // 循環模式選項
// 如果需要分頁器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前進後退按鈕
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滾動條
scrollbar: {
el: '.swiper-scrollbar',
},
})
})
}).catch(err => console.log(err))
},
updated() {
console.log('update')
// 如果有其他資料改變,那麼updated鈎子也要出發,那麼會有重複執行個體化問題
// var mySwiper = new Swiper('.swiper-container', {
// loop: true, // 循環模式選項
// // 如果需要分頁器
// pagination: {
// el: '.swiper-pagination',
// },
// // 如果需要前進後退按鈕
// navigation: {
// nextEl: '.swiper-button-next',
// prevEl: '.swiper-button-prev',
// },
// // 如果需要滾動條
// scrollbar: {
// el: '.swiper-scrollbar',
// },
// })
}
})
new Vue({
el: '#app'
})
</script>
</html>