vue常见的通信方式总结

 更新时间:2023年08月03日 08:31:00   作者:zt_ever  
我们日常项目开发中,少不了组件之间的通信,我们可能只知道一些常见的方式比如props,emits,其实,实现组件间的通信有很多种方式,本文就给大家总结一些我们常见的通信方式,需要的朋友可以参考下

正文

一、props

props用于父组件子组件传参,主要步骤是:

  1. 父组件在引入的子组件上v-bind绑定一个变量,值为要传递的参数。
  2. 子组件用defineProps来接收传过来的变量。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
  <div>
    <input type="text" v-model="value">
    <button>添加</button>
  </div>
  <Child :val="value"/>
</template>
<script setup>
import Child from './child.vue'
import {ref} from 'vue'
const value=ref('hello')
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <h2>{{ val }}</h2>
</template>
<script setup>
const props=defineProps({
  val:String
})
</script>
<style lang="scss" scoped></style>

效果图如下:

props.gif

二、emits

emits用于子组件父组件传参,主要步骤是:

  1. 子组件通过defineEmits注册一个事件,并在点击事件中将这个事件携带要传递的参数发散出去。
  2. 父组件在引入的子组件上绑定这个事件,这个事件的参数就是传递过来的值。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
  <h2>{{ res }}</h2>
  <Child @add="handleAdd" />
</template>
<script setup>
import Child from './child.vue'
import { ref } from 'vue'
const res = ref('hello')
const handleAdd = (e) => {
  res.value = e
}
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <input type="text" v-model="msg">
  <button @click="handle">添加</button>
</template>
<script setup>
import {ref} from 'vue'
const msg=ref('hello') 
const emit=defineEmits(['add'])//注册事件
const handle=()=>{
  emit('add',msg.value)
}
</script>
<style lang="scss" scoped></style>

效果图如下:

emits.gif

三、v-model

v-model用于子组件父组件传参,主要步骤是:

  1. 子组件通过defineEmits注册一个属性,并在点击事件中将这个属性携带要传递的参数发散出去。
  2. 父组件在引入的子组件上用v-model绑定这个属性,值为传递过来的值。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
  <h2>{{ title }}</h2>
  <Child v-model:msg="title"/>
</template>
<script setup>
import Child from './child.vue'
import { ref } from 'vue'
const title = ref('hello')
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <input type="text" v-model="val">
  <button @click="handle">添加</button>
</template>
<script setup>
import {ref} from 'vue'
const val=ref('hello')
const emits=defineEmits(['update:msg'])
const handle=()=>{
  emits('update:msg',val.value)
}
</script>
<style lang="scss" scoped></style>

效果图如下:

emits.gif

v-model能达到和emits一样的效果,主要区别就是父组件可以偷点懒,不用多去绑定一个点击事件了。

四、refs

refs用于子组件父组件传参,主要步骤是:

  1. 子组件通过defineExpose将要传递的值暴露出去。
  2. 父组件在引入的子组件上用ref获取子组件的dom结构,dom结构有值的时候读取传递的值。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
   <h2>{{ childRef?.val }}</h2> <!--childRef有值的时候读val-->
  <Child ref="childRef"/>
</template>
<script setup>
import Child from './child.vue'
import { ref } from 'vue'
const childRef=ref(null)  //子组件的dom结构
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <input type="text" v-model="val">
  <button @click="handle">添加</button>
</template>
<script setup>
import {ref} from 'vue'
const val=ref('')
const handle=()=>{}
defineExpose({val})
</script>
<style lang="scss" scoped></style>

效果如下:

refs.gif

五、provide、inject

provide、inject用于父组件子孙组件传参,主要步骤是:

  1. 父组件通过provide将要传递的值提供出去(provide提供的一定是额外的引用类型数据)。
  2. 子孙组件通过inject注入传递过来的值。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
  <div>
    <input type="text" v-model="msg">
    <button @click="handle">添加</button>
  </div>
  <Child />
</template>
<script setup>
import Child from './child.vue'
import { provide, ref } from 'vue'
const msg = ref('')
const list=ref(['html','css'])
provide('title', list.value) 
const handle = () => {
  list.value.push(msg.value)
  msg.value=''
}
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <h2>{{ title }}</h2>
</template>
<script setup>
import { inject } from 'vue'
const title = inject('title')
</script>
<style lang="scss" scoped></style>

