【问题标题】:2-way binding in Vue 2.3 componentVue 2.3 组件中的 2 路绑定
【发布时间】:2017-06-06 15:51:55
【问题描述】:

我了解 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)
    }
  }
}

这一切都很好,除了如果 parent 然后由于应用程序中发生的其他事情而更改 userChoice 的值,孩子不会更新单选按钮.我必须在孩子中包含这个watch

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

但这感觉有点多余,我担心发出事件来更新父母的数据实际上会导致孩子的“观看”事件也被触发。在这种情况下,除了浪费几个周期外,它不会产生任何影响,但如果它正在记录或计数任何东西,那将是一个误报......

也许这是真正的 2 向绑定(即动态父 → 子,以及子 → 父)的正确解决方案。我是否错过了有关如何连接两侧的“输入”和“输出”数据的内容?

如果您想知道,想要更改“userChoice”的家长最常见的情况是响应“清除答案”按钮,该按钮会将userChoice 设置回空字符串。这应该具有“取消设置”所有单选按钮的效果。

【问题讨论】:

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


    【解决方案1】:

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

    更新 您对options 的设置是值得注意的,但它不起作用。

    我在q-radio 中使用answer 来控制其检查状态(v-model 在收音机中具有特殊行为,这就是我将valuev-model 结合使用的原因)。从您的评论来看,q-radio 似乎想要一个可以设置的值。您应该能够通过基于answer 的计算来做到这一点,您将使用它而不是您的option 数据项:get 返回answer,而set 执行emit。我已经更新了我的 sn-p 以使用 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 = {};
        }
      }
    });
    <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.min.js"></script>
    <div id="app">
      <question stem="What is your favourite colour?" :options="options" :answer.sync="userChoice" inline-template>
        <div>
          <h5>{{stem}}</h5>
          <div class="option" v-for="opt in options">
            <div>Answer={{answer && answer.text}}, option={{opt.text}}</div>
            <label>
            <q-radio :val="opt" v-model="proxyAnswer" inline-template>
              <input type="radio" :value="val" v-model="proxyValue">
            </q-radio>
            {{opt.text}}
          </label>
          </div>
        </div>
      </question>
      <button @click="clearSelection">Clear</button>
    </div>

    【讨论】:

    • 我对这些奇怪的东西很好奇 - 我知道我没有发布整个组件,但它对我来说运行良好。也许是因为 Quasar,其中包括 Webpack 和 Babel?我所有的代码都在单文件组件(.vue)中。但是,最重要的是,q-radio 是一个类星体组件 (quasar-framework.org/components/radio.html) 所以我不确定我是否可以实现你上面所做的 - 它只接受 v-modelval 道具,但你指定了 answer也有。当然,我不能将传入的answer 绑定到q-radio v-model,这会导致'mutating a prop' 错误。
    • 但是,根据你所说的,我认为它可以归结为我的另一个问题,它也没有一个非常明确的答案:stackoverflow.com/questions/43606355/… 真的我需要做的是传递answer 绑定到q-radiov-model。但目前,Vue 并没有提供一种我认为没有的无缝方式。
    猜你喜欢
    • 2018-07-09
    • 2018-01-26
    • 1970-01-01
    • 2019-03-26
    • 2017-10-09
    • 2018-07-03
    • 2019-03-26
    • 2017-06-05
    • 1970-01-01
    相关资源
    最近更新 更多