Vue双向道具绑定

Dio*_*lor 3 vue.js vue-component vuejs2

以下是我目前的结构(不起作用).

父组件:

<template>
<field-input ref="title" :field.sync="title" />
</template>

<script>
import Field from './input/Field'
export default {
  components: {
    'field-input': Field
  },
  data() {
    return {
      title: {
        value: '',
        warn: false
      }
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

子组件:

<template>
<div>
  <input type="text" v-model="field.value">
  <p v-bind:class="{ 'is-invisible' : !field.warn }">Some text</p>
</div>
</template>

<script>
export default {
  props: ['field']
}
</script>
Run Code Online (Sandbox Code Playgroud)

要求是:

  • 如果父项的父数据title.warn值在父项中发生更改,class则应更新子项的绑定(field.warn).
  • 如果孩子的<input>更新(field.value),title.value则应更新父母的.

实现这一目标的最干净的工作解决方案是什么?

acd*_*ior 9

不要将子组件绑定<input>到父组件title.value(如<input type="text" v-model="field.value">).这是一种已知的不良做法,能够让您的应用数据流更难理解.

要求是:

  • 如果父项的父数据title.warn值在父项中发生更改,class则应更新子项的绑定(field.warn).

这很简单,只需创建一个warn道具并将其从父级传递给子级.

父母(将道具传给孩子):

<field-input ref="title" :warn="title.warn" />
Run Code Online (Sandbox Code Playgroud)

子/模板(仅使用道具 - 阅读):

<p v-bind:class="{ 'is-invisible' : !warn }">Some text</p>
Run Code Online (Sandbox Code Playgroud)

子/ JavaScript(声明道具及其预期类型):

export default {
  props: {warn: Boolean}
}
Run Code Online (Sandbox Code Playgroud)

请注意,在模板中它!warn不是!title.warn.此外,您应该声明warnBooleanprop,因为如果您不这样做,则父级可能会使用<field-input warn="false" />会产生意外结果的字符串(例如)(!"false"实际上false不是true).

  • 如果孩子的<input>更新(field.value),title.value则应更新父母的.

这里有几个可能的选项(比如.sync在道具中使用),但我认为在这种情况下最干净的解决方案是创建一个value道具并使用v-model道具.

父(使用绑定prop v-model):

<field-input ref="title" v-model="title.value" />
Run Code Online (Sandbox Code Playgroud)

子/模板(使用prop作为初始值并input在更改时发出事件):

<input type="text" :value="value" @input="$emit('input', $event.target.value)">
Run Code Online (Sandbox Code Playgroud)

子/ JavaScript(声明道具及其预期类型):

export default {
  props: {value: String}
}
Run Code Online (Sandbox Code Playgroud)

点击此处查看这两个解决方案的工作演示.


San*_*Ben 6

实现双向数据绑定有以下几种方式:

  1. 在组件上使用props
  2. 使用v-model 属性
  3. 使用同步修饰符
  4. 使用Vuex

对于双向绑定,请记住,它会导致一系列难以维护的突变,引用自文档:

不幸的是,真正的双向绑定会产生维护问题,因为子组件可以对父组件进行变异,而该变异的来源在父组件和子组件中都不明显。

以下是可用方法的一些详细信息:

1.) 在组件上使用 props

通常不建议使用 props 进行双向绑定,但可能,通过传递一个对象或数组,您可以更改该对象的属性,并且它将在子级和父级中观察到,而 Vue 不会在控制台中打印警告。

每次更新父组件时,子组件中的所有 props 都会刷新为最新值。这意味着你不应该尝试改变子组件内的道具

道具易于使用,是解决大多数常见问题的理想方式。
由于Vue 观察变化的方式,对象上的所有属性都需要可用,否则它们将不会是响应式的。如果在 Vue 完成使它们成为可观察的'set'之后添加了任何属性,则必须使用它们。

 //Normal usage
 Vue.set(aVariable, 'aNewProp', 42);
 //This is how to use it in Nuxt
 this.$set(this.historyEntry, 'date', new Date());
Run Code Online (Sandbox Code Playgroud)

该对象将对组件和父级都是反应式的:

我将一个对象/数组作为道具传递,它自动双向同步 - 更改子项中的数据,更改父项中的数据。

如果通过 props 传递简单的值(字符串、数字),则必须显式使用.sync 修饰符

引自--> /sf/answers/2500672191/

2.) 使用 v-model 属性

v-model 属性是一种语法糖,可以在父子之间轻松进行双向绑定。它与同步修饰符的作用相同,只是它使用特定的道具和特定的事件进行绑定

这个:

 <input v-model="searchText">
Run Code Online (Sandbox Code Playgroud)

与此相同:

 <input
   v-bind:value="searchText"
   v-on:input="searchText = $event.target.value"
 >
Run Code Online (Sandbox Code Playgroud)

其中 prop 必须是value并且 event 必须是input

3.) 使用同步修饰符

sync 修饰符也是语法糖,与 v-model 的作用相同,只是 prop 和 event 名称由正在使用的任何内容设置。

在父级中,它可以按如下方式使用:

 <text-document v-bind:title.sync="doc.title"></text-document>
Run Code Online (Sandbox Code Playgroud)

可以从子进程发出一个事件以通知父进程任何更改:

 this.$emit('update:title', newTitle)
Run Code Online (Sandbox Code Playgroud)

4.) 使用 Vuex

Vuex 是一个可以从每个组件访问的数据存储。可以订阅更改。

通过使用 Vuex 存储,可以更容易地查看数据突变的流程,并且它们是明确定义的。通过使用vue 开发人员工具,可以轻松调试和回滚所做的更改。

这种方法需要更多的样板文件,但如果在整个项目中使用,它就会成为一种更清晰的方式来定义如何进行更改以及从何处进行更改。

请参阅入门指南