Vue2之组件通信(爆肝)

news2024/12/29 11:51:23

大家有什么想看的可以在评论区留言,我尽量满足,感谢大家!

组件通信是vue中一个非常重要的内容,我们需要掌握好组件通信,那么让我为大家介绍几种组件通信的方式吧!

一、props

这是父传子的方式,它有三种方式去定义,让我为大家介绍一下

注意:
props是只读的,不要去修改 vue底层监视了props 如果被修改它会发出警告

代码与介绍如下:

// 父组件
<template>
  <div>
    <!-- 我为Student添加属性 -->
    <!-- 传递数据 -->
    <Student name="张三" :age="18" sex="" />
  </div>
</template>
<script>
// 导入Student组件
import Student from './components/Student.vue'
export default {
  name:'App',
  components:{
    Student
  }
}
</script>

// 子组件
<template>
  <div>
      <div>姓名:{{ name }}</div>
      <div>年龄:{{ age }}</div>
      <div>性别:{{ sex }}</div>
  </div>
</template>
<script>
export default {
  name: 'MyStudent',
  // 我这里可以使用到props去接收数据
  // 这个数据会在哪呢? 
  // 它会在VC 也就是这个组件实例身上
  // 第一种方法 只接受
  // props: ["name", "age", "sex"],
  //......................
  // 第二种方法 限制类型 
  // 限制了类型 假设我们传入了一个跟这类型不一样的值
  // 它会在控制台报错 但不影响数据传递 为什么呢
  // 它可以给操作人员做到提示的用处
  // props:{
  //     // 记得大写
  //     name:String,
  //     age:Number,
  //     sex:String,
  // },
  //......................
  // 第三种 限制类型 限制必要性 指定默认值
  props:{
      name:{
          type:String,
          required:true
      },
      age:{
          type:Number,
          default:18
      },
      sex:{
          type:String,
          required:true
      }
  }
}
</script>

在这里插入图片描述

二、自定义事件

配合$emit
顾名思义 自定义事件 我们自己定义的事件
可以实现子传父

// 父组件
<template>
  <div>
    <!-- 自定义事件 你想定义什么都行 -->
    <Student @getStudentName="getStudentName" />
    <!-- 注意事项 如果我想使用原生的DOM事件 我们需要添加上native修饰符 -->
    <Student @click.native="test" />
  </div>
</template>

<script>
// 导入Student组件
import Student from './components/Student.vue'
export default {
  name: 'App',
  components: {
    Student
  },
  methods: {
    getStudentName(value) {
      console.log(value) // 打印 张三
    },
    test() {
      console.log(1);
    }
  }
}
</script>

// 子组件
<template>
    <div>
        <div>我是Student组件</div>
        <button @click="sendStudentName">点击名字传给父组件</button>
        <button @click="offStudentName">解绑</button>
    </div>
</template>

<script>
export default {
    name: 'MyStudent',
    data(){
        return {
            name:'张三'
        }
    },
    methods:{
        sendStudentName(){
            // this.$emit(触发的事件,传入的数据)
            this.$emit('getStudentName',this.name)
        },
        // 解绑 
        offStudentName(){
            // off有三种写法
            // 解绑单个 this.$off(绑定的事件)
            this.$off('getStudentName')
            // 解绑多个 使用数组 this.$off(["事件","事件"])
            // 解绑全部
            // this.$off()
        }
    }
}
</script>

请添加图片描述

三、ref

ref也可以实现子传父
使用到$on 既然有 $on 那就有 $off

// 父组件
<template>
  <div>
    <!-- ref绑定一个名字 -->
    <Student ref="student" />
  </div>
</template>
<script>
// 导入Student组件
import Student from './components/Student.vue'
export default {
  name: 'App',
  components: {
    Student
  },
  methods: {
    getStudentName(value) {
      console.log(value) // 打印 张三
    }
  },
  // 最好写在 mounted中
  mounted(){
    // $on 绑定事件 最好写成箭头函数 不然this指向student这个组件,不指向App组件
    // this.$refs.student.$on('getStudentName',(value)=>{
    //   console.log(value) // 张三
    // })
    // 通常是如下写法
    this.$refs.student.$on('getStudentName',this.getStudentName)
  }
}
</script>

