1. 內(nèi)部監(jiān)聽生命周期函數(shù)
export default {
mounted() {
this.chart = echarts.init(this.$el)
// 請(qǐng)求數(shù)據(jù),賦值數(shù)據(jù) 等等一系列操作...
// 監(jiān)聽窗口發(fā)生變化,resize組件
window.addEventListener('resize', this.$_handleResizeChart)
// 通過hook監(jiān)聽組件銷毀鉤子函數(shù),并取消監(jiān)聽事件
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', this.$_handleResizeChart)
})
},
updated() {},
created() {},
methods: {
$_handleResizeChart() {
// this.chart.resize()
}
}
}
總結(jié)
在Vue組件中,可以用過$on,$once去監(jiān)聽所有的生命周期鉤子函數(shù),如監(jiān)聽組件的updated鉤子函數(shù)可以寫成 this.$on('hook:updated', () => {})
2. 外部監(jiān)聽生命周期函數(shù)
今天同事在公司群里問,想在外部監(jiān)聽組件的生命周期函數(shù),有沒有辦法?。?/p>
為什么會(huì)有這樣的需求呢,原來同事用了一個(gè)第三方組件,需要監(jiān)聽第三方組件數(shù)據(jù)的變化,但是組件又沒有提供change事件,同事也沒辦法了,才想出來要去在外部監(jiān)聽組件的updated鉤子函數(shù)。查看了一番資料,發(fā)現(xiàn)Vue支持在外部監(jiān)聽組件的生命周期鉤子函數(shù)。
<template>
<!--通過@hook:updated監(jiān)聽組件的updated生命鉤子函數(shù)-->
<!--組件的所有生命周期鉤子都可以通過@hook:鉤子函數(shù)名 來監(jiān)聽觸發(fā)-->
<custom-select @hook:updated="$_handleSelectUpdated" />
</template>
<script>
import CustomSelect from '../components/custom-select'
export default {
components: {
CustomSelect
},
methods: {
$_handleSelectUpdated() {
console.log('custom-select組件的updated鉤子函數(shù)被觸發(fā)')
}
}
}
</script>
開發(fā)全局組件,你可能需要了解一下Vue.extend
開發(fā)loading組件
<template>
<transition name="custom-loading-fade">
<!--loading蒙版-->
<div v-show="visible" class="custom-loading-mask">
<!--loading中間的圖標(biāo)-->
<div class="custom-loading-spinner">
<i class="custom-spinner-icon"></i>
<!--loading上面顯示的文字-->
<p class="custom-loading-text">{{ text }}</p>
</div>
</div>
</transition>
</template>
<script>
export default {
props: {
// 是否顯示loading
visible: {
type: Boolean,
default: false
},
// loading上面的顯示文字
text: {
type: String,
default: ''
}
}
}
</script>
開發(fā)出來loading組件之后,如果需要直接使用,就要這樣去用
<template>
<div class="component-code">
<!--其他一堆代碼-->
<custom-loading :visible="visible" text="加載中" />
</div>
</template>
<script>
export default {
data() {
return {
visible: false
}
}
}
</script>
但這樣使用并不能滿足我們的需求
1.可以通過js直接調(diào)用方法來顯示關(guān)閉
2.loading可以將整個(gè)頁面全部遮罩起來
通過Vue.extend將組件轉(zhuǎn)換為全局組件
- 改造
loading組件,將組件的props改為data
export default {
data() {
return {
text: '',
visible: false
}
}
}
2.通過Vue.extend改造組件
// loading/index.js
import Vue from 'vue'
import LoadingComponent from './loading.vue'
// 通過Vue.extend將組件包裝成一個(gè)子類
const LoadingConstructor = Vue.extend(LoadingComponent)
let loading = undefined
LoadingConstructor.prototype.close = function() {
// 如果loading 有引用,則去掉引用
if (loading) {
loading = undefined
}
// 先將組件隱藏
this.visible = false
// 延遲300毫秒,等待loading關(guān)閉動(dòng)畫執(zhí)行完之后銷毀組件
setTimeout(() => {
// 移除掛載的dom元素
if (this.$el && this.$el.parentNode) {
this.$el.parentNode.removeChild(this.$el)
}
// 調(diào)用組件的$destroy方法進(jìn)行組件銷毀
this.$destroy()
}, 300)
}
const Loading = (options = {}) => {
// 如果組件已渲染,則返回即可
if (loading) {
return loading
}
// 要掛載的元素
const parent = document.body
// 組件屬性
const opts = {
text: '',
...options
}
// 通過構(gòu)造函數(shù)初始化組件 相當(dāng)于 new Vue()
const instance = new LoadingConstructor({
el: document.createElement('div'),
data: opts
})
// 將loading元素掛在到parent上面
parent.appendChild(instance.$el)
// 顯示loading
Vue.nextTick(() => {
instance.visible = true
})
// 將組件實(shí)例賦值給loading
loading = instance
return instance
}
export default Loading
- 在頁面使用
loading
import Loading from './loading/index.js'
export default {
created() {
const loading = Loading({ text: '正在加載。。。' })
// 三秒鐘后關(guān)閉
setTimeout(() => {
loading.close()
}, 3000)
}
}
通過上面的改造,loading已經(jīng)可以在全局使用了,如果需要像element-ui一樣掛載到Vue.prototype上面,通過this.$loading調(diào)用,還需要改造一下
將組件掛載到Vue.prototype上面
Vue.prototype.$loading = Loading
// 在export之前將Loading方法進(jìn)行綁定
export default Loading
// 在組件內(nèi)使用
this.$loading()