为所有实例设置组件属性/将相同的数据传递给所有组件实例

Posted

技术标签:

【中文标题】为所有实例设置组件属性/将相同的数据传递给所有组件实例【英文标题】:Set Component prop for all instances / Pass same data to all Component instances 【发布时间】:2020-03-14 02:04:41 【问题描述】:

我有一个组件,其中每个实例都需要传递一些数据,该组件被多次使用,并且该组件的所有实例都应该接收相同的数据/道具。

<my-component :someProp="someValue"></my-component>
<my-component :someProp="someValue"></my-component>
<my-component :someProp="someValue"></my-component>
<!-- ...and lots more... -->

这是我目前的方法:

这有点多余,我如何为我的组件的所有实例预填充这个 someProp? 我尝试了 Vue.extend() 但无法弄清楚它所期望的语法,该部分的文档不够清楚。 这就是我想象的工作方式:

// App.vue
import MyComponent from './components/MyComponent'

const PreConfiguredComponent = Vue.extend(MyComponent, 
  props: 
    someProp: "someValue"
  
)

export default 
  name: 'app',
  data: () => (),
  components: 
    MyComponent: PreConfiguredComponent
  

你明白了,我不知道如何更好地表达它。不必使用 props,但我不知道其他传递数据的方法。

【问题讨论】:

1.当您说“所有实例”时,您的意思是数据实际上是全局的,还是仅指特定上下文中的所有实例,例如在同一个父模板中?根据您的组件当前的使用方式,这可能是一个微妙的区别,但它对可能的答案产生了巨大的影响。 2. 子组件创建后,值能有任何变化吗? @skirtle 不,数据以后不会改变,我的意思是使用它的 Vue 应用程序/组件中的所有实例,在这种情况下是主 App.vue。 不可以使用v-for 吗?或者这些组件中的每一个都需要其他可能不同的道具吗? @jrend 是的,这是不可能的,因为组件可以无处不在。 【参考方案1】:

有很多不同的方法可以解决这个问题。我怀疑这将是一个详尽的列表,但我可以给出一些可能性。

1。全局存储值

这里明显的选择是 Vuex 商店。只需将相关数据放入 store 中,组件就可以获取所需的内容。

但是,全局商店不一定是 Vuex。如果您没有其他理由引入 Vuex,那么您可能更喜欢更临时的东西。

存储的另一种方法是将数据保存在$root,官方文档中描述了这种方法:

https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch

另一种选择是拥有一个可以将数据保存为单例的.js 文件。有多种方法可以做到这一点,但最简单的形式可能是这样的:

export default 
  myData: null

然后您将 import 该对象并根据需要读取/写入 myData 的值。它不一定是反应式的,但我假设初始值将在开始时设置,在创建应用程序之前,并且在那之后不会改变。

2。将值存储在 Vue 原型中

这与上述非常相似,但我认为值得单独提及。它看起来像这样:

Vue.prototype.$myComponentData = 'someValue'

然后在任何组件中,您都可以通过属性$myComponentData 访问该值。

文档:https://vuejs.org/v2/cookbook/adding-instance-properties.html

3。提供/注入

provide/inject 机制是鲜为人知的 Vue 功能之一,但它提供了使用 props 将数据向下传递给子组件的替代方法。它有各种优点和缺点,通常你会尝试使用道具。

https://vuejs.org/v2/api/#provide-inject

简而言之,它允许组件为其所有后代提供命名值,而无需单独显式地将其传递给每个后代。然后后代组件可以选择他们想要注入的命名属性。

您将无法使用 provide/inject 将不同的值传递给后代组件,但在您的情况下,值是相同的,所以它应该可以工作。

如果您认为这种方法可能适合您,那么我建议您进一步阅读:

https://blog.logrocket.com/how-to-make-provide-inject-reactive/

4。重构以删除重复

虽然这不太可能是您采用的解决方案,但我认为值得一提。

这个问题的起始前提似乎是明确传递道具是一种重复形式。额外的噪音和额外的努力可能会犯错误。

有可能我们可以在传递道具的同时删除该重复项。这里的关键是重构模板,使子组件仅具有一次功能。

显然,这需要在一个循环中,以便我们仍然可以获得所有所需的组件。该循环需要一个合适的数据结构来驱动它,以便创建所有正确的组件。

我假设问题中的模板是简化的。如果您确实连续有多个实例,那么重构为使用 v-for 应该非常简单。如果(看起来更有可能)组件嵌套在布局中的不同位置,那么尝试将其编码到数据结构中以避免一些模板重复可能会变得笨拙。

希望这个想法很清楚,但如果不是,您可以阅读一下:

https://michaelnthiessen.com/reducing-redundant-repetition

5。动态组件

这就是问题中提到的。有多种方法可以做到这一点,但这个想法的核心是我们在运行时更改我们的组件定义。这并不一定意味着创建一个新组件,它同样可能意味着在现有组件定义中加入一些东西。我们已经看到了这个想法的变体,使用前面提到的Vue.prototype 方法。

理论上它可以通过 prop 的 default 值来完成,但似乎没有必要使用 prop,除非在某些情况下以通常的方式从外部设置该 prop。

我们可以使用data 将其设置为属性,但我个人很想使用Vue.prototype 技巧的变体将属性添加到组件自己的原型中:

MyComponent = Vue.extend(
  template: `<div> value </div>`
)

MyComponent.prototype.value = 'some value'

new Vue(
  el: '#app',

  components: 
    MyComponent
  
)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <my-component></my-component>
</div>

从性能角度来看,使用原型相对便宜。反应性存在潜在问题,但它们仅适用于值可以更改的情况,而在这种情况下则不能。

只是为了明确说明propdata 方法:

MyComponent = 
  template: `<div> value </div>`


PreConfiguredComponent = Vue.extend(
  extends: MyComponent,

  props: 
    value: 
      default: 'some prop value'
    
  
)

new Vue(
  el: '#app',

  components: 
    MyComponent: PreConfiguredComponent
  
)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <my-component></my-component>
</div>

和:

MyComponent = 
  template: `<div> value </div>`


PreConfiguredComponent = Vue.extend(
  extends: MyComponent,

  data () 
    return 
      value: 'some data value'
    
  
)

new Vue(
  el: '#app',

  components: 
    MyComponent: PreConfiguredComponent
  
)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <my-component></my-component>
</div>

您同样可以尝试直接调整导入的 MyComponent 而不是扩展它。

【讨论】:

方法 5 正是我要找的,带有 Vue.extend 和 PreConfiguredComponent 的方法,谢谢!

以上是关于为所有实例设置组件属性/将相同的数据传递给所有组件实例的主要内容,如果未能解决你的问题,请参考以下文章

如何将一个组件中查询的数据传递给另一个组件以用作查询变量?

如何将更新的数据传递给已经渲染的子 vue 组件

将异步获取的数据传递给子道具

ReactJS - 如何将“全局”数据传递给深度嵌套的子组件?

如何推迟将 Ajax 数据传递给子组件?

如何将设计数据传递给React组件?