// 子组件
<template>
  <div>
      <div>我是Student组件</div>
      <button @click="sendStudentName">点击名字传给父组件</button>
  </div>
</template>
<script>
export default {
  name: 'MyStudent',
  data(){
      return {
          name:'张三'
      }
  },
  methods:{
      sendStudentName(){
          // this.$emit(触发的事件,传入的数据)
          this.$emit('getStudentName',this.name)
      }
  }
}
</script>

请添加图片描述

四、v-model

咦,这不是双向数据绑定吗?它怎么会出现在咋们的组件通信里?
好,接下来大家要知道v-model的原理
其实他还是借助了自定义事件,与props,当一个扩展知识吧!
原理: v-model本质上是一个语法糖例如应用在输入框上,就是 value属性 和 input事件 的合写
就是下面这段代码,假设我在data中有数据,我使用双向数据绑定

<Student :value="age" @input="age = $event.target.value"></Student>

父组件代码:

<template>
  <div>
    <!-- 我们使用v-model v-model的原理采用了
     :value + @input="?=$event.target.value" -->
    <BaseSelect v-model="selectId"></BaseSelect>
  </div>
</template>
<script>
import BaseSelect from "./components/BaseSelect.vue"
export default {
  name: 'VueApp',
  data() {
    return {
      selectId: '2',
    };
  },
  components: {
    BaseSelect
  }
};
</script>
<style scoped></style>

子组件代码:

<template>
    <div>
        <!-- 我们不能直接使用v-model去绑定 -->
        <!-- 我们使用change事件监听 -->
        <select :value="value" @change="handleChange">
            <option value="1">北京</option>
            <option value="2">上海</option>
            <option value="3">广州</option>
            <option value="4">深圳</option>
        </select>
    </div>
</template>
<script>
export default {
    name: 'VueBaseSelect',
    props: {
        // 我们直接使用value去接收父组件中的selectId
        value: String
    },
    methods: {
        handleChange(e) {
            // 子传父 用到this.$emit() input事件 因为我们父组件的事件是input
            this.$emit("input", e.target.value)
        }
    }
};
</script>
<style scoped></style>

请添加图片描述

五、sync

其实这跟上面的v-model有异曲同工之处

作用:可以实现 子组件 与 组件数据的 双向绑定,简化代码

特点: prop属性名,可以自定义,非固定为 value

场景:封装弹框类的基础组件,visible属性 true显示false隐藏

本质:就是 :属性名 和 @update:属性名 合写

<BaseDialog :visible.sync="isShow" />
-----------------------------------
<BaseDialog :visible="isShow" @update:visible="isShow=$event" />

上代码

父组件:

<template>
  <div>
    <button @click="isShow=true">点击退出登录</button>
    <BaseDialog :visible.sync="isShow" />
    <!-- <BaseDialog :visible="isShow" @update:visible="isShow=$event" /> -->
  </div>
</template>

<script>
import BaseDialog from './components/BaseDialog.vue';
export default {
  name:'App',
  data() {
    return {
        isShow:false
    }
  },
  components:{
    BaseDialog
  }
  
}
</script>

<style lang='scss' scoped>

</style>

子组件:

<template>
    <div v-show="visible" class="box">
        <div class="contentBox">
            <h1 class="outText">你确定确定退出吗?</h1>
            <div class="button">
                <button @click="confirm">确定</button>
                <button @click="close">取消</button>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    name: 'MyBaseDialog',
    props:{
        visible:Boolean
    },
    data() {
        return {

        }
    },
    methods:{
        confirm(){
            this.$emit('update:visible',false)
        },
        close(){
            this.$emit('update:visible',false)
        }
    }
}
</script>

<style scoped>
.box {
    position: absolute;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.1);
}

.contentBox {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 500px;
    height: 400px;
    background-color: #fff;
}

.outText {
    text-align: center;
}
.button {
    display: flex;
    justify-content: space-around;
}
.button button{
    font-size: 40px;
}
</style>

