【问题标题】:Understanding Vue JS v-model two way binding理解 Vue JS v-model 两种方式绑定
【发布时间】:2019-09-16 14:40:41
【问题描述】:

我一直在尝试了解 Vue 的 v-model 如何与自定义输入以及常规输入组件一起工作。

我已经看到v-model 与组件和模板中的值相关联的示例,并且这两个值都会不同。我觉得这很令人困惑,我认为这可能是对“双向绑定”的误解。您如何将输入绑定到两个值。

例子:

//模板中的v-model

const myCustomInput = ('my-custom-input', {
  data() {
    return {
      myObj: 'hello'
    }
  },
  template: `<input v-model="myObj" >`
});

//组件中的v-model

<my-custom-input v-model="someOtherObj.str">

我已经看到有两个像这样的 v-model 的例子,它们在模板级别和组件上都定义了不同的值。

然而,当看到这个SO post 时,@asemahle 的回答似乎更合乎逻辑。此外,官方 Vue 文档甚至在模板和组件上都没有 2 个单独的 v-model Vue JS component basics

在后面的例子中,这似乎更合乎逻辑,因为只定义了一个 v-model 并绑定到输入组件,而不是两个。

第一个例子不正确吗?如果不是,有人可以更清楚地解释它是如何工作的。我似乎找不到任何关于将两个单独的v-models 用于一个输入的真正好的文档。

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:

    双向绑定是指将模板html绑定到一个对象。在您的示例中,您试图将其绑定到两个单独的值,正如您所说,这只是对术语双向绑定的误解。

    在双向绑定中,您仍然只会将一个 v-model 绑定到一个数据元素。 “双向”部分是指当您在文本框中键入时,一旦 v-model 绑定到数据属性,数据属性也会更改。此外,如果您更改数据属性,可能通过方法或API 调用,然后文本框也将反映该数据更改,因此是双向数据绑定。

    【讨论】:

    • 是的,我也是这么想的,但是我在网上看到太多例子,定义了两个v-models
    • 愿意分享一个例子吗?也许我可以看到帖子的去向。如果你有一个 v-model 绑定到两个单独的数据属性,如果这两个数据属性都包含数据,那么文本框会显示什么?它会连接它们吗?如果是这样,如果您在绑定到两个数据属性的文本框中键入内容会发生什么,这两个数据属性都会复制文本框。
    【解决方案2】:

    在您提供的示例代码中,您有一个组件,其模板在本机输入中包含 v-model

    template: `<input v-model="myObj" >`
    

    这意味着input 是(双向)绑定到myObj:对myObj 值的更改将反映在输入中,对输入的更改将更新数据项。

    然后,您将拥有该组件的一个实例,上面带有 v-model。该组件将接收到一个value 的prop,并有望通过emitinput 事件实现双向绑定。 v-model on components is described here.

    您没有“绑定到两个值的输入”,但您可能有一个毫无意义的绑定,因为您绑定的两件事(显然)是不相关的。您可能想要的是让您的组件充当值的传递,以便您可以将其视为几乎像原生inputThis example 就是这样做的。

    custom input in the docsv-model 放在组件上,并使用来自本机input 元素的valueemit input 的显式绑定。您可以v-model 替换为可设置的计算值,就像我在上一段中链接的示例中所做的那样。 get 返回valueset 执行emit

    【讨论】:

    • 我写的差不多。我只是想确认拥有两个 v-model 是否正确,因为我在 Internet 资源上随处可见这样的示例。但这似乎是源于“双向绑定”的误解
    • 拥有任意数量的v-models 都是正确的,每个接受值的实体限制为一个。
    • 拥有any number of v-models 是什么意思。如果您的意思是模板和组件中有多个v-model,我认为这是错误的,并且可能是对我在操作中所述的两种方式绑定的误解。我按照官方 Vue JS 文档制作了自定义输入组件,它似乎工作得很好。无论它来自哪个组件,它都会绑定数据属性
    • 一个组件可以包含多个具有v-model 绑定的实体。它们不必相互关联。充当传递是 v-model 的一个特殊用例,它仍然需要将它们绑定到不同的变量。
    • 我在答案中添加了最后一段,将v-model 解释为传递。
    【解决方案3】:

    尝试在子组件中使用watch
    家长:

    <OptionCarouselCards                                                   
      :selected-values="bevarageSelected"
      @optionSelected="getBeverage"
    />
    

    孩子:

    <v-slide-group
      v-model="selected"
      @change="onSelect"
    >
    
    
    export default {
      props: {
        selectedValues: {
          type: [Array, Number],
          required: false,
          default: -1
        } 
     },
     data () {
       return {
         selected: this.selectedValues
       }
     },
     watch: {
       selectedValues (selectedValues) {
         this.selected = selectedValues
     }
    },
    methods: {
      onSelect (event) {
        this.$emit('optionSelected', this.selected)
      }
     }
    }
    

    【讨论】:

      【解决方案4】:

      对于多个双向绑定组件参数,您可以尝试这样的事情(vue 3):

      <ChildComponent v-model:arg2="parentVariable1"  v-model:arg1="parentVariable2" />
      

      在子组件中更改值后,您只需调用:

      this.$emit("update:arg1","some_value") 
      or 
      this.$emit("update:arg2","some_value_2") 
      

      更多详情请见vue docs

      【讨论】: