vue3中的组件通信【1】《父子组件通信》

文章目录

    • 父子组件通信
    • (1)props / emits
        • ①props
        • 使用props
        • 获取非 Prop 的 Attribute
        • emits(子传父)
    • (2)v-model / emits
    • (3)ref / emits

父子组件通信

在这里插入图片描述

(1)props / emits

①props

Father.vue

<template><Childtitle="用户信息":index="1":uid="userInfo.id":user-name="userInfo.name"/>
</template><script>
import { defineComponent } from 'vue'
import Child from '@cp/Child.vue'interface Member {id: number,name: string
};export default defineComponent({// 需要启用子组件作为模板components: {Child},// 定义一些数据并return给template用setup () {const userInfo: Member = {id: 1,name: 'Petter'}// 不要忘记return,否则template拿不到数据return {userInfo}}
})
</script>

Child.vue

export default defineComponent({props: ['title','index','userName','uid']
})

加上类型限制:

export default defineComponent({props: {title: String,index: Number,userName: String,uid: Number}
})

在这里插入图片描述
如果你需要对某个 prop 允许多类型,比如这个 uid 字段,它可能是数值,也可能是字符串,那么可以在类型这里,使用一个数组,把允许的类型都加进去。

export default defineComponent({props: {// 单类型title: String,index: Number,userName: String,// 这里使用了多种类型uid: [ Number, String ]}
})

对部分字段设置为可选,并提供默认值:

export default defineComponent({props: {// 可选,并提供默认值title: {type: String,required: false,default: '默认标题'},// 默认可选,单类型index: Number,// 添加一些自定义校验userName: {type: String,// 在这里校验用户名必须至少3个字validator: v => v.length >= 3},// 默认可选,但允许多种类型uid: [ Number, String ]}
})

在这里插入图片描述

使用props

template 部分

<template><p>标题:{{ title }}</p><p>索引:{{ index }}</p><p>用户id:{{ uid }}</p><p>用户名:{{ userName }}</p>
</template>

script 部分

export default defineComponent({props: {title: String,index: Number,userName: String,uid: Number},// 在这里需要添加一个入参setup (props) {// 该入参包含了我们定义的所有propsconsole.log(props);}
})

获取非 Prop 的 Attribute

在 Child.vue 里,可以通过 setup 的第二个参数 context 里的 attrs 来获取到这些属性。

export default defineComponent({setup (props, { attrs }) {// attrs 是个对象,每个 Attribute 都是它的 keyconsole.log(attrs.class);// 如果传下来的 Attribute 带有短横线,需要通过这种方式获取console.log(attrs['data-hash']);}
})

emits(子传父)

Child.vue 绑定一个更新用户年龄的方法,那么在 Father.vue 里需要这么处理:

<template><Child@update-age="updateAge"/>
</template>
<script>
import { defineComponent, reactive } from 'vue'
import Child from '@cp/Child.vue'interface Member {id: number,name: string,age: number
};export default defineComponent({components: {Child},setup () {const userInfo: Member = reactive({id: 1,name: 'Petter',age: 0})// 定义一个更新年龄的方法const updateAge = (age: number): void => {userInfo.age = age;}return {userInfo,// return给template用updateAge}}
})
</script>

动态绑定 props 是用 :,绑定 emit 是用 @

Child.vue

export default defineComponent({emits: ['update-age']
})

接收 emits 时做一些校验
比如上面的更新年龄,只允许达到成年人的年龄才会去更新父组件的数据:

export default defineComponent({emits: {// 需要校验'update-age': (age: number) => {// 写一些条件拦截,记得返回falseif ( age < 18 ) {console.log('未成年人不允许参与');return false;}// 通过则返回truereturn true;},// 一些无需校验的,设置为null即可'update-name': null}
})

调用 emits

export default defineComponent({emits: ['update-age'],setup (props, { emit }) {// 2s 后更新年龄setTimeout( () => {emit('update-age', 22);}, 2000);}
})

(2)v-model / emits

  1. 在 Father.vue ,通过 v-model 向 Child.vue 传值
  2. Child.vue 通过自身设定的 emits 向 Father.vue 通知数据更新

Father.vue

<template><Childv-model:user-name="userInfo.name"/>
</template>

如果你要绑定多个数据,写多个 v-model 即可

<template><Childv-model:user-name="userInfo.name"v-model:uid="userInfo.id"/>
</template>

看到这里应该能明白了,一个 v-model 其实就是一个 prop,它支持的数据类型,和 prop 是一样的。

所以,子组件在接收数据的时候,完全按照 props 去定义就可以了。

export default defineComponent({props: ['title','index','userName','uid']
})

Child.vue

虽然 v-model 的配置和 prop 相似,但是为什么出这么两个相似的东西?自然是为了简化一些开发上的操作。

使用 props / emits,如果要更新父组件的数据,还需要在父组件定义好方法,然后 return 给 template 去绑定事件给子组件,才能够更新。

而使用 v-model / emits ,无需如此,可以在 Child.vue 直接通过 “update:属性名” 的格式,直接定义一个更新事件:

export default defineComponent({props: {userName: String,uid: Number},emits: ['update:userName','update:uid']
})

调用自身的 emits
在 Child.vue 配置好 emits 之后,就可以在 setup 里直接操作数据的更新了:

export default defineComponent({// ...setup (props, { emit }) {// 2s 后更新用户名setTimeout(() => {emit('update:userName', 'Tom')}, 2000);}
})

(3)ref / emits

在学习 响应式 API 之 ref 的时候,我们了解到 ref 是可以用在 DOM 元素与子组件 上面。

所以,父组件也可以直接通过对子组件绑定 ref 属性,然后通过 ref 变量去操作子组件的数据或者调用里面的方法。

比如导入了一个 Child.vue 作为子组件,需要在 template 处给子组件标签绑定 ref:

<template><Child ref="child" />
</template>

然后在 script 部分定义好对应的变量名称(记得要 return 出来):

import { defineComponent, onMounted, ref } from 'vue'
import Child from '@cp/Child.vue'export default defineComponent({components: {Child},setup () {// 给子组件定义一个ref变量const child = ref<HTMLElement>(null);// 请保证视图渲染完毕后再执行操作onMounted( () => {// 执行子组件里面的ajax函数child.value.getList();// 打开子组件里面的弹窗child.value.isShowDialog = true;});// 必须return出去才可以给到template使用return {child}}
})

子组件如果想主动向父组件通讯,也需要使用 emit


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部