请添加图片描述

六、全局事件总线

一看这个名字就觉得,全局,那我是不是在哪个组件都可以使用呀,没错,是的

首先要有一个概念,既然是全局下的,我如何在别的组件中看见这个方法,并且我们需要用到$on 与 $emit,它们只有在vm上才会存在,所有我们可以在vue的原型对象上声明一个方法,好,废话不多说,上操作

我们找到main.js

new Vue({
  render: h => h(App),
  beforeCreate() {
    // 使用全局事件总线 最好在beforeCreate中写
    Vue.prototype.$bus = this
  },
}).$mount('#app')

组件

// 父组件
<template>
  <div>
    <Student></Student>
  </div>
</template>
<script>


import Student from './components/Student.vue'
export default {
  name:'MyApp',
  data() {
    return {
        name:''
    }
  },
  components:{
    Student
  },
  mounted() {
    this.$bus.$on("getStudentName",(data)=>{
        console.log(data);
    })
  }
}
</script>

<style lang='scss' scoped>

</style>

// 子组件
<template>
    <div>
        <div>我是Student组件</div>
        <button @click="sendStudentName">点击名字传给父组件</button>
    </div>
</template>

<script>
export default {
    name: 'MyStudent',
    data(){
        return {
            name:'张三'
        }
    },
    methods:{
        sendStudentName(){
            // this..$bus.$emit(触发的事件,传入的数据)
            this.$bus.$emit('getStudentName',this.name)
        }
    }
}
</script>

请添加图片描述

七、provide & inject

跨组件共享数据

子孙后代都可以收到

我认为这种方法挺方便的

来,为大家展示一下

父组件

<template>
    <div>
        <button @click="updateColor">点击修改颜色</button>
        <button @click="updateName">点击修改姓名</button>
        <Home></Home>
    </div>
</template>

<script>
import Home from './components/Home.vue';
export default {
    name: 'App',
    // 来我们使用一下provide
    provide() {
        return {
            color: this.color,
            info: this.info
        }
    },
    components: {
        Home
    },
    data() {
        return {
            // 普通数据类型 非响应式
            color: 'pink',
            // 复杂数据类型 响应式
            info: {
                name: '张三',
                age: 18
            }
        }
    },
    methods: {
        updateColor() {
            this.color = 'red'
        },
        updateName() {
            this.info.name = '李四'
        }
    }
}
</script>

<style lang='scss' scoped></style>

子组件

<template>
    <div>
        <div>{{ color }}</div>
        <div>
             {{ info.name }}---{{ info.age }}
        </div>
    </div>
</template>

<script>
export default {
    name: 'MyHome',
    // 我们使用inject去做接收
    inject:['color','info'],
}
</script>

<style lang='scss' scoped></style>

请添加图片描述

八、消息订阅与发布

定阅消息:消息名
发布消息:消息内容

通俗易懂的例子

订阅报纸:地址
邮递员送报纸:报纸

我们需要使用到第三方组件库

npm i pubsub-js

父组件:

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

<script>
// 引入pubsub
import pubsub from 'pubsub-js'
import Student from './components/Student.vue'
export default {
  name:'App',
  components:{
    Student
  },
  mounted(){
    // 订阅消息 第一个参数订阅的消息名 第二个回调函数
    // 最好写成箭头函数 要不然this指向会有问题
    // 回调函数有两个参数 第一个消息名 第二个订阅的数据
    this.pubId = pubsub.subscribe("name",(msgName,data)=>{
        console.log(msgName,data);
    })
  }
}
</script>

<style lang='scss' scoped>

</style>

子组件

<template>
  <div>
    <button @click="sendData">点击发布</button>
  </div>
</template>

<script>
// 引入pubsub
import pubsub from 'pubsub-js'
export default {
  name:'MyStudent',
  data() {
    return {
        name:'张三'
    }
  },
  methods:{
    sendData(){
        pubsub.publish('name',this.name)
    }
  }
}
</script>

<style lang='scss' scoped>

</style>

请添加图片描述

九、$parent 与 $children

大家一看,这不就是父子吗?没错确实是父子,哈哈

