根据上篇文章对选项合并策略源码的解读,可以利用Vue内部提供的API实现自定义的合并策略以及生命周期钩子函数。
Vue.config.optionMergeStrategies
tips:以下父组件选项可理解为mixins混入的数据;子组件选项为当前自身组件选项。
自定义选项合并策略
/src/utils/customMergeHook.js
合并策略:
- 若子组件选项不存在,则返回父组件选项;
- 否则,判断父组件选项是否存在,如果存在则合并父子组件选项;不存在则返回子组件选项,以数组的形式。
/**
* Hooks are merged as arrays.
*/
function mergeHook(parentVal, childVal) {
const res = childVal ? parentVal ? parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal;
return res ? dedupeHooks(res) : res;
}
// 去重函数
function dedupeHooks (hooks) {
const res = []
for (let i = 0; i < hooks.length; i++) {
// 判断数据是否已存在
if (res.indexOf(hooks[i]) === -1) {
res.push(hooks[i])
}
}
return res
}
自定义生命周期函数
一、开发核心业务
/src/utils/customLifeCycle.js
- 导入相关依赖
import Vue from 'vue';
// 以上自定义的选项合并策略
import { mergeHook } from '@/utils/customMergeHook'
- 初始化函数,设置自定义生命周期函数名称及选项合并策略
function init() {
const strats = Vue.config.optionMergeStrategies
/**
* 自定义生命周期函数
* 将其生命周期合并策略设置为以上自定义的选项合并策略
* 也可以设置与内置生命周期合并策略一致;(例:strats.XXX = strats.created)
*/
strats.pageVisible = mergeHook
strats.pageHidden = mergeHook
strats.pageResize = mergeHook
}
// 执行初始化函数
init()
- 编写监听触发生命周期函数的方法
// 通过已触发该生命周期函数
const notifyTriggerCustomHooks = (lifeCycleName, vm) => {
// 生命周期存在$options中,通过$options[lifeCycleName]获取生命周期
const lifeCycles = vm.$options[lifeCycleName]
// 使用以上自定义选项合并策略,返回的是一个数组格式
if (lifeCycles && lifeCycles.length) {
// 遍历lifeStyleName对应的生命周期函数列表,依次执行
lifeCycles.forEach(lifeCycle => {
lifeCycle.call(vm)
})
}
// 遍历所有的子组件,然后依次递归执行
if (vm.$children && vm.$children.length) {
vm.$children.forEach(child => {
notifyTriggerCustomHooks(lifeCycleName, child)
})
}
}
- 绑定事件
/**
* 将事件变化绑定到根节点上
* @param {*} rootVm
*/
export function bindVm(rootVm) {
let lifeCycleName = undefined
// 监听窗口页面的显示隐藏
window.addEventListener('visibilitychange', () => {
// 判断当前是哪个生命周期函数
if (document.visibilityState == 'hidden') {
lifeCycleName = 'pageHidden'
} else if (document.visibilityState == 'visible') {
lifeCycleName = 'pageVisible'
}
if (lifeCycleName) {
// 通知所有组件生命周期发生变化了
notifyTriggerCustomHooks(lifeCycleName, rootVm)
}
})
// 监听窗口大小变化
window.addEventListener('resize', () => {
lifeCycleName = 'pageResize'
notifyTriggerCustomHooks(lifeCycleName, rootVm)
})
}
二、绑定事件
/src/main.js
...
import{ bindVm } from '@/utils/customLifeCycle'
const vm = new Vue({
...
})
// 执行方法,将事件绑定根节点上
bindVm(vm)
三、使用
- 编写mixins混入
/src/mixins/index.js
export default {
pageHidden() {
// mixins混入,触发隐藏页面;执行相关业务
...
},
pageVisible() {
// mixins混入,触发显示页面;执行相关业务
...
},
pageResize() {
// mixins混入,触发窗口大小发生变化;执行相关业务
...
}
}
- 页面调用
/src/views/page1/index.vue(以该页面为例)
<template>
...
</template>
<script>
...
import mixins from '@/mixins'
export default {
// mixins混入
mixins: [mixins],
pageHidden() {
// 组件内触发隐藏页面;执行相关业务
...
},
pageVisible() {
// 组件内触发显示页面;执行相关业务
...
},
pageResize() {
// 组件内触发窗口大小发生变化;执行相关业务
...
}
}
</script>
<style lang="scss" scoped>
...
</style>