【问题标题】:Creating a root computed value from component computed values?从组件计算值创建根计算值?
【发布时间】:2019-12-02 02:36:55
【问题描述】:

我对 Vue 有点陌生,我正在尝试弄清楚如何从组件的计算值中访问计算值。 请查看这个小提琴:https://jsfiddle.net/85ma3rct/

 <script src="https://unpkg.com/vue"></script>
  <div id="app">
    <table>   
      <floor></floor> 
      <floor></floor>
      <floor></floor>
    </table>  
    Largest area: {{ largest_area}}
  </div>

Vue.component('floor', {
  data: function () {
    return {
      width: 20,
      height: 20
    }
  },
  computed: {
    area: function () {
      return this.width * this.height;
    }
  },  
  template: '<tr><td><input type="number" v-model="width"></td>' +
            '<td><input type="number" v-model="height"></td>' +
            '<td>{{ area }}</td>' +
            '</tr>'
})

new Vue({
  el: '#app',
  computed: {
    largest_area: function () {
      // How to get this from component computed values...
      return 0
    }
  }, 
})

如何从多个组件中通过计算值获得最大面积计算值?

【问题讨论】:

标签: vue.js


【解决方案1】:

一种可能的解决方案是观察子组件的区域值变化并向父组件发出值

  watch: {
    area: {
      handler() {
         this.$emit('input', this.area)
      },
      immediate: true
    }
  },

然后在父级中

<table>

  <floor @input="changeVal($event, 0)"></floor> 
  <floor @input="changeVal($event, 1)"></floor>
  <floor @input="changeVal($event, 2)"></floor>

  </table>

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
    areas: [0, 0, 0]
  },
  computed: {
    largest_area: function () {
        return Math.max(...this.areas)
    }
  },
  methods: {
    changeVal(val, index) {
       this.$set(this.areas, index, val)
    }
  }
})

在这里演示https://jsfiddle.net/ittus/kuo9crjm/1/

【讨论】:

    【解决方案2】:

    您可以将您的&lt;floor&gt; 组件转换为custom elements that can use v-model。然后每个&lt;floor&gt; 可以将计算出的区域发送给它的父级,父级可以收集和计算最大值。

    例如

    Vue.component('floor', {
      template: `<tr>
      <td><input type="number" v-model="width" @input="update"></td>
      <td><input type="number" v-model="height" @input="update"></td>
      <td>{{ area }}</td>
      </tr>`,
      data: () => ({ width: 20, height: 20 }),
      computed: {
        area() { return this.width * this.height }
      },
      methods: {
        update() { this.$emit('input', this.area) }
      },
      created() { this.update() } // emit the initial value
    })
    
    new Vue({
      el: '#app',
      data: { areas: [0, 0, 0] },
      computed: {
        largest_area () { return Math.max(...this.areas) }
      }
    })
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.min.js"></script>
    <div id="app">
      <table>
        <floor v-for="(_, n) in areas" v-model="areas[n]" :key="n"></floor>
      </table>
      Largest area: {{ largest_area }}
    </div>

    通常,要支持v-model,您的组件将具有value prop。但是,由于您的组件初始化了自己的数据,因此我省略了这一点。唯一真正的要求是您的组件发出一个 input 事件。

    【讨论】:

    • @EvilArthas 我不明白你的意思。此答案中的所有内容都是被动的
    • 我的错,对不起:)
    【解决方案3】:

    您可以使用 $refs 作为此参考 - Refs

    ref 添加到您的组件中,无论您在哪里导入并使用它 -

    <MyComponent ref="child" />
    

    然后您可以从您的消费component 访问它的所有属性。

    在您的消费组件中,您可以在$refs 属性中访问它,如下所示

    this.$refs.child.{child-property}
    

    ref 添加到floor

    <table>   
      <floor ref="floor"></floor> 
    </table>  
    

    然后参考一下

    new Vue({
      el: '#app',
      computed: {
        largest_area: function () {
            console.log(this.$refs.floor.area())
            return 0
        }
      }, 
    })
    

    【讨论】:

    • 这违反了one-way data flow
    • @Phil, refs 不再是被动的,这会阻止 child 意外地改变 parent 状态。我不确定我是否在这里遗漏了一点,但这是官方文档根据 OP 要求推荐的方式 - vuejs.org/v2/guide/…
    • 调用方法与进入 refs 并访问它们的数据和计算属性非常不同。不建议这样做
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    相关资源
    最近更新 更多