Vue | 自定义组件双向绑定基础用法

Vue | 自定义组件双向绑定基础用法

vue 中,由于单向数据流,常规的父子组件属性更新,需要 在父组件绑定相应属性,再绑定相应事件,事件里去做更新的操作,利用语法糖 可以减少绑定事件的操作。

这里就简单的梳理一下vue提供的双向更新的语法糖用法(水一篇,为了节省篇幅只给了关键部分的代码)。

vue2

v-model

基础使用
<!-- 父组件 -->
<template>
  <div class="vmodel-test">
  	V-model 测试
    <hr />
    v-model 默认基础类型值 | <span>{{ val }}</span>
    <inner v-model="val"></inner>
  </div>
</template>

export default {
  name: "VmodelTest",
  components: { inner },
  data() {
    return {
      val: 11111,
    }
  }
}  
<!-- 子组件 -->
<template>
  <div class="inner">
    <button @click="onUPdate">更改</button>
  </div>
</template>
<script>
export default {
  name: "Inner",
  props: {
    value: {
      type: [String, Number],
      default: "",
    },
  },
  data() {
    return {};
  },
  methods: {
    onUPdate() {
	  // 更新
      this.$emit("input", new Date().toLocaleString());
    },
  },
};
</script>

在这里插入图片描述

简单总结就是, 对于父组件 v-model 绑定的值,子组件 需要 定义一个 value 的props,然后更新时使用 input 事件 去更新值,适用于基础类型和对象类型,⚠️需要注意的是这种更新是全量更新(覆盖式)

比如我 v-model 接受的是一个对象,我只想更新对象的 a 属性

// 更新
this.$emit("input", {
  ...this.value,
  a: new Date().toLocaleString(),
});
自定义更新事件名

model: 允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。API — Vue.js

input 是默认事件,可以自定义,需要 在子组件 写一个 model(2.2新增) 属性去更改

model: {
  prop: "value", // 指定是更新value
  event: "custom-update-value", // 一般以 update:value 命名
},
props: {
  value: {
    type: [Array, Object],
    default: () => {},
  },
},

那么 更新时只需要用新的事件名,⚠️原来默认input事件已经失效

// 更新
this.$emit("custom-update-value", {
  ...this.value,
  a: new Date().toLocaleString(),
});

sync 修饰符

基础使用

sync 修饰符也双向更新的一个方法,更适用于多个属性需要双向更新的场景

首先在父组件中绑定绑定的属性后面,跟上sync修饰符

sync 修饰符 | <span>{{ modelValue3 }}</span>
<inner3 :model-value.sync="modelValue3"></inner3>

子组件更新时, 事件名 update: 拼上 属性名

//...
props: {
  modelValue: {
    type: [Array, Object],
    default: () => {},
  },
},
//...
// 更新
this.$emit("update:modelValue", {
  ...this.value,
  b: [1, new Date().toLocaleString()],
});

在这里插入图片描述

也是全量更新, ⚠️注意这种方式不支持 model 方式自定义事件名

一次性绑定多个(v-bind.sync)

支持 v-bind 一次性绑定多个值的方式

<!--  -->
sync 修饰符 对象解构传入(vbind) | <span>{{ modelValue4 }}</span>
<inner4 v-bind.sync="modelValue4"></inner4>

//...(节省篇幅,只给出相应的data)
modelValue4: {
  a: { val: 111 },
  b: [1, 2]
},
/** 子组件 **/
props: {
  a: {
    type: [Array, Object],
    default: () => {},
  },
  b: {
    type: [Array, Object],
    default: () => {},
  },
},
//...
// 更新
this.$emit("update:a", {
   ...this.a,
   val: new Date().toLocaleString(),
});
this.$emit("update:b", [1, new Date().toLocaleString()]);

在这里插入图片描述

vue3

v-model

基础使用

父组件传的v-model,子组件用 modelValue 接收

<!-- 父组件 -->
v-model 默认-对象类型值 | <span>{{ modelValue1 }}</span>
<inner1 v-model="modelValue1"></inner1>

子组件 使用 update:modelValue 更新值

