vue自定义组件双向数据绑定

1、使用v - model指令(推荐方式)

  • 在 Vue 中,v - model是一个语法糖,它在组件上的使用实际上是自动扩展为特定的属性和事件。
  • 例如,创建一个自定义组件MyInput,它类似于原生的input标签可以实现数据双向绑定。
  • 首先,在组件内部,要通过model选项来定义v - model绑定的属性和对应的事件。
  • 以下是MyInput组件的示例代码:
<template>
  <input :value="value" @input="updateValue">
</template>
<script>
export default {
  name: 'MyInput',
  props: {
    value: String
  },
  methods: {
    updateValue(event) {
      this.$emit('input', event.target.value);
    }
  },
  model: {
    prop: 'value',
    event: 'input'
  }
};
</script>
  • 然后在父组件中使用MyInput组件并进行双向绑定:
<template>
  <div>
    <my - input v - model="message"></my - input>
    <p>Message: {{message}}</p>
  </div>
</template>
<script>
import MyInput from './MyInput.vue';
export default {
  components: {
    MyInput
  },
  data() {
    return {
      message: 'Hello'
    };
  }
};
</script>
  • 在这里,MyInput组件内部通过props接收value属性,这个属性是由父组件通过v - model传递过来的。当input元素的input事件触发时,组件内部通过$emit触发input事件,并将新的值传递给父组件。父组件中的v - model会自动更新绑定的message数据。

2、手动实现双向绑定(不使用v - model语法糖)

  • 还是以一个类似输入框的组件为例。在父组件中,将数据传递给子组件作为属性,同时给子组件传递一个更新数据的方法。
  • 子组件代码如下:
<template>
  <input :value="inputValue" @input="handleInput">
</template>
<script>
export default {
  name: 'CustomInput',
  props: {
    inputValue: String
  },
  methods: {
    handleInput(event) {
      this.$emit('updateValue', event.target.value);
    }
  }
};
</script>
  • 父组件代码:
<template>
  <div>
    <custom - input :inputValue="parentValue" @updateValue="updateParentValue"></custom - input>
    <p>Parent value: {{parentValue}}</p>
  </div>
</template>
<script>
import CustomInput from './CustomInput.vue';
export default {
  components: {
    CustomInput
  },
  data() {
    return {
      parentValue: 'Initial value'
    };
  },
  methods: {
    updateParentValue(newValue) {
      this.parentValue = newValue;
    }
  }
};
</script>
  • 在这个例子中,父组件将parentValue作为inputValue属性传递给子组件。子组件在input事件触发时,通过$emit触发updateValue事件,并将新的值传递给父组件。父组件监听updateValue事件,调用updateParentValue方法来更新parentValue数据。

3、 .sync修饰符

  1. 基本概念
  • 在 Vue 中,.sync是一个语法糖,主要用于在父子组件之间实现双向数据绑定。它提供了一种简洁的方式来让子组件能够修改父组件中的数据。
  • 例如,我们有一个父组件ParentComponent和一个子组件ChildComponent,父组件中有一个数据属性count,当我们想要子组件能够修改这个count属性时,可以使用.sync修饰符。
  • 父组件代码如下:
<template>
  <div>
    <p>Count in Parent: {{count}}</p>
    <child - component :count.sync="count"></child - component>
  </div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      count: 0
    };
  }
};
</script>
  • 子组件代码如下:
<template>
  <div>
    <button @click="incrementCount">Increment Count in Child</button>
  </div>
</template>
<script>
export default {
  props: {
    count: Number
  },
  methods: {
    incrementCount() {
      this.$emit('update:count', this.count + 1);
    }
  }
};
</script>
  1. 工作原理
  • 当使用.sync修饰符时,实际上是一个语法简写。对于<child - component :count.sync=“count”></child - component>这样的代码,它等价于<child - component :count=“count” @update:count=“count = $event”></child - component>。
  • 在子组件内部,当需要修改父组件传递过来的count属性时,通过$emit发送一个update:count事件,并且将新的值作为参数传递出去。父组件接收到这个事件后,就会将count属性更新为新的值,从而实现了双向数据绑定。

4、.sync 与 v - model 的比较

  • 相似点:
    • 它们都可以实现父子组件之间的数据双向绑定。都是一种语法糖,帮助开发者更简洁地实现数据交互。
  • 不同点:
    • v - model主要用于表单元素或者类似表单元素的自定义组件,并且在组件内部默认绑定的属性是value,对应的事件是input(当然可以通过model选项进行修改)。而.sync可以用于更广泛的数据双向绑定场景,只要遵循update:propName这样的事件命名规则就可以。
    • v - model在一个组件上通常只用于一个属性的双向绑定,而.sync可以用于多个属性的双向绑定,例如<component :prop1.sync=“data1”:prop2.sync=“data2”>。
### Vue3 中自定义组件实现双向数据绑定 #### 使用 `v-model` 指令(推荐方式) 在 Vue3 中,通过 `v-model` 实现自定义组件双向数据绑定是最简洁的方式。当使用 `v-model` 绑定到一个子组件上时,默认情况下会监听名为 `update:modelValue` 的事件并将其值作为新的输入传递给父级。 ```html <!-- 子组件 MyInput.vue --> <template> <input :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script> export default { props: ['modelValue'] } </script> ``` ```html <!-- 父组件 ParentComponent.vue --> <template> <my-input v-model="parentData"></my-input> </template> <script> import MyInput from './MyInput.vue'; export default { components: { MyInput }, data() { return { parentData: '' }; } }; </script> ``` [^1] #### 手动实现双向绑定(不使用 `v-model` 语法糖) 如果不采用 `v-model` 这样的语法糖,则需要显式地处理 prop 和 event 来完成同样的功能: ```html <!-- 子组件 CustomCheckbox.vue --> <template> <label> <input type="checkbox" :checked="isChecked" @change="$emit('change', !isChecked)"> {{ label }} </label> </template> <script> export default { props: { checked: Boolean, label: String }, computed: { isChecked() { return this.checked; } } } </script> ``` ```html <!-- 父组件 App.vue --> <template> <custom-checkbox :checked="isAgreed" @change="toggleAgreement">同意条款</custom-checkbox> </template> <script> import CustomCheckbox from './CustomCheckbox.vue' export default { name: 'App', components: { CustomCheckbox }, data () { return { isAgreed: false } }, methods: { toggleAgreement (newValue) { this.isAgreed = newValue } } } </script> ``` [^2] #### `.sync` 修饰符 `.sync` 是一种简化写法用于同步父子组件之间的状态更新。它允许我们更方便地将多个属性与相应的事件关联起来。不过需要注意的是,在现代 Vue 应用中通常建议优先考虑 `v-model` 或者直接使用事件来代替 `.sync`。 ```html <!-- 子组件 ChildWithSyncModifier.vue --> <template> <div> <button @click="$emit('update:message', message + '!')">增加感叹号</button> </div> </template> <script> export default { props: ['message'] } </script> ``` ```html <!-- 父组件 UsingSyncModifier.vue --> <template> <child-with-sync-modifier :message.sync="greetingMessage"></child-with-sync-modifier> </template> <script> import ChildWithSyncModifier from './ChildWithSyncModifier.vue' export default { components: { ChildWithSyncModifier }, data () { return { greetingMessage: '你好' } } } </script> ``` #### `.sync` 与 `v-model` 的比较 两者都可以用来创建双向的数据流,但是它们之间存在一些差异: - **适用范围**: `v-model` 主要针对表单控件类元素;而 `.sync` 则适用于任何类型的 prop。 - **默认行为**: 对于 `v-model`, 默认事件名称为 `input`; 而对于 `.sync`, 需要在 emit 时指定完整的路径如 `update:propName`. - **灵活性**: 如果只需要简单的布尔值或其他单一类型的状态共享, `.sync` 更加直观; 若涉及到复杂对象或数组的操作则可能更适合使用 `v-model`.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值