vue3组件之间通信的方式有几种

516 阅读2分钟

vue3组件通信方式汇总:cn.vuejs.org/

父子组件之间传参

  • 父组件传递子组件参数
  • 子组件通过事件派发的方式把事件和参数传递给父组件
  • 父组件通过ref方式操作子组件的事件和取子组件的参数

兄弟组件之间传参

  • 通过EventBus来进行兄弟组件传值

跨组件之间传参

  • provide / inject

页面之间的数据管理

  • 响应式 API做简单状态管理
  • 通过Vuex来进行数据管理
  • 通过pinia进行数据管理

案例

父组件传递子组件参数(常用)

<script setup lang="ts">
//父组件 father.vue
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'  //引入子组件

</script>

<template>
  <div>
    <div class="border">
      <h1>组件传值方法总结</h1>
    </div>
    <div class="border">
      <h3>父传子参数:<HelloWorld msg="你好犀利呀" /></h3>  <!-- msg作为父组件传递子组件的参数 -->
    </div>
  </div>
</template>
<script setup lang="ts">
//子组件 son.vue
const props = withDefaults(
  defineProps<{
    msg: string //参数必传
    noMsg?: string //参数非必填
    btnShow?: boolean //是否显示按钮
  }>(),
  {
    noMsg: '参数默认值',
    btnShow: false
  }
)
</script>

<template>
  <span class="green">{{ msg }}</span> <!-- 父组件传递过来的参数msg -->
</template>

子组件通过事件派发的方式把事件和参数传递给父组件(常用)

<script setup lang="ts">
//父组件 father.vue
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'  //引入子组件

const onOutData = (e: string) => {
  console.log(e,'接收所传过来的参数')
}
</script>

<template>
  <div>
    <div class="border">
      <h1>组件传值方法总结</h1>
    </div>
    <div class="border">
      <h3>父传子参数:<HelloWorld msg="你好犀利呀" btnShow @onOutData="onOutData" /></h3>  <!-- 通过事件的方式接收 -->
    </div>
  </div>
</template>
<script setup lang="ts">
//子组件 son.vue
const props = withDefaults(
  defineProps<{
    msg: string //参数必传
    noMsg?: string //参数非必填
    btnShow?: boolean //是否显示按钮
  }>(),
  {
    noMsg: '参数默认值',
    btnShow: false
  }
)

const emit = defineEmits(['onOutData'])
const onOutData = () => {
  emit('onOutData','子组件传递父组件的参数')  // 子传父
}
</script>

<template>
  <span class="green">{{ msg }}</span> <!-- 父组件传递过来的参数msg -->
  <button v-if="btnShow" @click="onOutData">触发</button>
</template>

父组件通过ref方式操作子组件的事件和取子组件的参数(常用)

<script setup lang="ts">
//父组件 father.vue
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'  //引入子组件
let HelloWorldRef = ref<any>(null) //1.定义

const onEditBtn = () => {
  HelloWorldRef.value.print() //3.触发子组件事件
  console.log(HelloWorldRef.value.data) //4.获取子组件参数
}
</script>

<template>
  <div>
    <div class="border">
      <h1>组件传值方法总结</h1>
    </div>
    <div class="border">
      <h3>父传子参数:<HelloWorld ref="HelloWorldRef" msg="你好犀利呀" /></h3>  <!-- 2.设置在对应的组件上 -->
      <button> @click="onEditBtn">打印</button>
    </div>
  </div>
</template>
<script setup lang="ts">
//子组件 son.vue
import { ref } from 'vue'
const props = withDefaults(
  defineProps<{
    msg: string //参数必传
    noMsg?: string //参数非必填
    btnShow?: boolean //是否显示按钮
  }>(),
  {
    noMsg: '参数默认值',
    btnShow: false
  }
)

const emit = defineEmits(['onOutData'])

let data = ref('子组件的参数')

const onOutData = () => {
  emit('onOutData','子组件传递父组件的参数')  // 子传父
}
const print = () => {
  console.log(props.msg, '父组件控制子组件事件触发')
}
// 将事件和参数暴露出去
defineExpose({ print, data })
</script>

<template>
  <span class="green">{{ msg }}</span> <!-- 父组件传递过来的参数msg -->
  <button v-if="btnShow" @click="onOutData">触发</button>
</template>

通过EventBus来进行兄弟组件传值 略

跨组件之间传参 略

响应式 API做简单状态管理

参考:cn.vuejs.org/guide/scali…

通过Vuex来进行数据管理(官网推荐pinia)

<script setup lang="ts">
//父组件 father.vue
import { ref } from 'vue'
import { useStore } from 'vuex'
import HelloWorld from './components/HelloWorld.vue'  //引入子组件

const store = useStore()
const rootCounter = computed(() => store.state.rootCounter)
const increment = () => {
  store.commit('increment')
}

const decrement = () => {
  store.dispatch('incrementAction')
}
</script>

<template>
  <div>
    <div class="border">
      <h1>组件传值方法总结</h1>
    </div>
  <div class="border">
      <h3>通过Vuex来进行数据管理</h3>
      <h4>
        从store中取值方式:
        <span class="span">方式一:{{ store.state.rootCounter }}</span>
        <span class="span">方式二:{{ rootCounter }}</span>
      </h4>
      <h4>
        把值存入store中:
        <span class="span">方式一:{{ store.state.rootCounter }}</span>
        <button @click="increment">+1</button>
        <button @click="decrement">-1</button>
      </h4>
    </div>
  </div>
</template>
//父组件 store.ts
import { createStore } from "vuex"

const store = createStore({
  state() {
    return {
      rootCounter: 100
    }
  },
  getters: {
    doubleRootCounter(state) {
      return state.rootCounter * 2
    }
  },
  mutations: {
    increment(state) {
      state.rootCounter++
    }
  },
  actions: {
    incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
      commit("increment")
    }
  },
  modules: {}
});

export default store;

通过pinia进行数据管理(推荐,常用)

<script setup lang="ts">
//父组件 father.vue
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
import { useUserInfoStore } from '../../stores/pinia/userInfo'

const onIncrement = () => {
  useUserInfo.increment() //触发pinia
}
</script>

<template>
  <div>
    <div class="border">
      <h1>组件传值方法总结</h1>
    </div>

    <div class="border">
      <h3>通过pinia进行数据管理<button @click="onIncrement">+</button>:{{ useUserInfo.count }}</h3>
      <HelloWorld ref="HelloWorldRef" msg="" btnShow />
    </div>
  </div>
</template>
<script setup lang="ts">
//子组件 son.vue
import { ref } from 'vue'
import { useUserInfoStore } from '@/stores/pinia/userInfo'

const onOutData = () => {
  useUserInfo.increment() //触发pinia
}
</script>

<template>
  <span class="green">{{ msg }}</span>
  <span class="green">noMsg:{{ noMsg }}</span>
  <button v-if="btnShow" @click="onOutData">触发</button>
</template>
//pinia.ts
import { ref, computed } from "vue";
import { defineStore } from "pinia";

export const useUserInfoStore = defineStore("userInfo", () => {
  const count = ref(0);
  const doubleCount = computed(() => count.value * 2);
  function increment() {
    count.value++;
  }

  return { count, doubleCount, increment };
});

案例地址:

gitee.com/heyongtao_1…