<!-- 子组件 -->
<script setup lang='ts'>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const onUPdate = () => {
   // 更新
   emit("update:modelValue", {
    ...props.modelValue,
    a: new Date().toLocaleString(),
  });
}
</script>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

均是全量更新

绑定多个值
<!-- 父组件 -->
v-model 绑定多个值 | <span>{{ modelValue2 }} | {{ modelValue21 }}</span>
<inner2 
    v-model:modelCusValue="modelValue2" 
    v-model:modelCusValue1="modelValue21"
></inner2>
/** 子组件 **/
<script setup lang='ts'>
  const props = defineProps(['modelCusValue', 'modelCusValue1'])
  const emit = defineEmits(['update:modelCusValue', 'update:modelCusValue1'])

  const onUPdate = () => {
      // 更新
	  emit("update:modelCusValue", {
        ...props.modelCusValue,
        a: new Date().toLocaleString(),
      });
      emit("update:modelCusValue1", {
        ...props.modelCusValue1,
        a: new Date().toLocaleString(),
      });
  }
</script>

在这里插入图片描述

也是全量更新

defineModel

基础使用

此宏为 3.4 新增,使用起来比前面的方式稍微简洁一些。装个 vue-eslint-parser 且在 vite.config.ts 做如下配置 plugins, 避免编译器报错。

export default defineConfig({
  plugins: [
    vue({
      // 开启 definModel
      script: { defineModel: true }
    }),
  ]
  //...
})
<!-- 父组件 -->
defineModel() | <span>{{ modelData }} | {{ modelData1 }} | {{ modelData2 }}</span>
<inner3
    v-model="modelData" 
    v-model:modelData1="modelData1"  
    v-model:modelData2="modelData2"
></inner3>
//...
const modelData1 = ref({
  a: 1,
  b: [1, 2],
})
const modelData2 = ref({
  a: 1,
  b: [1, 2],
})

此方法在子组件使用 直接使用 属性 value 赋值就行了

<script setup lang='ts'>
type modelValueType = {
  a: number | string,
  b: Array<number>
}
let model = defineModel<modelValueType>({ required: true })
let model1 = defineModel<modelValueType>('modelData1', { required: true })
let model2 = defineModel<modelValueType>('modelData2', { 
  required: true, 
  type: Object,
  default: { a: 0, b: [2,3] } 
})

const onUPdate = () => {
  // 更新
  model.value = {
    ...model.value,
    b: [2, 1],
    a: new Date().toLocaleString()
  }
  model1.value.a = new Date().toLocaleString();
  model2.value.a = new Date().toLocaleString();
  // 或者如下方式
  // Object.assign(model.value, { a: new Date().toLocaleString() });
}
</script>

这种方式 支持单个属性更新,全量更新只需全部赋值,比较灵活
在这里插入图片描述

最后

若行文有误,望评论区交流。

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 中,父子组件之间可以通过 props 和 events 实现数据的双向绑定。具体的步骤如下: 1. 在父组件中定义一个数据,并将其作为 props 传递给子组件: ```vue <template> <div> <child-component :message="message" @update-message="updateMessage"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { message: '' }; }, methods: { updateMessage(value) { this.message = value; } } }; </script> ``` 2. 在子组件中使用 props 接收父组件传递的数据,并使用 $emit 方法触发一个自定义的事件来通知父组件更新数据: ```vue <template> <div> <input type="text" v-model="childMessage" @input="updateParentMessage"> </div> </template> <script> export default { props: ['message'], data() { return { childMessage: this.message }; }, methods: { updateParentMessage() { this.$emit('update-message', this.childMessage); } }, watch: { message(newValue) { this.childMessage = newValue; } } }; </script> ``` 在上述示例中,父组件通过 :message="message" 将自己的 message 数据以 props 的方式传递给子组件。子组件接收到这个父组件的 message 数据后,使用 v-model 绑定到一个本地的 childMessage 变量上。当子组件中的输入框内容发生变化时,通过 @input 事件触发 updateParentMessage 方法,该方法使用 $emit 触发自定义事件 'update-message' 并将子组件的 childMessage 数据作为参数传递给父组件。父组件接收到这个事件后,触发 updateMessage 方法来更新自己的 message 数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值