Vue 允许自定义混入策略,通过
Vue.config.optionMergeStrategies配置选项的合并方式。
Vue 内置了几种合并策略:
const strats = Vue.config.optionMergeStrategies
strats.data
strats.created
strats.methods
strats.computed
strats.watch
Vue.config.optionMergeStrategies.myOption = function(toVal, fromVal) {
return mergedValue
}
参数说明:
toVal:目标值(通常是组件选项)fromVal:来源值(通常是混入选项)Vue.config.optionMergeStrategies.customOption = function(toVal, fromVal) {
if (!toVal) return fromVal
if (!fromVal) return toVal
return toVal + ',' + fromVal
}
const mixin = {
customOption: 'mixin'
}
new Vue({
mixins: [mixin],
customOption: 'component',
created() {
console.log(this.$options.customOption)
}
})
输出:component,mixin
Vue.config.optionMergeStrategies.myMethod = Vue.config.optionMergeStrategies.methods
类似钩子函数的合并策略:
Vue.config.optionMergeStrategies.myHook = function(toVal, fromVal) {
return toVal
? fromVal
? toVal.concat(fromVal)
: toVal
: fromVal
}
Vue.config.optionMergeStrategies.pluginConfig = function(toVal, fromVal) {
return {
...fromVal,
...toVal
}
}
const mixin = {
pluginConfig: {
theme: 'dark',
locale: 'en'
}
}
new Vue({
mixins: [mixin],
pluginConfig: {
theme: 'light',
debug: true
},
created() {
console.log(this.$options.pluginConfig)
}
})
输出:
{
theme: 'light',
locale: 'en',
debug: true
}
Vue.config.optionMergeStrategies.permissions = function(toVal, fromVal) {
const merged = new Set()
if (fromVal) {
fromVal.forEach(p => merged.add(p))
}
if (toVal) {
toVal.forEach(p => merged.add(p))
}
return Array.from(merged)
}
const mixin = {
permissions: ['read', 'write']
}
new Vue({
mixins: [mixin],
permissions: ['read', 'delete'],
created() {
console.log(this.$options.permissions)
}
})
输出:['read', 'write', 'delete']
Vue.config.optionMergeStrategies.eventHandlers = function(toVal, fromVal) {
if (!toVal) return fromVal
if (!fromVal) return toVal
const merged = { ...fromVal }
for (const key in toVal) {
if (merged[key]) {
merged[key] = [merged[key], toVal[key]].flat()
} else {
merged[key] = toVal[key]
}
}
return merged
}
Vue.config.optionMergeStrategies.debug = function(toVal, fromVal) {
console.log('toVal:', toVal)
console.log('fromVal:', fromVal)
const result = { ...fromVal, ...toVal }
console.log('merged:', result)
return result
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<p>Theme: {{ theme }}</p>
<p>Permissions: {{ permissions.join(', ') }}</p>
</div>
<script>
Vue.config.optionMergeStrategies.theme = function(toVal, fromVal) {
return toVal || fromVal
}
Vue.config.optionMergeStrategies.permissions = function(toVal, fromVal) {
const merged = new Set()
if (fromVal) fromVal.forEach(p => merged.add(p))
if (toVal) toVal.forEach(p => merged.add(p))
return Array.from(merged)
}
const mixin = {
theme: 'dark',
permissions: ['read', 'write'],
data() {
return {
theme: this.$options.theme,
permissions: this.$options.permissions
}
}
}
new Vue({
el: '#app',
mixins: [mixin],
theme: 'light',
permissions: ['read', 'delete']
})
</script>
</body>
</html>
| 需求 | 推荐策略 |
|---|---|
| 简单覆盖 | 组件优先 |
| 都要执行 | 合并为数组 |
| 深度合并 | 递归合并对象 |
| 去重合并 | 使用 Set |
自定义混入策略提供了灵活的选项合并方式,但大多数情况下,使用默认策略已经足够。