Vue3组件间通信总结

266 阅读1分钟

vue3组件通信(8种)

各位看官,以下为本人根据官方及各路大神的总。结所收集的,若有错误欢迎纠正

一、父传子:

1、props

父:
    <template>
        <!-- 子组件 -->
        <Child :data1="data1"></Child>
    </template>
    <script setup>
        const data1 = []
    </script>
子:
    <script setup>
        import { defineProps } from 'vue'
        const props = defineProps({
          data1: {
            type: Array,
            default: () => [],
          },
        })
        const data1 = props.data1
    </script>
    或
    <script>
        import {defineCompontent} from 'vue'
        export default defineCompontent({
          name: '',
          props: ['data1'],
          setup(props) {
            const data1 = props.data1
            return {
              data1,
            }
          }
        })
    </script>

2、provide/inject(可跨级)

父:
    <script setup>
    import { ref, provide } from 'vue'
        // 向子组件提供数据
        const data1 = []
        provide('data1', data1)
    </script>
子孙等:
    <script setup>
        import {inject} from 'vue'
        const data1 = inject('data1')
    </script>

3、attrs(个人不常用)

父:
    <Child :data1="data1" :data2="data2"></Child>
    <script setup>
          import { ref, reactive } from "vue"
          const data1 = ref("1")
          const data2 = ref("2")
    </script>
子:
    <script setup>
        import {defineProps, useAttrs} from 'vue'
        const props = defineProps({
          data1,
        })
        const attrs = useAttrs()
        const data2 = attrs.data2;
    </script>

4、父亲调用子方法expose/ref

父:
    <template>
        <!-- 子组件 -->
        <Child ref="child"></Child>
    </template>
    <script setup>
        import { ref } from 'vue'
        const child = ref()
        child.value.fn()
    </script>
子:
    <script setup>
        import {defineExpose} from 'vue'
        const fn = () => {}
        defineExpose({
          fn,
        })
    </script>
    或
    <script>
        import {defineCompontent} from 'vue'
        export default defineCompontent({
          name: '',
          setup() {
            const fn = () => {}
            return {
              fn,
            }
          }
        })
    </script>

二、子传父

5、$emit

父:
    <template>
        <!-- 子组件 -->
        <child  @fn1="fn1"></child>
    </template>
    <script setup>
        const fn1 = (data) => {}
    </script>
子:
    <script setup>
        import {defineEmits} from 'vue'
        const emits = defineEmits(['fn1'])
        const data = {}
        emits('fn1', data)
    </script>
    或
    <script>
        import {defineComponent} from 'vue'
        export default defineComponent({
          name: '',
          setup(props, context) {
            const data = {}
            context.emit('fn1', data)
          }
        })
    </script>
    或
    <script>
        import {defineComponent} from 'vue'
        export default defineComponent({
          name: '',
          setup(props, ctx) {
            const data = {}
            ctx.emit('fn1', data)
          }
        })
    </script>

三、父子之间

6、v-model(props和emit)

父:
    <Child v-model:data="data"></Child>
子:
<script setup>
    import { defineEmits, defineProps } from 'vue'
    const props = defineProps({
    data: {
      type: Array,
      default: () => [],
    },
    })
    const emits = defineEmits(['update:data'])
    emits('update:data', data)

四、跨组件

7、mitt(全局事件总线)

先安装:npm i mitt -S
main.js
    import { createApp } from 'vue'
    import App from './App.vue'
    import mitt from 'mitt'
    const emitter = mitt()
    const app = createApp(App)
    app.config.globalProperties.$emitter = emitter
发:
    <script setup>
      import {getCurrentInstance} from 'vue'
      const {proxy} = getCurrentInstance()
      const data = {}
      proxy.$emitter.emit('data1', data)
    </script>
收:
    <script setup>
      import {getCurrentInstance, onBeforeUnmount} from 'vue'
      const {proxy} = getCurrentInstance()
      const fn = (data) => {}
      proxy.$emitter.on('data1', fn)
      onBeforeUnmount(() => {
        proxy.$emitter.off('data1', fn)
      }) // 组件销毁时需清除,
    </script>

8、VueX

<script setup>
    import {computed} from 'vue'
    import {useStore} from 'vuex'
    const store = useStore()
    const data = computed(() => store.state.name.data) 
    // 其中name为模块化的名字,如果没有可直接用store.state.data
</script>