效果图如下:

provide.gif

六、eventBus(mitt)

eventBus(mitt)用于父子子父兄弟传参,这里以父传子为例,主要步骤是:

  1. 全局引入mitt并声明vue全局的变量$emitter
  2. 父组件通过在点击事件中调用emit方法将要传递的值发布出去。
  3. 子组件通过on方法的回调函数的参数得到传递过来的值。

代码示例如下:

<!-- 父组件Parent.vue -->
<template>
  <div>
    <input type="text" v-model="msg">
    <button @click="handle">添加</button>
  </div>
  <Child />
</template>
<script setup>
import Child from './child.vue'
import { ref,getCurrentInstance } from 'vue'
const msg = ref('')
const app=getCurrentInstance()
const handle = () => {
  app.appContext.config.globalProperties.$emitter.emit('foo', msg.value)
}
</script>
<style lang="scss" scoped></style>
<!-- 子组件Child.vue -->
<template>
  <h2>{{ title }}</h2>
</template>
<script setup>
import { ref,getCurrentInstance } from 'vue'
const title = ref('hello world')
const app=getCurrentInstance()
app.appContext.config.globalProperties.$emitter.on('foo',(e)=>{
  title.value=e
})
</script>
<style lang="scss" scoped></style>

效果图如下:

mitt.gif

七、vuex

vuex我们都不陌生,用于共享数据状态,便捷了组件间的通信以及代码的维护,它的基础用法如下:

  • 使用yarn/npm安装vuex。
  • 在src下的store中新建index.js。
import {createStore} from 'vuex'
const store=createStore({ 
  state(){  //仓库中的数据源
    return {
      count:2
    }
  },
  mutations:{  //所有修改数据源的方法
    add(state,n){
      state.count+=n
    }
  },
  actions:{  //触发mutations中的方法
    addAction(context,num){
      context.commit('add',num)
    }
  },
  getters:{  //计算属性,只要依赖值变化就会自动重新执行
    countSquare(state){ 
      return state.count**2
    }
  }
}) 
export default store
  • 在main.js中引入store并把其挂载到vue中。

那么,在组件中如何访问store中的数据和方法呢?我们从以下四块来说明:

  1. state
  • 使用this.$store.state.count
<template> 
    <div id="app"> 
        {{ this.$store.state.count }} 
    </div> 
</template>
  • 使用mapState
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex' 
export default { 
    computed: { // 将 store 映射到当前组件的计算属性   
        ...mapState(['count']) 
    } 
}
  1. mutations
  • 使用this.$store.commit()
export default { 
    methods: { 
        handle() { // 触发 mutations 中的 add 方法
            this.$store.commit('add', 1) 
        }
    }
}
  • 使用mapMutations
import { mapMutations } from 'vuex' 
export default { 
    methods: { // 将 mutations 中的 add 方法映射到 methods 中
        ...mapMutations(['add']) 
    }
}
  1. actions
  • 使用this.$store.dispatch()
export default { 
   methods: { 
       handle(num) { // 使用 dispatch 来调用 actions 中的方法
           this.$store.commit('addAction', num) 
       }
   }
}
  • 使用mapActions
import { mapActions } from 'vuex' 
export default { 
    methods: { 
        // 映射 actions 中的指定方法 到 methods中
        ...mapActions(['addAction']) 
    }
}
  1. getters
  • 使用this.$store.getters.countSquare
<template> 
   <div id="app"> 
       {{ this.$store.getters.countSquare }} 
   </div> 
</template>
  • 使用mapGetters
import { mapGetters } from 'vuex' 
export default { 
    computed: { 
        // 映射 actions 中的指定方法 到 methods中
        ...mapGetters(['countSquare']) 
    }
}

八、pinia

pinia是vuex的升级版,它有以下优点:

  1. pinia抛弃了vuex中的mutations,pinia中actions兼容同步和异步
  2. vuex中数据过多需分模块进行管理,而pinia中每个store都是独立的,互不影响。
  3. pinia体积非常小,只有1KB左右。

它的基础用法如下:

  • 使用yarn/npm安装pinia。
  • 引入pinia并挂载
