VUE3 九种组件通信的方式(附详细代码)

  1. props

    1. 用途:可以实现父子组件通信

    2. 父组件

      <template>
          <div>
              <Son :money="money"></Son>
          </div>
      </template>
      
      <script setup lang="ts">
      import Son from './son.vue'
      import { ref } from 'vue';
      let money = ref(1000)
      </script>
      
      <style scoped></style>
    3. 子组件

      <template>
          <div>
              {{ props.money }}
          </div>
      </template>
      
      <script setup lang="ts">
      /*	两种方式都可以使用		*/
      // defineProps({
      //     money: {
      //         type: Number,
      //         default: 666
      //     }
      // })
      let props = defineProps(['money'])
      </script>
      
      <style scoped></style>
  2. 自定义事件

    1. 用途:可以实现子父组件通信

    2. 父组件

      <template>
        <div style="width: 400px;height: 200px;background: pink;">
          <practice1 @zdy = 'test'></practice1>
        </div>
        
      
      </template>
      
      <script setup>
      import { ref,nextTick } from 'vue';
      import practice1 from './practice1.vue'
      function test(...val){
        console.log(...val)
      }
      
      </script>
      
      <style></style>
      
    3. 子组件

      <template>
        <div style="width: 100px;height: 50px;background: purple;" @click="test">dsfjsldkjf</div>
      </template>
      
      <script setup>
      let $emit  = defineEmits(['zdy','zdy1'])
      function test(){
          $emit('zdy','hh','hello')
      }
      console.log($emit)
      </script>
      
      <style></style>
      
  3. 全局事件总线$bus:

    1. 用途:可以实现任意组件通信

    2. 安装 

      pnpm i mitt
    3. 配置

      1. 新建bus.js文件

        import mitt from 'mitt'
        const $bus = mitt()
        export default $bus
    4. 使用

      1. 父组件

        <template>
            <div>
                <Son  @zdy = 'handle'></Son>
            </div>
        </template>
        
        <script setup lang="ts">
        import Son from './son.vue'
        import { ref } from 'vue';
        import $bus from '../utils/bus.js'
        $bus.on('dataToParent',(a:any)=>{
            console.log(a)
        })
        </script>
        
        <style scoped></style>
      2. 子组件

        <template>
            <div>
                <button @click="dataToParent">点击向父组件发送全局事件总线数据</button>
            </div>
        </template>
        
        <script setup lang="ts">
        import $bus from '../utils/bus.js'
        const dataToParent = ()=>{
            $bus.emit('dataToParent','hello')
        }
        </script>
        
        <style scoped></style>
  4. v-model

    1. 父组件

      <template>
          <div>
              <Son :money="money"></Son>
          </div>
      </template>
      
      <script setup lang="ts">
      import Son from './son.vue'
      import { ref } from 'vue';
      let money = ref(1000)
      </script>
      
      <style scoped></style>
    2. 子组件

      <template>
          <div>
              {{ money }}
          </div>
      </template>
      
      <script setup lang="ts">
      defineProps(['money'])
      </script>
      
      <style scoped></style>
  5. useAttrs

    1. 父组件

      <template>
          <div>
              <Son :money="money" title="attr传参" size='default' type="primary"></Son>
          </div>
      </template>
      
      <script setup lang="ts">
      import Son from './son.vue'
      import { ref } from 'vue';
      let money = ref(1000)
      </script>
      
      <style scoped></style>
    2. 子组件

      <template>
          <div>
              {{ $attrs.money }} --{{ $attrs.title }}
          </div>
      </template>
      
      <script setup lang="ts">
      import { useAttrs } from 'vue';
      let $attrs = useAttrs()
      console.log($attrs)
      </script>
      
      <style scoped></style>
  6. provide与inject

    1. 父组件

      <template>
          <div>
              <Son :money="money"></Son>
          </div>
      </template>
      
      <script setup lang="ts">
      import Son from './son.vue'
      import { ref,provide } from 'vue';
      let money = ref(1000)
      provide('name','wang')
      </script>
      
      <style scoped></style>
    2. 子组件

      <template>
          <div>
             
          </div>
      </template>
      
      <script setup lang="ts">
      import { inject } from 'vue';
      let name = inject('name')
      console.log(name)
      </script>
      
      <style scoped></style>
  7. ref与$parent

    1. 父组件

      <template>
          <div>
              <div>当前父组件的money是{{ money }}</div>
              <button @click="take100FromSon">从儿子手里拿100元</button>
              <Son :money="money" ref="son"></Son>
              <Dau></Dau>
      
          </div>
      </template>
      
      <script setup lang="ts">
      import Son from './son.vue'
      import Dau from './daughtor.vue'
      import { ref } from 'vue';
      let son = ref()
      let money = ref(1000)
      const take100FromSon = ()=>
      {
          son.value.money -=100;
          money.value+=100
      }
      defineExpose({
          money
      })
      </script>
      
      <style scoped></style>
    2. 儿子组件1

      <template>
          <div>
             儿子的手里有{{ money }}
          </div>
      </template>
      
      <script setup lang="ts">
      import { ref } from 'vue';
      let money = ref(500)
      defineExpose({
          money
      })
      </script>
      
      <style scoped></style>
    3. 儿子组件2

      <template>
          <div>
      女儿的手里有{{ money }}元
      <button @click="take1000FromFather($parent)">从父亲手里拿1000元</button>
          </div>
      </template>
      
      <script setup lang="ts">
      import { ref } from 'vue';
      let money = ref(5000)
      const take1000FromFather = ($parent:any)=>{
          $parent.money-=1000
          money.value+=1000
      }
      </script>
      
      <style scoped>
      
      </style>
  8. pinia

    1. 安装pinia 

      pnpm i pinia
    2. 初始化pinia

      1. 创建一个store文件夹,在下面新建一个index.js文件

        import {createPinia} from 'pinia'
        let store = createPinia()
        export default store 
      2. 在main.js文件中声明

        import store from './pinia'
        app.use(store)
    3. 使用pinia

      1. 在store下新建一个modules文件夹,用来管理pinia文件,例如,创建了一个test.js文件。

        import {defineStore} from 'pinia'
        import {ref} from 'vue'
        export const testPinia = defineStore('testPinia',()=>{
            const a = ref('hello')
            const sendMessage = ()=>{
                a.value = 'hello,vue'
                console.log(a.value)
            }
            return{a,sendMessage}
        })
      2. 组件中使用

        <template>
            <div>
        
            </div>
        </template>
        
        <script setup lang="ts">
        import {testPinia} from '../pinia/modules/test.js'
        const testpinia = testPinia()
        console.log(testpinia.a)
        testpinia.sendMessage()
        </script>
        
        <style scoped>
        
        </style>
  9. slot

    1. 默认插槽

      1. 父组件

        <template>
        <Son>
          <h1>我是默认插槽填充的结构</h1>
        </Son>
        
        **具名插槽:**
        </template>
        
        <script setup lang="ts">
        import Son from './son.vue'
        </script>
        
        <style scoped>
        
        </style>
      2. 子组件

        <template>
            <div>
              <slot></slot>
            </div>
          </template>
          <script setup lang="ts">
          </script>
          <style scoped>
          </style>
      3. 效果图

    2. 具名插槽

      1. 父组件

        <template>
          <h1>slot</h1>
            <Son>
              <template v-slot:a> 
                <!-- //可以用#a替换  -->
                <div>填入组件A部分的结构</div>
              </template>
              <template v-slot:b>
                <!-- //可以用#b替换 -->
                <div>填入组件B部分的结构</div>
              </template>
            </Son>
        </template>
        
        <script setup lang="ts">
        import Son from './son.vue'
        </script>
        
        <style scoped>
        
        </style>
      2. 子组件

        <template>
            <div>
              <h1>todo</h1>
              <slot name="a"></slot>
              <slot name="b"></slot>
            </div>
          </template>
          <script setup lang="ts">
          </script>
          
          <style scoped>
          </style>
      3. 效果图

    3. 作用域插槽

      1. 概念:可以理解为,子组件数据由父组件提供,但是子组件内部决定不了自身结构与外观(样式)

      2. 父组件

        <template>
          <div>
            <h1>slot</h1>
            <Son :todos="todos">
              <template #="{$row,$index}">
                 <!--父组件决定子组件的结构与外观-->
                 <span :style="{color:$row.done?'green':'red'}">{{$row.title}}</span>
              </template>
            </Son>
          </div>
        </template>
        
        <script setup lang="ts">
        import Son from "./son.vue";
        import { ref } from "vue";
        //父组件内部数据
        let todos = ref([
          { id: 1, title: "吃饭", done: true },
          { id: 2, title: "睡觉", done: false },
          { id: 3, title: "打豆豆", done: true },
        ]);
        </script>
        <style scoped>
        </style>
      3. 子组件

        <template>
          <div>
            <h1>todo</h1>
            <ul>
             <!--组件内部遍历数组-->
              <li v-for="(item,index) in todos" :key="item.id">
                 <!--作用域插槽将数据回传给父组件-->
                 <slot :$row="item" :$index="index"></slot>
              </li>
            </ul>
          </div>
        </template>
        <script setup lang="ts">
        defineProps(['todos']);//接受父组件传递过来的数据
        </script>
        <style scoped>
        </style>
      4. 效果图

  • 44
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 中,组件之间的通信可以通过多种方式实现,以下是一些常用的方法和相应的代码示例: 1. Props: 父组件通过属性传递数据给子组件。 - 父组件中: ```vue <template> <child-component :message="parentMessage"></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: 'Hello from parent' }; } } </script> ``` - 子组件中: ```vue <template> <div>{{ message }}</div> </template> <script> export default { props: { message: { type: String, required: true } } } </script> ``` 2. Emit 事件: 子组件通过触发自定义事件向父组件发送消息。 - 子组件中: ```vue <template> <button @click="sendMessage">Send Message</button> </template> <script> export default { methods: { sendMessage() { this.$emit('message-sent', 'Hello from child'); } } } </script> ``` - 父组件中: ```vue <template> <child-component @message-sent="handleMessage"></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, methods: { handleMessage(message) { console.log(message); // 输出:Hello from child } } } </script> ``` 3. Provide/Inject: 祖先组件通过 provide 向所有后代组件注入数据,后代组件通过 inject 来使用这些数据。 - 祖先组件中: ```vue <template> <child-component></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, provide() { return { message: 'Hello from ancestor' }; } } </script> ``` - 后代组件中: ```vue <template> <div>{{ injectedMessage }}</div> </template> <script> export default { inject: ['message'], computed: { injectedMessage() { return this.message; } } } </script> ``` 这些是 Vue 3 中常用的组件间通信方式代码实现示例。根据具体的需求和场景,你可以选择适合的方式来实现组件通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值