Vue3常用的通讯方式总结与实例代码

 更新时间:2022年05月29日 09:28:35   作者:一只豆豆  
Vue.js中一个很重要的知识点是组件通信,不管是业务类的开发还是组件库开发,都有各自的通讯方法,下面这篇文章主要给大家介绍了关于Vue3常用的通讯方式的相关资料,需要的朋友可以参考下

前言

Vue3更新了很久了,但是之前项目都是用Vue2写的,最近去官网look了一波,在这里总结一下Vue3常用的通讯方式。
尤大大,不要再更新了,真的学不动了。

本文用的是Vue3.2版本的setup语法糖官网

props

父组件

    <template>
      <div>
          <Child :msg="msg" :obj="obj" />
      </div>
    </template>

    <script setup>
        import { ref, reactive } from 'vue'
        // Vue3.2版本setup语法糖引入组件不需要注册便可以使用组件
        import Child from './child.vue'

        const msg = ref('一只豆豆')
        // 传递复杂类型数据
        const obj = reactive({name: '豆豆'})
    </script>

子组件

    <template>
      <div></div>
    </template>

    <script setup>
        // Vue3.2版本setup语法糖 defineProps 不需要引入可以直接使用
        const props = defineProps({
            msg: {
                type: String,
                default: ''
            },
            obj: {
                type: Object,
                default: () => {}
            }
        })
        console.log('msg', props.msg); // 一只豆豆
        console.log('obj', props.obj.name); // 豆豆
</script>

$emit

父组件

    <template>
      <div>
          <Child @myClick="myClick" />
      </div>
    </template>

    <script setup>
        import { ref, reactive } from 'vue'
        import Child from './child.vue'

        const myClick = val => {
            console.log('val', val); // emit传递信息
        }
</script>

子组件

    <template>
      <div>
          <button @click="handleClick">click me</button>
      </div>
    </template>

    <script setup>
        // Vue3.2版本setup语法糖 defineEmits 不需要引入可以直接使用
        const emit = defineEmits(['myClick']) // 如果有多个emit事件可以往数组后边添加即可
        
        const handleClick = ()=>{
            emit("myClick", "emit传递信息")
        }
    </script>

EventBus

在Vue3中就没有EventBus了,可以使用mitt.js来替代
安装

$ npm install --save mitt

bus.js

    import mitt from 'mitt'
    export default mitt()

兄弟组件A emit触发

    <template>
      <div>
        <button @click="handleClick">click me</button>
      </div>
    </template>

    <script setup>
        import bus from './bus'
        const handleClick = () => {
          bus.emit('foo', '豆豆')
        }
    </script>

兄弟组件B on接收

    <template>
      <div></div>
    </template>

    <script setup>
        import bus from './bus'
        bus.on('foo', e => {
          console.log('e', e) // '豆豆'
        })
    </script>

v-model

Vue2版本是可以通过修饰符.sync让子组件修改父组件的值,但是Vue3就取消这个修饰符,融合到v-model里边去了

父组件

    <template>
      <div>
        <div>{{ name }}</div>
        <div>{{ age }}</div>
        <Child v-model:name="name" v-model:age="age" />
      </div>
    </template>

    <script setup>
        import Child from './child.vue'
        import { ref } from 'vue'

        const name = ref('豆豆')
        const age = ref(20)
    </script>

子组件

    <template>
      <div>
        <div></div>
        <button @click="handleChange">click me</button>
      </div>
    </template>

    <script setup>
        // 'update:name' 这样写在console里面就不会有告警了
        const emit = defineEmits(['update:name', 'update:age'])
        const handleChange = () => {
          emit('update:name', '一只豆豆')
          emit('update:age', 18)
        }
    </script>

expose / ref

子组件通过 expose 暴露属性和方法出去
父组件通过 ref 来获取子组件的值和调用方法

父组件

    <template>
      <div>
        <Child ref="myRef" />
        <button @click="handleClick">click me</button>
      </div>
    </template>

    <script setup>
        import Child from './child.vue'
        import { ref } from 'vue'
        const myRef = ref(null)
        const handleClick = () => {
          console.log('myRef', myRef.value.name) // 豆豆
          myRef.value.fn() // 一只豆豆
        }
    </script>

子组件

    <template>
      <div>
        <div></div>
      </div>
    </template>

    <script setup>
        // Vue3.2版本setup语法糖 defineExpose 不需要引入可以直接使用
        defineExpose({
          name: '豆豆',
          fn () {
            console.log('一只豆豆')
          }
        })
    </script>

provide / inject

provide / inject 可以给后代组件传参,嵌套多少层都没问题

父组件

    <template>
      <div>
        <Child />
      </div>
    </template>

    <script setup>
        import Child from './child.vue'
        import { ref, provide } from 'vue'
        const name = ref('豆豆')
        provide('name', name)
    </script>

