vue3组件通信的七种方式

152 阅读1分钟

记性太差了,学了的东西过几天就忘了,现在打算把学习的内容都整理成笔记,现在给大家分享一下自己在学习组件通信时候的笔记吧

  1. props 父 => 子

    //父组件
    <template>
        <List :list="list"/>
    </template><script setup>
    import { ref } from 'vue';
    import List from './List.vue'//const list = ref(['JavaScript', 'HTML', 'CSS'])//要把这个list传给子组件
    </script>
    ​
    //子组件
    <script setup>
        import { defineProps } from 'vue'
        const props = defineProps({ // defineProps专门用来解析父组件传递的数据
      list: {
        type: Array,
        default: () => []
      }
    })
    </script>
    
  2. emit 子 => 父

    <!--子组件(名为Child)-->
    <template>
        div class="wrap">
        <input type="text" class="form-control" v-model="value">
        <button class="btn" type="button" @click="handleAdd">添加</button>
      </div>
    </template><script setup>
        import { ref, defineEmits } from 'vue';
    ​
      const value = ref('')
        const emits = defineEmits(['add'])//定义一个事件的名称为emits
        const handleAdd = () => {
            emits('add',value.value) //发散名为add,值为value.value的事件
            value.value = ''
        }
    </script><!--父组件-->
    <template>
    <!-- 接收add,给它绑定一个handleAdd事件 -->
      <ChildVue @add = 'handleAdd' />
    </template><script setup>
     import ChildVue from './Child.vue'
     import { ref } from 'vue'
     
     const list = ref (['a','b','c'])
     const handleAdd = value => {//会有一个回调参数
      list.push(value)
     }
    </script>
    
  3. v-model 子 => 父

    <!--子组件(名为Child)-->
    <template>
        div class="wrap">
        <input type="text" class="form-control" v-model="value">
        <button class="btn" type="button" @click="handleAdd">添加</button>
      </div>
    </template><script setup>
    import { ref,defineEmits,defineProps } from 'vue'
        const props = defineProps({
            list:{
                type:Array,
                default:() => []
            }
        })
        
        const emits = defineEmits('update:list')//这里update是固定写法,list为从父组件接受过来的数据
        const arr = props.list
        const handleAdd = () => {
            arr.push(value.value)
            emits('update:list',arr)
            value.value = ''
        }
    </script><!--父组件-->
    <template>
    <!-- 只要给v-model添加一个list属性就可以了 -->
      <ChildVue v-model:list = 'list' />
    </template><script setup>
     import ChildVue from './Child.vue'
     import { ref } from 'vue'
     
     const list = ref (['a','b','c'])
    </script>
    
  4. refs 子 => 父

    <!--子组件(名为Child)-->
    <template>
        div class="wrap">
        <input type="text" class="form-control" v-model="value">
        <button class="btn" type="button" @click="handleAdd">添加</button>
      </div>
    </template><script setup>
    import { ref,defineExpose) } from 'vue'
        
        const list = ref (['a','b','c'])
        const handleAdd = () => {
            list.value.push(value.value)
            value.value = ''
        }
        // <script setup>写法会导致整个组件实例无法暴露出来,父组件无法通过ref获取到子组件的实例
        defineExpose({ list })//使list暴露出来
    </script><!--父组件-->
    <template>
    <!-- 这里就是相当于将childRefs设置为子组件的实例对象 -->
      <ChildVue ref:'childRefs' />
        <div class="child">
          <ul class="list-group">
            <li class="list-item" v-for="item in childRefs?.list" :key="item">{{ item }}</li>
          </ul>
        </div>
    </template><script setup>
     import ChildVue from './Child.vue'
     import { ref } from 'vue'
     
       const childRefs = ref(null)//初始化</script>
    

    不用setup写法的话,子组件JS部分应该写成:

    <script>
    import { ref } from 'vue';
    export default {
      setup() {
        const list = ref(['JavaScript', 'HTML', 'CSS'])
        const value = ref('')
    ​
        const handleAdd = () => {
          list.value.push(value.value)
          value.value = ''
        }
    ​
        return {
          list,
          value,
          handleAdd
        }
      }
    }
    </script>
    
  5. provide / inject 父 => 子

    <!--父组件-->
    <template>
      <div>
        <div class="wrap">
          <input type="text" class="form-control" v-model="value">
          <button class="btn" type="button" @click="handleAdd">添加</button>
        </div>
    ​
        <Child/>
      </div>
    </template>
    <script setup>
    import { ref, provide } from 'vue';
    import Child from './Child.vue'const list = ref(['JavaScript', 'HTML', 'CSS'])
    const value = ref('')
    ​
    const handleAdd = () => {
      list.value.push(value.value)
      value.value = ''
    }
    ​
    provide('list', list.value) // 向子组件提供数据,相当于广播这个list
    </script>
    <!--子组件(名为Child)-->
    <template>
      <div class="child">
        <ul class="list-group">
          <li class="list-item" v-for="item in list" :key="item">
            {{ item }}
          </li>
        </ul>
      </div>
    </template><script setup>
    import { inject } from 'vue';
    ​
    const list = inject('list')//接受父组件的传递
    </script>
    
  6. vue2 当中使用EventBus(事件总线)实现组件通信,vue3中移除了事件总线,使用 mitt.js 或者 tiny-emitter.js(这两个都是第三方工具) 父 - 子 || 子 - 父 || 兄弟组件

  7. Vuex 和 Pinia