vue.js:确定自定义选项合并策略的范围,而不是走向全局

标签 vue.js

大家好,

快速总结:如何针对每个组件而不是全局使用自定义选项合并策略?

我的问题: 我正在通过 Mixins 扩展我的组件,到目前为止它运行良好。然而,虽然它与组件方法之类的东西配合得很好,但我经常需要重写一些生命周期钩子(Hook),比如挂载、创建等。要注意的是,Vue - 默认情况下 - 将它们排在一个数组中并依次调用它们.这当然是由 Vues 默认的合并策略定义的。

但是在某些特定情况下,我确实需要覆盖钩子(Hook)而不是让它堆叠。我知道我可以根据自己的喜好自定义 Vue.config.optionMergeStrategies,但我希望在每个组件的基础上自定义 mergeStrategy,而不是全局应用它。

我在纸面上的天真方法是创建一个更高的函数来存储原始钩子(Hook),应用我的自定义策略,调用我的组件主体,然后恢复 Vues 原始钩子(Hook)。

让我们这样说

export default function executeWithCustomMerge(fn) {
    const orig = deep copy Vue.config.optionMergeStrategies;


    Vue.config.optionMergeStrategies.mounted = (parent, child) => [child];

    fn();
    Vue.config.optionMergeStrategies = deep copy orig;

这是实际操作

executeWithCustomMerge(() => {
    Vue.component('new-comp', {
         mixins: [Vue.component("old-comp")],
    },
    mounted() {
       //i want to override my parent thus I am using a custom merge strategy
    });
});

现在,这不会成功,因为恢复原始 Hook 策略仍然适用于全局,并且会在我的组件上的大多数 Hook 被调用之前重置。

我想知道我需要做什么才能将我的合并策略范围限定到一个组件。

最佳答案

我看过optionMergeStrategies更详细地从文档中找到了这个有趣的引用(强调我的):

The merge strategy receives the value of that option defined on the parent and child instances as the first and second arguments, respectively. The context Vue instance is passed as the third argument.

所以我认为实现自定义合并策略会很简单,该策略检查 Vue 实例并查看其属性以决定使用哪种策略。像这样:

const mergeCreatedStrategy = Vue.config.optionMergeStrategies.created;
Vue.config.optionMergeStrategies.created = function strategy(toVal, fromVal, vm) {
  if (vm.overrideCreated) {
    // If the "overrideCreated" prop is set on the component, discard the mixin's created()
    return [vm.created];
  }
  return mergeCreatedStrategy(toVal, fromVal, vm);
};

事实证明,当为组件调用策略函数时,第三个参数 (vm) 没有设置。这是一个新的错误!参见 https://github.com/vuejs/vue/issues/9623

所以我找到了另一种方法来通知合并策略它应该做什么。由于 JavaScript 函数是一流的对象,they can have properties and methods just like any other object .因此,我们可以通过在其上设置属性并在合并策略中查找其值来设置组件的功能以覆盖其父级,如下所示:

Vue.mixin({
  created() {
    this.messages.push('global mixin hook called');
  }
});

const mixin = {
  created() {
    this.messages.push('mixin hook called');
  },
};

const mergeCreatedStrategy = Vue.config.optionMergeStrategies.created;
Vue.config.optionMergeStrategies.created = function strategy(toVal, fromVal) {
  if (fromVal.overrideOthers) {
    // Selectively override hooks injected from mixins
    return [fromVal];
  }
  return mergeCreatedStrategy(toVal, fromVal);
};

const app = {
  el: '#app',
  mixins: [mixin],
  data: { messages: [] },
  created() {
    this.messages.push('component hook called');
  },
};
// Comment or change this line to control whether the mixin created hook is applied
app.created.overrideOthers = true;

new Vue(app);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <h1>Messages from hooks</h1>
  <p v-for="message in messages">{{ message }}</p>
</div>

关于vue.js:确定自定义选项合并策略的范围,而不是走向全局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52988704/

相关文章:

javascript - Vue 有条件地阻止事件传播给子级

javascript - Vue.js:为什么我的列表没有使用 v-for 指令渲染?

webpack - 在 Vue CLI 3 配置中使用相对 URL 时本地字体路径不正确

vue.js - Vuetify 自动完成将不会渲染

vue.js - 如何模拟故事书故事中的模块?

css - 幻灯片反向转换,Vue Js

vue.js - jsconfig.json 给出 ts 错误

javascript - vue-resource root 和授权的配置

javascript - 赋值的左边可以是 Javascript 中的表达式吗

javascript - 在vuejs组件中调用外部函数