Vue3中父、子组件间传递数据与子组件内部数据的传递

799 阅读1分钟

## 父、子组件通过provide/inject传递数据

在父组件中放入子组件均会用到的变量。这种做法的好处是无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。

<script lang='ts'> 
  import { ref, provide } from 'vue' 
  export default { 
    setup(){ 
      const asideVisible = ref(false) 
      provide('to_child',asideVisible) 
      } 
    } 
</script>

在子组件中获取,return出来就可以在组件中使用了。

<script lang='ts'> 
  import { Ref, inject } from 'vue' 
  export default { 
    setup(){ 
      const asideVisible = inject<Ref<boolean>>('to_child') 
      return { asideVisible } 
      } 
    } 
</script>

子组件内部数据的传递

通过在组件中使用ref定义数据的初始状态和修改数据的方法来实现,注意读取ref的值时要使用checked.value

<template> 
  <button @click="toggle" :class="{checked}"> 
  //如果checked为真,class加上checked 
  <span></span> 
  </button> 
</template> 

<script lang="ts"> 
import { ref } from 'vue' 

export default { 
  setup(){ 
    const checked = ref(false) 
    const toggle = ()=>{ checked.value = !checked.value } 
    return {checked, toggle} 
    } 
  } 
</script>

父子组件通信

在父组件中的子组件上添加事件,控制子组件的状态。

<template> 
    <div> <Child :value='y' @input='y = $event' /> 
    //v-bind:value = 'y' </div> 
</template> 
    
<script lang='ts'> 
    import Child from '@/lib/Child.vue' 
    export default{ 
      components:{ Child }, 
      setup(){ const y = ref(true) 
        return { y } 
      } 
    } 
</script>

在子组件中,使用props来获取value。但是不能直接使用props.value来修改,只能通过setup的第二个参数context的方法emit来修改数据。

<button @click="toggle" :class="{checked:value}">
    ... 
    ... 
    export default { 
        props:{ value:Boolean //直接就可以展示在子组件的template中,与setup无关。 },
        setup(props,context){ 
            const toggle = ()=>{ 
                context.emit('input',!props.value) 
                //通过context.emit 触发input事件 实现父子组件通信 } 
                return { toggle } 
            } 
        }

内部数据 vs 父子数据

子组件中使用ref定义数据的初始状态并创建修改数据的方法。这种方法简单,但不能与外部交流。

父子间的数据传递:如上例,父组件在使用的子组件上添加:value = 'y'(初始状态) 以及 @input = 'y = $event'。子组件通过props.value来获得数据的初始值,通过自定义方法,通过设定context.emit触发input事件来修改。父组件通过@input = 'y = $event'来拿到emit触发事件的结果,即props.value = !props.value。将value的值变为!value。从而实现组件通信。

input只是为了好理解,真正的事件名字与value有关,叫做update:value

父组件上应该这样写:

<Child :value='y' @update:value='y = $event' /> 
//而这种写法可以写成
<Child v-model:value='y' /> 

同时子组件也应该把input改为update:value

 setup(props,context){
    const toggle = ()=>{
      context.emit('update:value',!props.value)     //通过context.emit 触发update:value事件  实现父子组件通信
    }
    return { toggle }
  } 

如果写成

<Child v-model='y' /> 

相当于传modelValueprops而非自定义的propsName