【Vue3】父子组件双向数据绑定

Vue3 — 父子组件实现数据双向绑定

1.基础父子组件传值 — props + 自定义事件 + defineEmit + emit

1.1 父组件 ⇨ 子组件

直接通过向子组件身上添加方法的方式传递数据:

<uploadCom
    :limit="1"
    :policy="() => staffGetOssUploadPolicy()"
>uploadCom>

其中,limitpolicy就是定义好的变量名,子组件用props接收数据时,需要用正确的变量名来接收,如下:

const props = defineProps({
	limit: {
        type: Number,
        default: 100,
    },
    policy: {
        type: Function,
        default: async () => {},
    }
})

// 使用
let limit = props.limit
const policy = props.policy

需要注意的是,**Vue3 中通过defineProps方法定义的所有 props,默认为响应式!**这是 Vue3 中新增的一个特性。

因此,我们不再需要像 Vue2 中一样,为这些 props 单独定义watch方法去监听其变化并实时更新!

Props 响应式的工作原理如下:当父组件的 Props 改变时,相应的子组件会接收到通知并进行更新。这样,当Props 更改后,父组件和子组件的数据就可以保持一致。

1.2 子组件 ⇨ 父组件

注意:

由于vue数据传递是单向数据流,子组件没有权利修改父组件传过来的数据,只能请求父组件对原始数据进行修改,即用 emit 通知父组件去修改。

首先,需要在父组件中的子组件上绑定响应 emit 通知的事件:

<uploadCom
    :limit="limit"
    @updateLimit="updateLimit"
>uploadCom>

然后定义该事件的处理函数:

// 传入的数据
const limit = ref(1)

// 事件处理函数
const updateLimit = (num) => {
	limit.value = num;
}

而在子组件中,首先需要注册一个 emit 方法,然后触发指定的事件即可:

const emit = defineEmits(["updateLimit"])

emit("updateLimit", 2);

这样父组件中就会触发事件调用响应函数,从而实现子组件向父组件传值!

2.父子组件双向数据绑定 — v-model + props + emit

在上面的基础通信方式中,实际上是利用了绑定并触发自定义事件来通知父组件修改原数据。

当子组件通知父组件更新的值,正好也是父组件通过props传递给子组件的值时,此时可以在父组件中用v-model在该属性上进行双向绑定。如下:

<uploadCom
    v-model:limit="limit"
>uploadCom>

此时,父组件中不再需要绑定自定义事件,也不需要定义响应函数!

而子组件中,直接注册一个 emit 方法,然后通过用emit("update:xxx", param)即可通知父组件更新指定变量名的数据!

const emit = defineEmits(["update:limit"])

// 个人理解:update:xxx 是一个内置的事件,所以我们不再需要进行手动的绑定、配置处理函数等工作
emit("update:limit", 2);

这样,我们就达成了一种类似于数据双向绑定的效果。

为什么说是类似?因为数据既可以从父组件流向子组件,也可以从子组件流向父组件(但实际上并不是),且也是通过v-model命令实现的。

补充说明

当使用父子组件双向绑定时,若我们没有指定变量名:

<TestCom v-model="test1">TestCom>        // 未指定变量名
<TestCom v-model:test2="test2">TestCom>  // 指定变量名

则此时在子组件中用 props 接收数据时,默认用modelValue这个属性来接收未命名的数据:

const props = defineProps({
	// 父组件 v-model 时test1数据没有指定参数名,所以此时属性modelValue会接收到test1
	modelValue:{ 
		type:String,
		default: 'test'
	},
    // 而已命名的数据test2则由对应名称的属性来接收
	test2: {
		type: String,
		default: 'aaa'
	}
})

那么要更新这个未命名的数据时该如何操作呢?实际上是同样的方法:

const emit = defineEmits(["update:modelValue"])
emit("update:modelValue", 'update!');

这种情况实际上是很常见的,因为有些公共组件并不能确定父组件中传入的数据的名称,无法通过统一的名称来接收数据,此时就需要用到默认的modelValue了。

你可能感兴趣的:(Vue3,vue.js,前端,javascript)