如何在 Vue.js 应用程序中共享 "computed" 方法

How to share "computed" methods across a Vue.js application

我有一个加载项目列表的 Vue.js 应用程序,每个项目都作为 prop 传递给 Vue 组件。

我发现通过使用 mixins 我可以共享公共组件属性,例如 computedcreated

现在,我正在尝试对项目列表进行排序,但无法弄清楚如何访问每个组件的计算属性以应用 sorting/filtering。我怎样才能做到这一点?

[{
  price: 10,
  qty: 2
}, {
  price: 8,
  qty: 3
}]

Mixin-./Cost.js

export default {
  computed: {
     cost () {
        return this.price * this.qty;
     }
  }
}

组件(按预期工作)- ./Product.vue

import Cost from './Cost.js'
export default {
   name: 'product-item',
   props: ['product'],
   mixins: [Cost]
}

How would you access the computed properties, or restructure this setup?

列表组件

<template>
  <div id="list">
     <div v-for="product in sorted" :product="product">Cost: {{ cost }} </div>
  </div>
</template>

<script>
import ProductItem from './Product.vue'
export default {
   components: { ProductItem },
   created: () {
      this.items = [...] // as noted above
   },
   computed: {
       sorted () {
           return this.items.sort( (a,b) => b.cost - a.cost); // cost is not accessible!
       }
   }
}
</script>

正如@Sphinx 所建议的,您可以使用 ref 来访问子组件。

例如:

<template>
  <div id="list">
     <product-item v-for="product in sorted" :product="product" :ref="product"></product-item>
  </div>
</template>
<script>
import ProductItem from './Product.vue'
export default {
   components: { ProductItem }, 
   data: () => ({
       hidrated: false,
       items: []
   })
   created() {
       this.items = [...] // as noted above
   },
   mounted() {
       this.hidrated = true
   },
   computed: {
       sorted () {
           if (!this.hidrated && !Object.keys(this.$refs).length) {
               // handle initial state, before rendered
               return this.items
           }
           return Object.values(this.$refs)[0]
               .sort((a,b) => b.cost - a.cost)
               .map(c => c.product)
       }
   }
}
</script>

这是假设您的 List Component 中没有其他 ref

你还必须先检查组件是否被渲染,这里我使用hidrated来标记组件何时被挂载。

使用vuex。您的 vuex store 将提供一个 getters 对象,该对象可以包装到多个组件的本机 computed 对象中,或直接访问。您的代码将是 DRY、反应式、缓存和可维护的。

根据我的经验,一旦您需要超越 child-parent 数据关系,vuexstoreshared state 就是可行的方法。一旦你掌握了它,你的应用程序的发展就会变得非常神奇。

显示如何安装 vuex 超出了问题的范围。访问 https://vuex.vuejs.org/guide/getters.html 以了解 getter 与计算属性的相似之处,以及在组件之间共享的价值。官方 Vuex 指南还将演示如何使用商店初始化 Vue 实例。

这里有一些片段向您展示了vuex系统中的演员

存储和状态

// state definition (basically a shared reactive 'data' object that lives outside components)
state:{
    message:'Hello'
}

// the store getters are declared as methods and accessed as properties (just like component/computed)
getters:{
    message: state => return state.message
}

从组件访问

// component 1 wraps getter
computed:{
    message(){
      return this.$store.getters.message
    }
}

// component 2 also wraps getter
computed:{
    message(){
      return this.$store.getters.message
    }
}
// templates can also use getters directly
<div>{{$store.getters.message}}</div>

// If message was wrapped, you can simply use the computed property
<div>{{message}}</div>

一旦您开始使用 vuex,各种其他宝藏就会开始出现,例如 Chrome 中的开发者工具、undo/redo 支持、简单的状态重构、时间-旅行调试、应用程序持久性等。还有一些快捷方式可以将多个商店 getter 添加到您的计算属性中。