Vue 2.3组件中的双向绑定

时间:2017-06-06 15:51:56

标签: vue.js vuejs2 2-way-object-databinding

我理解Vue 2.3中返回的.sync修饰符,并将其用于实现“多项选择”的简单子组件。问题和答案。父组件像这样调用子:

<question
  :stem="What is your favourite colour?"
  :options="['Blue', 'No, wait, aaaaargh!']
  :answer.sync="userChoice"
>

父级有一个字符串数据元素userChoice来存储子组件的结果。孩子为选项提供问题和单选按钮。孩子的基本部分看起来像这样(我使用的是Quasar,因此q-radio):

<template>
  <div>
    <h5>{{stem}}</h5>
    <div class="option" v-for="opt in options">
      <label >
        <q-radio v-model="option" :val="opt.val" @input="handleInput"></q-radio>
        {{opt.text}}
      </label>
    </div>
  </div>
</template>

export default {
  props: {
    stem: String,
    options: Array,
    answer: String
  },
  data: () => ({
    option: null
  }),
  methods: {
    handleInput () {
      this.$emit('update:answer', this.option)
    }
  }
}

这一切都运行良好,除了如果然后因应用程序中发生的其他事情而更改userChoice的值这一事实,孩子不会这样做更新单选按钮。我必须在孩子中加入watch

  watch: {
    answer () {
      this.option = this.answer
    }
  }

但感觉有点多余,我担心发布事件来更新父母的数据实际上会导致孩子看到&#39;事件也开火了。在这种情况下,除了浪费几个周期之外它没有任何影响,但如果它记录或计算任何东西,那将是误报......

也许这是真正的双向绑定的正确解决方案(即动态父→子,以及子→父)。我是否错过了如何连接&#39; in&#39;和&#39; out&#39;双方的数据?

如果你想知道,父母想要改变用户选择的最常见情况是&#39;将回应一个明确的答案&#39;将userChoice设置回空字符串的按钮。这应该具有“不设置”的效果。所有的单选按钮。

1 个答案:

答案 0 :(得分:3)

你的构造有一些奇怪的东西不起作用,但如果你把它传播到发生变化的answer.sync组件,基本上q-radio就可以了。正确处理更改父级中的答案,但是要清除值,似乎需要将其设置为对象而不是null(我认为这是因为它需要可分配)。

更新options的设置是值得注意的事情。

我在answer中使用q-radio来控制其检查状态(v-model在广播中有特殊行为,这就是我将value与{{{{{{ 1}})。从您的评论中,v-model看起来希望拥有一个可以设置的值。您应该能够使用q-radio基于answer进行计算,而不是使用option数据项:get返回answer,{ {1}}执行set。我已更新了我的代码段以使用emit支持val加上我描述的计算机。 q-radio会发出proxyAnswer事件,这是update修饰符想要的事件。我还使用代理计算实现了.sync,但这只是为了让应该已经烘焙的行为进入q-radio

(我所描述的实际上是你对数据项和观察者所做的事情,但计算机是一种更好的方法来封装它。)

q-radio
new Vue({
  el: '#app',
  data: {
    userChoice: null,
    options: ['Blue', 'No, wait, aaaaargh!'].map(v => ({
      value: v,
      text: v
    }))
  },
  components: {
    question: {
      props: {
        stem: String,
        options: Array,
        answer: String
      },
      computed: {
        proxyAnswer: {
          get() {
            return this.answer;
          },
          set(newValue) {
            this.$emit('update:answer', newValue);
          }
        }
      },
      components: {
        qRadio: {
          props: ['value', 'val'],
          computed: {
            proxyValue: {
              get() {
                return this.value;
              },
              set(newValue) {
                this.$emit('input', newValue);
              }
            }
          }
        }
      }
    }
  },
  methods: {
    clearSelection() {
      this.userChoice = {};
    }
  }
});