【问题标题】:Sharing variable across all vue component instances在所有 vue 组件实例之间共享变量
【发布时间】:2020-07-17 08:46:59
【问题描述】:

我正在尝试重构一些代码并将一些代码移动到 mixin。但我得到了不同的行为。我希望在组件的所有实例之间共享一个对象。所以我写了类似下面的东西

<script>
export default {
  registryManager: new RegistryManager()
}
</script>

在某些情况下,我通过this.$options.registeryManager 访问它。 现在我已将此代码移至 mixin。

混音

export default {
  registryManager: new RegistryManager()
}

组件

<script>
import registryManager from './mixins/registryManager';
export default {
  mixins: [registryManager]
}
</script>

假设您有 2 个组件 A、B。之前,组件 A 的所有实例都有一个 registryManager,组件 B 的所有实例都有一个单独的 registryManger。 使用 mixin,组件 A 和组件 B 的所有实例共享一个注册表管理器,因为无论有多少组件使用 mixin,都只会创建一个 mixin 实例 有什么方法可以为每个组件创建一个 mixin 实例以获得更早的行为?

【问题讨论】:

  • 为您导入mixin 的每个组件创建一个新实例。所以不确定你想要达到什么目标?
  • 不确定是不是这样。所有组件都获得相同的注册表管理器实例。
  • 有没有更简洁的方式在组件的所有实例之间共享变量?
  • 是的,使用像Vuex 这样的状态管理库。如果 mixin 编写正确,它们的行为类似于 pure 函数。不确定我是否理解您的问题。
  • 它被定义为一个选项有什么原因吗?它应该在某处被覆盖吗?

标签: vue.js vue-component vue-mixin


【解决方案1】:

这是预期的行为。只有一个类实例,new RegistryManager() 在 mixin 模块中只评估一次,Vue 不知道registryManager 需要多次实例化。

由于组件构造函数和类实例是一一对应的关系,所以可以赋值为构造函数属性。

这可以在全局范围内完成:

Object.defineProperty(Vue.prototype, 'registryManager', {
  get() {
    if (!this.constructor._registryManager) {
      this.constructor._registryManager = new RegistryManager();
    }

    return this.constructor._registryManager;
  }
});

该类也以这种方式延迟实例化。可以放在install(Vue) {...}里面作为插件使用。

或者在本地作为 mixin:

  beforeCreate() {
    if (!this.constructor._registryManager) {
      this.constructor._registryManager = new RegistryManager();
    }

    this.registryManager = this.constructor._registryManager;
  }

【讨论】:

  • 这样会被添加到所有组件中。没有办法将它注入包含 mixin 的组件中吗?我将尝试这件作品一次,并尝试对所需的行为进行一些修改。
  • 在全球范围内这样做可能不是一件坏事。但是,是的,它也可以是一个 mixin。
【解决方案2】:

您可以在 mixin 中创建一个工厂方法,该方法需要一个 id(例如组件的名称)并返回一个 RegisterManager 的实例。

mixin 模块必须保留从 id 到 RegisterManager 实例的映射。

类似的东西。

const instances = {
}

export default {
  getRegistryManager: (id) => {
    if (!instances[id]) {
      instances[id] = new RegistryManager()
    }

    return instances[id]
  }
}

然后从您的组件中调用getRegistryManager

<script>
  import getRegistryManager from './mixins/registryManager';
  export default {
   mixins: [getRegistryManager("ComponentName")]
  }
</script>

【讨论】:

  • 这在任何时候都是一个不错的解决方案。但问题是我正在编写一个节点模块供其他人使用。首先,我不能要求他们做很多事情。用户不应该为创建注册表而烦恼。其次,很多用户不提供姓名或ID可能会发生冲突。
猜你喜欢
  • 1970-01-01
  • 2013-09-26
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
相关资源
最近更新 更多