$children 可以有多个,所以是数组,如果父组件中没有子组件,children就是空数组
$parent是个对象,如在#app上拿parent得到的是new Vue()的实例,在这实例上再拿 parent得到的是undefined

父组件

<template>
    <div>
        <div>{{ name }}</div>
        <div>{{ msg }}</div>
        <Student :msg="msg"></Student>
        <button @click="getChildren">点击获取子组件的name</button>
    </div>
</template>

<script>
import Student from './components/Student.vue';
export default {
    name: 'App',
    components: {
        Student
    },
    data() {
        return {
            name:'',
            msg: '码字中.....'
        }
    },
    methods: {
        getChildren() {
           this.name = this.$children[0].name
        }
    }
}
</script>

<style lang='scss' scoped></style>

子组件

<template>
  <div>
    <button @click="updateParent">点击修改父组件的msg</button>
  </div>
</template>

<script>
export default {
  name:'MyStudent',
  props:["msg"],
  data() {
    return {
        name:'张三'
    }
  },
  methods:{
    updateParent(){
        this.$parent.msg = '疯狂码字中'
    }
  }
}
</script>

<style lang='scss' scoped>

</style>

请添加图片描述

还有几种方式,日后补全,感谢大家的阅读

最值得欣的景,是自己奋斗的足迹,加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1606478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FFmpeg合并音视频文件操作备忘(mac版)

利用NDM嗅探插件从B站下载下来的文件是音视频分开的&#xff0c;用剪辑软件合并时发现导出时文件都特别大&#xff0c;于是使用FFmpeg处理 环境&#xff1a; MBP M1芯片版 系统 macOS Sonama 14.4.1 操作步骤&#xff1a; 一、官方下载链接&#xff1a;https://evermeet.cx/…

MySQL 锁机制全面解析

目录 1. MySQL的锁类型1.1 全局锁1.2 表锁1.3 行锁1.4 共享锁&#xff08;读锁&#xff09;1.5 排它锁&#xff08;写锁&#xff09;1.6 死锁 2 乐观锁和悲观锁2.1 乐观锁2.2 悲观锁 3 意向锁4 间隙锁5 临键锁6. 事务隔离级别对锁的影响6.1 读未提交&#xff08;Read Uncommitt…

npm内部机制与核心原理

npm 的核心目标&#xff1a; Bring the best of open source to you, your team and your company. npm 最重要的任务是安装和维护开源库。 npm 安装机制与背后思想 npm 的安装机制非常值得探究。Ruby 的 Gem&#xff0c;Python的pip都是全局安装机制&#xff0c;但是npm的安装…

️️️Vue3+Element-Plus二次封装一个可定制化的table组件

前言 为什么需要二次封装 开发后台管理系统,会接触到很多表格和表单,一但表格表单多起来,仅仅只需要一小部分改变&#xff0c;都需要在中重写一大堆代码,许多重复逻辑,我们可以把重复逻辑抽离出来二次封装一个组件 使用,减少在开发中需要编写的代码。 为什么需要定制化 每个…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点&#xff1a; 最大的优点就是免费&#xff08;但说实话功能和体验方面很弱&#xff09;支持中文提问&#xff08;最好用英文&#xff09;&#xff0c;智能生成图文&#xff08;但是只能生成英文内容&#xff09;可以AI生成图片&#xff0c;图片很精美酷炫&#xff0…

数据可视化(四):Pandas技术的高级操作案例,豆瓣电影数据也能轻松分析!

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

(八)Pandas窗口数据与数据读写 学习简要笔记 #Python #CDA学习打卡

一. 窗口数据(Window Functions) Pandas提供了窗口函数(Window Functions)用于在数据上执行滑动窗口操作&#xff0c;可以对数据进行滚动计算、滑动统计等操作。需要注意的是&#xff0c;在使用窗口函数时&#xff0c;需要根据实际需求选择合适的窗口大小和窗口函数&#xff0…

硬件设备杂记——12G SDI及 AES67/EBU