import App from './App.vue'
import {createPinia} from 'pinia'
createApp(App).use(createPinia()).mount('#app')
  • 在src下的store中新建index.js。
import {defineStore} from 'pinia'
import axios from 'axios'
const useStore=defineStore('cart',{
  state:()=>{  //放响应式数据源
    return{
      badge:0
    }
  },
  getters:{
      handleBadge(){
          this.badge++
      }
  },
  actions:{
    async changeBadge(){
      const res =await axios.post('/cartList', {  //获取购物车数据
        username: JSON.parse(sessionStorage.getItem('userInfo')).username
      })
      this.badge=res.data.length
    }
  },
  persist:{   //开启数据缓存   持久化
    enabled:true,
    strategies:[    //缓存指定数据
      {
        path:['userInfo'],
        storage:localStorage  //指定localStorage存储
      }
    ]
  }
})
export default useStore

那么,在组件中如何访问store中的数据和方法呢?直接引入并调用就可以访问啦~

import useStore from '@/store/cart.js' const cart=useCartStore() cart.changeBadge()

总结

以上就是vue中的通信方式,组件通信不成问题了!如有错误或还有其它通信方式欢迎大佬指出,一起讨论!

到此这篇关于vue常见的通信方式总结的文章就介绍到这了,更多相关vue通信方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • uniapp-vue3-弹出选择组件wo-pop-selector使用示例

    uniapp-vue3-弹出选择组件wo-pop-selector使用示例

    wo-pop-selector弹出选择组件采用uniapp-vue3实现, 支持H5、微信小程序,本文给大家介绍uniapp-vue3-弹出选择组件wo-pop-selector及使用示例,感兴趣的朋友一起看看吧
    2023-10-10
  • 一文详解Vue中的虚拟DOM与Diff算法

    一文详解Vue中的虚拟DOM与Diff算法

    vue中的diff算法时常是面试过程中的考点,本文将为大家讲解何为diff以及diff算法的实现过程,那么在了解diff之前,我们需要先了解虚拟DOM是什么,需要的朋友可以参考下
    2024-02-02
  • vue自定义横向滚动条css导航两行排列布局实现示例

    vue自定义横向滚动条css导航两行排列布局实现示例

    这篇文章主要为大家介绍了vue自定义横向滚动条css导航两行排列布局实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 详解iview的checkbox多选框全选时校验问题

    详解iview的checkbox多选框全选时校验问题

    这篇文章主要介绍了详解iview的checkbox多选框全选时校验问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • vue日期时间工具类详解

    vue日期时间工具类详解

    这篇文章主要为大家详细介绍了vue日期时间工具类,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • Vue3使用JSX的方法实例(笔记自用)

    Vue3使用JSX的方法实例(笔记自用)

    以前我们经常在react中使用jsx,现在我们在vue中也是用jsx,下面这篇文章主要给大家介绍了关于Vue3使用JSX的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Vue项目中大文件切片上传实现秒传与断点续传的详细实现过程

    Vue项目中大文件切片上传实现秒传与断点续传的详细实现过程

    这篇文章主要给大家介绍了关于Vue项目中大文件切片上传实现秒传与断点续传的详细实现过程, 在开发中,如果上传的文件过大,可以考虑分片上传,分片就是说将文件拆分来进行上传,将各个文件的切片传递给后台,然后后台再进行合并,需要的朋友可以参考下
    2023-08-08
  • vue-cli3打包时图片压缩处理方式

    vue-cli3打包时图片压缩处理方式

    这篇文章主要介绍了vue-cli3打包时图片压缩处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Electron vue的使用教程图文详解

    Electron vue的使用教程图文详解

    Electron相当于一个浏览器的外壳,可以把网页程序嵌入到壳里面,可以运行在桌面上的一个程序,可以把网页打包成一个在桌面运行的程序。这篇文章主要介绍了electron-vue多显示屏下将新窗口投放是其他屏幕 ,需要的朋友可以参考下
    2019-07-07
  • 关于Vue中img动态拼接src图片地址的问题

    关于Vue中img动态拼接src图片地址的问题

    这篇文章主要介绍了关于Vue中img动态拼接src图片地址的问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10

最新评论