以下这些方式都可以传递数据和方法,其中传递方法可以相当于反向传递,非常灵活。
父传子:props
1 2 3 4
| <!--假定父组件给子组件传递(数据、方法)--> <template> <child :msg="msg" :fun="fun"></child> </template>
|
1 2 3 4 5 6 7 8
| <!--子组件通过defineProps接收后可以直接使用--> <template> <div>{{msg}}</div> <button @click="fun">点击</button> </template> <script> defineProps(['msg', 'fun']) </script>
|
通过fun可以调用父组件的方法,从而进一步从子传数据到父组件中
子传父:emit和自定义事件
1 2 3 4 5 6 7 8 9
| <template> <!-- 父组件中给子组件绑定自定义事件和对应回调 --> <child @my-event="myEvent"></child> </template> <script> function myEvent(data) { console.log(data) } </script>
|
1 2 3 4 5 6 7 8
| <template> <!-- 子组件中通过$emit触发自定义事件 --> <button @click="emit('my-event', data)">点击</button> </template> <script> const data = ref('hello') defineEmits(['my-event']) </script>
|
emitter任意组件通信
某一组件的click事件绑定如emitter('my-event', data)
在另一组件中通过emitter.on('emitter', data => {})接收,最好在unmounted中销毁emitter.off('my-event')
v-model
在父组件中绑定v-model:data=datavalue,子组件中
1 2 3 4 5 6 7 8
| <template> <input :value="data" @input="$emit('update:data', $event.target.value)"> </template>
<script> defineProps(['data']) defineEmits(['update:data']) </script>
|
$attrs实现祖孙通信
由于子组件未通过defineProps接收的属性都存在attrs,最后由孙组件通过defineProps接收需要的方法和值
因此除了中间组件多了绑定$attrs外,其他和Props一样
parent实现父子通信
通过$refs可以获取子元素中所有通过defineExpose暴露的属性和方法
在父组件中绑定事件的回调函数,并传入$refs。
1 2 3 4 5
| let data = ref('hello') defineExpose({ data })
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <child ref="child"></child> <button @click="fun($ref)">点击</button> </template> <script> const child = ref() function fun(refs) { console.log(refs) // 结构是{child: {data(Proxy): 'hello'}} console.log(refs.child.data) // 会被深层解包,输出hello } </script>
|
$parent则适用于子组件获取父的属性和方法
provide和inject:祖先传后代
在祖先组件中通过provide提供数据,后代组件直接通过inject接收数据
1 2 3 4 5
| provide('dataContent', {data,fun})
const {data,fun} = inject('dataContent', {data: 'hello', fun: () => {console.log('hello')}})
|