vue.js - Vue 2.3 组件中的双向绑定(bind)

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

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

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

父级有一个字符串数据元素 userChoice 来存储来自子组件的结果。 child 出示选项的问题和单选按钮。 child 的基本部分如下所示(我使用的是 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 的值, child 不会更新单选按钮。我必须在 child 中包含这个 watch:

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

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

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

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

最佳答案

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

更新 您对 options 的设置值得注意,但没有奏效。

我在 q-radio 中使用 answer 来控制其检查状态(v-model 在 radio 中有特殊行为,即为什么我将 valuev-model 结合使用)。从您的评论来看,q-radio 似乎想要一个可以设置的值。您应该能够使用基于 answer 的计算来做到这一点,您可以使用它来代替您的 option 数据项:get 返回answerset 执行emit。我已经更新了我的代码片段以将 val Prop 用于 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>

关于vue.js - Vue 2.3 组件中的双向绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44394625/

相关文章:

javascript - Lightgallery 只能打开一次(VueJs)

vuejs2 - 为什么,当您在 v-select 外部单击时,v-model 会重置为 null?验证

angular - 如何测试 Angular 2 双向绑定(bind)输入值

asp.net - ASP.NET 中什么是双向(2-way)数据绑定(bind)?

python - 使用 Vue.js 和 Python Flask 下载文件

javascript - Vuejs 如何创建多语言网站

css - 使用 v-for 指令插入时 Vue 不应用样式

angularjs - 使用 AngularJS 在 HighCharts 中单击事件和双向数据绑定(bind)

javascript - 如何将 VeeValidate 与 vue-i18n 集成?

javascript - 为什么在这种情况下我不能过滤本地 json 文件 (vuejs2)