vue3中常见的七种组件通信

618 阅读2分钟

vue3中常见的几种组件通信,你都知道吗?看一看下面的vue3组件通信写法,看看它和vue2中的组件通信有什么不同

Vue3中常见的七种组件通信

  • props
  • emit
  • v-model
  • refs
  • provide/inject
  • mitt
  • vuex/Pinia

vue3的组件使用写法

1. props

props用来 父组件 -> 子组件传值

// Parent.vue

<template>
  <ChildVue :list="list"></ChildVue>  //将父组件的list数组传给子组件
</template>
 
<script setup>
 const list =ref(['JavaScript','HTML','CSS'])
 const value = ref('')
 const handleAdd =() =>{ 
 list.value.push(value.value)
 value.value = ''
}
</script>


// Child.vue
 <ul class="list-group">
 
    //拿父组件的数组进行循环渲染
   <li class="list-item" v-for="(item,index) in props.list" :key="index" > 
        {{item}}
    </li>
  </ul>
<script setup >
  import { defineProps } from 'vue'; //专门用来解析父组件传递的数据
  const props = defineProps({  
    list:{
      type:Array,
      default: () =>[]
    }
  })
</script>

vue3用setup 要 import { defineProps } from 'vue';

const props = defineProps () 才能使用props

2. emit

emit用来子组件 -> 父组件 传值

// Parent.vue
<template>
  <div>
    <!-- 子组件 -->
    <ChildVue @add = 'childValue'></ChildVue>   //add 就是子组件抛出的事件名

    <!-- 父组件 -->
    <div class="child">
      <ul class="list-group">
        <li class="list-item" v-for="(item, index) in list" :key="index">
          {{ item }}
        </li>
      </ul>
    </div>
  </div>
</template>


// Child.vue
<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/reactivity"
const emit = defineEmits()  //定义一个事件名称

const value = ref('')
 const handleAdd =() =>{ 
    // this.$emit('add',value.value)   vue2写法
    emit('add',value.value)   // vue3写法
    value.value = ''
}

</script>

①:vue2 中用法是 在子组件 点击事件里面用 this.$emit('事件名',this.数据) 发散出去

②:vue3中用法是 import { defineEmits } from "@vue/reactivity"

const emit = defineEmits() 就可以用emit f方法了,其他和vue2 用法一样

3. v-model

v-model 用来子组件 -> 父组件 传值

// Parent.vue
<template>
  <div>
    <!-- 子组件 -->
    <ChildVue v-model:list="list"></ChildVue>  // v-model 双向绑定
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildVue from '../vmodel/Childs.vue';
 const list =ref(['JavaScript','HTML','CSS'])
</script>


// Child.vue
<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/reactivity"

const emit = defineEmits(['update:list'])  //定义一个事件名称 'update:list' 固定写法
const props = defineProps({                // list需要用props接收
  list:{
    type:Array,
    default:() =>[]
  }
})

const value = ref('')
 const handleAdd =() =>{ 
   const arr = props.list
    arr.push(value.value)     //将要输入的值push进数组
    emit('update:list',arr)   // vue3写法  更新父组件list的值并传给父组件
    value.value = ''
}

</script>

父组件中在子组件上v-model双向绑定

子组件中,用props接受,用emit 发散 并返回更新好的数据给父组件。 update:*是Vue中的固定写法,*表示props中的某个属性名。

4.refs

refs 用来子组件 -> 父组件传值

// Parent.vue
<template>
  <div>
    <!-- 子组件 -->
    <ChildVue ref="childRefs"></ChildVue>      //父组件na
  </div>
  </template>
  
// Child.vue
<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/reactivity"

 const list =ref(['JavaScript','HTML','CSS'])
 const value = ref('')
 const handleAdd =() =>{ 
    list.value.push(value.value)      //将要添加的值push进数组
    value.value = ''
}
defineExpose({list})                 // 抛出这个list
</script>

子组件中 script setup 写法会导致整个组件实例无法暴露出来,要用 defineExpose() 暴露出传给父组件的值。

5.provide/inject

provide/inject 用来父组件-> 子组件 传值

// Parent.vue
<template>
  <div>
    <ListVue ></ListVue>
  </div>
</template>

<script setup>
 const list =ref(['JavaScript','HTML','CSS'])

 //向子组件 传递数据
 provide('list',list.value)

 const handleAdd =() =>{ 
 list.value.push(value.value)
 value.value = ''
}
</script>

//Child.vue
<template>
  <li class="list-item" v-for="(item,index) in list" :key="index" >
      {{item}}
  </li>
</template>

<script setup >
  import { inject } from 'vue'; //专门用来解析父组件传递的数据

  const list = inject('list')
</script>

provide:可以让我们指定想要提供给后代组件的数据或

inject:在任何后代组件中接收想要添加在这个组件上的数据,不管组件嵌套多深都可以直接拿来用

6.mitt

mitt可以用来 子组件 <-> 父组件 互通数据,下面这个例子用来 子组件 -> 父组件 传值

//Parrnt.vue
<template>
  <div>
    <!-- 子组件 -->
    <ChildVue @add = 'childValue'></ChildVue>
  </div>
</template>

<script setup>
import emitter from './mitt'  //引入mitt.js

const list =ref(['JavaScript','HTML','CSS'])

emitter.on('add',(val)=>{    // emitter.on用来接收数据
  // console.log(val); 
  list.value.push(val)
})
</script>

// Child.vue
<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 } from "@vue/reactivity"
import emitter from './mitt'   //引入 mitt.js

 const handleAdd =() =>{ 
   emitter.emit('add',value.value)   // emitter.emit 抛出事件
    value.value = ''
}
</script>

vue2当中使用EventBus(事件总线)实现组件通信,vue3中使用 mitt.js 或者 tiny-emitter.js

mitt用法: 先定义一个mitt.js 在里面引入 mitt 抛出mitt() 的调用 ,为了让父子组件引入的为同一份mitt.js。

在父子组件中 引入这份js,然后用emitter.emit('事件名',数据) 抛出, emitter.on('事件名',(val) => { }) 接收

7. vuex/Pinia

vuex 的用法比较简单。在store.js仓库里面存数据。然后父子组件引入store.js。对数据进行操作。可以把它看成第三方。Pinia和vuex操作类似。

新手上路,如有不对的或者遗漏的,欢迎指正,你的一赞一评都是我前行最大的动力,感谢

u=1878870177,632404494&fm=253&fmt=auto&app=120&f=JPEG.webp