常见的 SDI线缆规格&#xff0c;HD-SDI又被称为1.5G-SDI&#xff0c;具体参数以秋叶原的参数为例 AES67/EBU 目前音频网络标准主要集中在OSI网络体系的第二层和第三层。 第二层音频标准的弊端在于构建音频网络时需要专用的交换机&#xff0c;无法利用现有的以太网络&#xff0c…

布局香港之零售中小企篇 | 传承之味,迈向数字化经营的时代

随着内地与香港两地经贸合作日渐紧密&#xff0c;越来越多内地消费品牌将目光投向香港这片充满机遇的热土&#xff0c;纷纷入驻香港市场。「北店南下」蔚然成风&#xff0c;其中不乏已在内地市场深耕多年的传统老字号。数字化经营时代&#xff0c;老字号焕新刻不容缓&#xff0…

QoS流量整形

流量整形是一种带宽技术形式&#xff0c;它延迟某些类型的网络数据包的流动&#xff0c;以确保更高优先级应用程序的网络性能&#xff0c;它主要涉及调整数据传输速率&#xff0c;以确保网络资源以最佳容量得到利用。流量整形的目的是防止网络拥塞并提高网络的整体性能&#xf…

【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析 题目链接&#xff1a;912. 排序数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路&#xff1a; 快速排序作为一种经典的排序算法&#xff0c;其核心思想在于通过“分而治之”的策略&#xff…

C++:深入理解operator new/operator delete

动态内存管理 1.语法层面1.基本语法注意点 2.new/delete和malloc/free的区别3.operator new和operator delete函数&#xff08;底层重点&#xff09;1.operator new/delete原理2.图解1.new/new[]2.delete/delete[] 3.new[n]和delete[] 4.定位new1.定义2.使用格式 1.语法层面 1…

EPSON晶振应用到汽车电子产品上的型号有哪些?

EPSON品牌应用在汽车电子产品上的晶振.&#xff0c;当然也少不了晶振可能最熟悉的就是32.768K系列和26MHZGPS晶振用的多。 在汽车里每一个部件都应有的不一样,甚至多次使用到同一尺寸,不同频率的晶振.爱普生品牌晶振型号就有几百种,很容易混淆,要想记住汽车里所应用到的不是件…

python爬虫(Selenium案列)第二十四

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

windows docker desktop==spark环境搭建

编写文件docker-compose.yml version: 3services:spark-master:image: bde2020/spark-master:3.1.1-hadoop3.2container_name: spark-masterports:- "8080:8080"- "7077:7077"- "2220:22"volumes:- F:\spark-data\m1:/dataenvironment:- INIT_D…

HiveSql中的函数家族(二)

一、窗口函数 1、什么是窗口函数 在 SQL 中&#xff0c;窗口函数&#xff08;Window Functions&#xff09;是一种特殊的函数&#xff0c;它允许在查询结果集的特定窗口&#xff08;通常是一组行&#xff09;上执行聚合、分析和计算操作&#xff0c;而无需聚合整个结果集。窗口…

Linux 2.进程(守护进程)

守护进程 何谓守护进程常见守护进程进程查看命令pskill命令编写简单守护进程守护进程的父进程 何谓守护进程 daemon&#xff0c;表示守护进程&#xff0c;简称为d&#xff08;进程名后面带d的基本就是守护进程&#xff09; 长期运行&#xff08;一般是开机运行直到关机时关闭&…

Flask项目在Pycharm中设置局域网访问

打开PyCharm导入本应用。点击Run标签中的Edit Configurations 其中Target type选择Script path&#xff0c;Target填入本项目中app.py的路径&#xff0c;Additional optional填入--host0.0.0.0(不要有空格)。 再重新运行项目&#xff0c;会观察到除了原本的http://127.0.0.1:50…

java在线问卷调查系统的设计与实现(springboot+mysql源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线问卷调查系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于java的在线问卷调查…

函数 基础知识

本笔记为观看 50 函数-函数的定义_哔哩哔哩_bilibili的学习笔记 1 函数概述 作用:将一段经常使用的代码封装起来&#xff0c;减少重复代码一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个块实现特定的功能。 2 函数的定义 eg: int max(int a,int b); {retu…