后代组件

    <template>
      <div>
        <div>后代组件name {{ name }}</div>
      </div>
    </template>

    <script setup>
        import { inject } from 'vue'
        const name = inject('name')
        console.log('name', name.value) // 豆豆
    </script>

Vue2使用 provide / inject 传递数据不是响应式的,所以只能通过传递一个对象数据才能变成响应式
Vue3使用 provide / inject传递数据就是响应式了,这就很便捷

插槽 slot

普通插槽

父组件

    <template>
      <div>
        <Child>豆豆</Child>
      </div>
    </template>

    <script setup>
        import Child from './child.vue'
    </script>

子组件

    <template>
      <div>
        <slot></slot>
      </div>
    </template>

    <script setup></script>

具名插槽

    <template>
      <div>
        <Child>
          豆豆
          <template #name>
            <div>
              <button>一只豆豆</button>
            </div>
          </template>
        </Child>
      </div>
    </template>

    <script setup>
        import Child from './child.vue'
    </script>

子组件

    <template>
      <div>
        // 普通插槽
        <slot></slot>
        // 具名插槽
        <slot name="name"></slot>
      </div>
    </template>

    <script setup></script>

效果图

作用域插槽

父组件

    <template>
      <!-- v-slot="{scope}" 子组件返回的每一项数据 -->
      <Child v-slot="{ scope }" :arr="arr">
        <div class="box">
          <div>名字:{{ scope.name }}</div>
          <div>年龄:{{ scope.age }}</div>
          <div>爱好:{{ scope.like }}</div>
        </div>
      </Child>
    </template>

    <script setup>
        import { reactive } from 'vue'
        import Child from './child.vue'

        const arr = reactive([
          { name: '张三', age: 18, like: '篮球' },
          { name: '李四', age: 19, like: '排球' },
          { name: '王五', age: 20, like: '足球' }
        ])
    </script>

    <style lang="less">
        .box {
          display: inline-block;
          width: 200px;
          border: dashed blue 1px;
          margin-right: 15px;
          padding: 10px;
        }
    </style>

子组件

    <template>
      <div>
        <!-- :scope="item" 返回每一项 -->
        <slot v-for="item in arr" :scope="item" />
      </div>
    </template>

    <script setup>
        const props = defineProps({
          arr: {
            type: Array,
            default: () => []
          }
        })
    </script>

效果图

结语

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

相关文章

  • vue.js响应式原理解析与实现

    vue.js响应式原理解析与实现

    这篇文章主要为大家详细介绍了vue.js响应式原理解析与实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • VUE实现吸底按钮

    VUE实现吸底按钮

    这篇文章主要为大家详细介绍了VUE实现吸底按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • vue中路由传参以及跨组件传参详解

    vue中路由传参以及跨组件传参详解

    这篇文章主要给大家介绍了关于vue中路由传参以及跨组件传参的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 解决Vue 刷新页面导航显示高亮位置不对问题

    解决Vue 刷新页面导航显示高亮位置不对问题

    这篇文章主要介绍了解决Vue 刷新页面导航显示高亮位置不对问题,本文图文实例相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • Vue中的基础过渡动画及实现原理解析

    Vue中的基础过渡动画及实现原理解析

    这篇文章主要介绍了Vue中的基础过渡动画原理解析,需要的朋友可以参考下
    2018-12-12
  • Vue自嵌套树组件使用方法详解

    Vue自嵌套树组件使用方法详解

    这篇文章主要为大家详细介绍了Vue自嵌套树组件的使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • vue项目中api接口管理总结

    vue项目中api接口管理总结

    本篇文章给大家介绍了vue项目中API接口管理的相关知识点,以及相关JS代码分析,有兴趣的朋友参考下。
    2018-04-04
  • Vue3路由配置createRouter、createWebHistory、useRouter和useRoute详解

    Vue3路由配置createRouter、createWebHistory、useRouter和useRoute详解

    Vue3和Vue2基本差不多,只不过需要将createRouter、createWebHistory从vue-router中引入,再进行使用,下面这篇文章主要给大家介绍了关于Vue3路由配置createRouter、createWebHistory、useRouter和useRoute的相关资料,需要的朋友可以参考下
    2023-02-02
  • Vue CLI 3搭建vue+vuex最全分析(推荐)

    Vue CLI 3搭建vue+vuex最全分析(推荐)

    这篇文章主要介绍了Vue CLI 3搭建vue+vuex最全分析(推荐),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue+vuex+json-seiver实现数据展示+分页功能

    vue+vuex+json-seiver实现数据展示+分页功能

    这篇文章主要介绍了vue+vuex+json-seiver实现数据展示+分页功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-04-04

最新评论