vue2 八大组件通信,父子通信,跨层级通信,事件总线,vuex等

news2024/12/26 23:24:11

文章目录

  • 什么是组件通信?
  • 父子通信流程
  • props
    • Props 定义
    • Props 作用
    • 特点
    • 数组写法
    • 对象写法(props校验)
      • 简写只验证数据类型:
      • 完整写法,完整的验证:
  • props父向子传值
    • 用`props`父传子
    • 在子组件中修改`props`
  • $emit子向父传值
    • 用`props`子传父
    • 用`$emit`子传父
  • 事件总线
    • 事件总线前置知识
      • `$on`
      • `$off`
    • 事件总线的使用
  • 父通过ref、$refs向子拿值
  • 父子通信`$children` /`$parent`
      • $children
        • 示例
      • $parent
        • 示例
      • 注意事项
  • 跨层级通信`provide/inject`
  • 跨层级通信`attrs/listeners`
  • vuex

什么是组件通信?

组件通信,就是指组件与组件之间的数据传递

  • 组件的数据是独立的,无法直接访问其他组件的数据
  • 想使用其他组件的数据,就需要组件通信

父子通信流程

  1. 父组件通过 props 将数据传递给子组件
  2. 子组件利用 $emit 通知父组件修改更新
image-20240414202919381

props

Props 定义

组件上 注册的一些 自定义属性

Props 作用

  1. 向子组件传递数据

  2. props接受的数据,只读,不可修改

  3. props接收到的简单数据类型,不可修改

  4. props接收到的复杂数据类型,可修改,vue也不会报错,但是不建议这样做

特点

  1. 可以 传递 任意数量 的prop
  2. 可以 传递 任意类型 的prop

数组写法

数组写法没有校验,所以不会在控制台报错

props: ['title','text', 'name']

对象写法(props校验)

作用:

  • 为组件的 prop 指定验证要求,不符合要求,控制台就会有错误提示
  • 帮助开发者,快速发现错误

简写只验证数据类型:

props: {
    校验的属性名: 数据类型
}

完整写法,完整的验证:

props: {
  校验的属性名: {
    type: 数据类型,  // Number String Boolean ...
    required: true, // 是否必填
    default: 默认值, // 默认值(未传值就使用默认值)
    validator (value) {  // value接收的就是传过来的值
      // 自定义校验逻辑
      return 布尔值   // 返回true就代表通过验证
    }
  }
}

示例:

<script>
export default {
  // 完整写法(类型、默认值、非空、自定义校验)
  props: {
    w: {
      type: Number,
      //required: true,
      default: 0,
      validator(val) {
        // console.log(val)
        if (val >= 100 || val <= 0) {
          console.error('传入的范围必须是0-100之间')
          return false
        } else {
          return true
        }
      },
    },
  },
}
</script>

props父向子传值

props父传子

  1. 给子组件以添加属性的方式传值
  2. 子组件内部通过props接收
  3. 模板中直接使用 props接收的值

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在子组件中修改props

  1. 如果传过来的是简单数据类型,那么是无法修改的
  2. 如果传过来的是复杂数据类型,那么是可以修改的,但是不建议去修改
  3. 子组件如果要修改父组件传过来的数据的话,可以用$emit去触发父组件的自定义事件,让父组件自己去修改数据

$emit子向父传值

props子传父

  1. 父通过自定义属性将自己的方法传送出去
  2. 子通过props接受父传过来的方法
  3. 子通过调用接收过来的方法去传参的形式传数据
  4. 因为方法是在父亲身上,父亲因此接收到了数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

$emit子传父

  1. 给子组件绑定自定义事件,事件触发时调用来自父亲的回调函数
  2. vm.$emit( eventName, […args] )eventName为字符串类型,[…args]可省略,或者传入多条数据
  3. 在子组件内利用$emit触发子组件绑定的自定义事件,传入数据,进行修改更新

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上图流程:

  1. 点击button,调用回调函数changeTitle
  2. 回调函数调用$emit方法
  3. $emit方法会去触发子组件绑定的自定义事件changeTitle,同时传入参数
  4. 子组件绑定的自定义事件changeTitle被触发后会调用回调函数handleChange
  5. 回调函数handleChange用接收到的参数去修改数据msg

事件总线

事件总线前置知识

$on

可以给当前实例添加自定义事件,并且监听添加的自定义事件

  1. vm.$on( event, callback )
  2. 在 Vue 2 中,$on 是 Vue 实例的一个方法,监听当前实例上的自定义事件
  3. 事件可以由 vm.$emit 触发,当触发这些事件时,可以执行相应的回调函数
  4. 相比于在标签上直接写事件,通过$on添加的自定义事件灵活性更强

$off

用于移除自定义事件监听器

  1. vm.$off( [event, callback] )
  2. 如果没有提供参数,则移除所有的事件监听器
  3. 如果只提供了事件,则移除该事件所有的监听器
  4. 如果同时提供了事件与回调,则只移除这个回调的监听器

事件总线的使用

事件总线可以用于任意两个组件之间的通信

1、在src目录下创建个utils文件夹,里面创建EventBus.js文件(事件总线)

EventBus.js

// 导入vue文件
import Vue from 'vue'
// 创建空vue实例对象
const Bus = new Vue()
// 导出空vue实例对象
export default Bus

2、接收方son1.vue

<template>
  <div>
    我是son1(接收消息)
  </div>
</template>
<script>
import Bus from '../utils/EventBus'
export default {
  name: 'mySon1',
  created(){
    Bus.$on('myEvent',(msg)=>{   // 通过$on为Bus自定义事件,当事件触发时,后面的回调函数接收信息
      console.log('我是son1拿到了son2的数据:',msg)
    })
  }
}
</script>

3、发送方son2.vue

<template>
  <div>
    我是son2(发布消息)
    <button @click="sendMsg">发送消息</button>
  </div>
</template>
<script>
import Bus from '@/utils/EventBus'
export default {
  name: 'mySon2',
  data() {
    return {
      msg: '我是son2中的数据'
    }
  },
  methods: {
    sendMsg() {
      Bus.$emit('myEvent', this.msg)  // 通过$emit触发事件,触发事件的同时将数据传出去
    }
  }
}
</script>

​ Vue 的事件总线通常是通过将其定义在 Vue 的原型上来实现的,这样任何 Vue 组件都可以通过 this.$bus 来访问和使用它。这样做的好处是全局事件总线可以在任何组件内部进行事件的触发和监听,提供了一种在组件之间通信的机制

在 Vue 中定义全局事件总线的一般步骤是:

  1. 创建一个新的 Vue 实例作为事件总线。
  2. 将这个 Vue 实例挂载到 Vue 的原型上,通常使用 $bus 作为属性名。

示例如下:

// main.js 或其他入口文件  
import Vue from 'vue';  
import App from './App.vue';  
  
// 创建一个新的 Vue 实例作为事件总线  
const EventBus = new Vue();  
  
// 将事件总线挂载到 Vue 的原型上  
Vue.prototype.$bus = EventBus;  
  
new Vue({  
  render: h => h(App),  
}).$mount('#app');

之后,在任何一个 Vue 组件中,你都可以通过 this.$bus 来访问这个全局事件总线,然后使用 $emit 方法来触发事件,或者使用 $on$off$once 方法来监听、取消监听或一次性监听事件。

// 在某个组件中触发事件  
this.$bus.$emit('event-name', payload);  
  
// 在另一个组件中监听事件  
this.$bus.$on('event-name', (payload) => {  
  // 处理事件逻辑  
});

虽然全局事件总线提供了一种便捷的组件间通信方式,但它也有一些潜在的问题。过度使用全局事件总线可能导致组件之间的耦合度过高,使得代码难以理解和维护。因此,在使用全局事件总线时,需要权衡其便利性和潜在的风险,并考虑其他组件间通信的方式,如 props、事件、Vuex 等

父通过ref、$refs向子拿值

​ 用ref给子组件打标记,使用$refs获取到的是vc组件(子组件)实例对象,拿到了vc实例对象了,我们就可以对子组件进行操作,拿取子组件中的值

son.vue

<template>
  <div>
    我是子组件
  </div>
</template>
<script>
export default {
  name: 'mySon',
  data() {
    return {
      msg: '我是子组件中的数据'
    }
  }
}
</script>

App.vue

<template>
  <div>
    <son ref="son"></son>
  </div>
</template>
<script>
import son from './components/son.vue';
export default {
  components: { son },
  mounted() {
    console.log(this.$refs.son.msg)    // 我是子组件中的数据
  }
}
</script>

父子通信$children /$parent

在 Vue 2 中,$children$parent 是两个实例属性,它们允许你直接访问组件的父级或子级组件实例。然而,这种直接的父子通信方式通常不推荐用于复杂的组件结构,因为它们使组件之间的依赖关系变得隐式和难以维护。但是,在某些简单的场景下,它们可能是有用的。

$children

$children 是一个数组,包含当前组件实例的直接子组件。请注意,$children 并不保证顺序,也不是响应式的。

示例
// 父组件
export default {
  mounted() {
    console.log(this.$children); // 输出子组件的数组
  }
}

// 子组件(可能有很多)
// ...

$parent

$parent 属性用来访问当前组件实例的父组件实例。

示例
// 子组件
export default {
  mounted() {
    console.log(this.$parent); // 输出父组件的实例
    // 你可以通过 this.$parent 访问父组件的数据、方法等
  }
}

注意事项

  1. 不推荐过度使用:过度依赖 $parent$children 会导致组件之间的耦合度过高,使得代码难以维护和理解。在复杂的项目中,应该优先使用 props 和 events 进行父子通信,或者使用 Vuex 进行状态管理。
  2. 非响应式$children 数组不是响应式的,也就是说,当子组件被添加或删除时,Vue 不会触发视图更新。因此,你不应该试图通过修改 $children 来控制组件的渲染。
  3. 顺序不保证$children 数组中的组件顺序并不保证与它们在模板中的顺序一致。因此,你不应该依赖 $children 数组的顺序来访问特定的子组件。
  4. 循环引用:在某些情况下,可能会出现父子组件之间循环引用的问题。这通常是由于不恰当的组件设计或错误的父子关系导致的。在这种情况下,使用 $parent$children 可能会导致不可预测的结果。
  5. 替代方案:对于父子组件之间的通信,推荐使用 props 和 events。对于跨组件通信,可以考虑使用 Vuex 或 EventBus(尽管 EventBus 在大型项目中也可能导致问题)。

跨层级通信provide/inject

provideinject 主要在开发高阶插件/组件库时使用。它们允许一个祖先组件向其所有子孙组件提供一个依赖,不论组件层次有多深,该依赖都可以注入进来。

// 祖先组件  
export default {  
  provide() {  
    return {  
      foo: 'foo'  
    };  
  },  
  // ...  
}  
 
// 子孙组件  
export default {  
  inject: ['foo'],  
  created() {  
    console.log(this.foo); // "foo"  
  }  
  // ...  
}

注意:provideinject 主要是为高阶插件/组件库开发而设计的。在大多数应用中,应优先使用 props 和 events 进行父子组件通信,并且对于跨多层级的通信,Vuex 会是更好的选择

跨层级通信attrs/listeners

在 Vue 2 中,$attrs$listeners 是两个特殊的属性,允许你在组件之间透传(passthrough)属性和事件监听器。

  • $attrs 包含了父组件中未被子组件声明的属性(attribute)。换句话说,它是一个对象,包含了父组件传递给子组件的所有属性,除了那些在子组件中已经通过 props 选项明确声明的。

  • $listeners 包含了父组件传递给子组件的所有事件监听器(即 v-on 绑定的事件)。

这两个特性在你需要创建封装组件或高阶组件时非常有用,因为它们允许你将额外的属性和事件监听器传递给子组件,而无需在封装组件中显式声明它们。

下面是一个简单的例子来说明 $attrs$listeners 的用法:

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :prop1="value1" @event1="handleEvent1" class="extra-class" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      value1: 'someValue'
    };
  },
  methods: {
    handleEvent1() {
      console.log('Event 1 triggered');
    }
  }
};
</script>
<!-- ChildComponent.vue -->
<template>
  <div>
    <GrandChildComponent v-bind="$attrs" v-on="$listeners" />
  </div>
</template>

<script>
import GrandChildComponent from './GrandChildComponent.vue';

export default {
  components: {
    GrandChildComponent
  },
  props: ['prop1'] // 假设 ChildComponent 只声明了一个 prop1
};
</script>
<!-- GrandChildComponent.vue -->
<template>
  <div>
    <!-- 这里可以访问通过 $attrs 传递过来的 class 和其他未声明的属性 -->
    <!-- 也可以触发通过 $listeners 传递过来的事件 -->
  </div>
</template>

<script>
export default {
  mounted() {
    // 假设我们要在这里触发 event1 事件
    this.$emit('event1');
  }
};
</script>

在上面的例子中,ParentComponent 传递了一个 prop1 属性,一个 event1 事件监听器,以及一个未声明的 class 属性给 ChildComponent。在 ChildComponent 中,我们只声明了 prop1 作为 prop,因此 class 属性会被包含在 $attrs 中。同时,event1 事件监听器会被包含在 $listeners 中。

当我们使用 v-bind="$attrs"v-on="$listeners" 将这些属性和事件监听器透传给 GrandChildComponent 时,GrandChildComponent 可以接收到这些属性和事件,就好像它们是直接被传递给它的一样。这样,GrandChildComponent 可以访问 class 属性和触发 event1 事件,尽管这些属性和事件是在 ParentComponent 中定义的。

vuex

Vuex 是一个插件,可以帮我们管理 Vue 通用的数据 (多组件共享的数据)

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

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

相关文章

美国政府发布新的国际网络空间和数字政策战略(上)

文章目录 前言一、战略内容介绍二、数字团结的含义三、如何建立数字团结前言 美国务院5月6日正式发布《美国国际网络空间和数字政策战略:迈向创新、安全和尊重权利的数字未来》,旨在指导国际社会参与技术外交并推动《美国国家安全战略》和《美国国家网络安全战略》。 美国务…

无人售货机开启财富新机遇

创立属于自己的小本事业&#xff0c;却因经验匮乏及风险顾虑望而却步&#xff1f;探索零风险且潜在高收益的创业途径&#xff0c;无人售货机项目脱颖而出&#xff0c;成为理想之选&#xff01; 无人售货机&#xff1a;市场蓝海待挖掘 在消费升级和技术飞跃的双重驱动下&#…

【DDR 终端稳压器】Sink and Source DDR Termination Regulator [C] S0 S1 S2 S3 S4 S5 6状态

TPS51200A-Q1 器件通过 EN 功能提供 S3 支持。EN引脚可以连接到终端应用中的SLP_S3信号。当EN 高电平&#xff08;S0 状态&#xff09;时&#xff0c;REFOUT 和 VO 引脚均导通。当EN 低电平&#xff08;S3状态&#xff09;时&#xff0c;VO引脚关断并通过内部放电MOSFET放电时…

Photoshop中图层的应用

Photoshop中图层的应用 前言Photoshop中的图层面板Photoshop中图层的基本操作新建图层复制/剪切图层链接图层修改图层名称及颜色背景图层与普通图层栅格化图层图层的对齐与分布图层的合并 前言 图层在Photoshop中就像一层一层的透明纸&#xff0c;可以透过图层的透明区域看到下…

纯血鸿蒙APP实战开发——阅读翻页方式案例

介绍 本示例展示手机阅读时左右翻页&#xff0c;上下翻页&#xff0c;覆盖翻页的功能。 效果图预览 使用说明 进入模块即是左右翻页模式。点击屏幕中间区域弹出上下菜单。点击设置按钮&#xff0c;弹出翻页方式切换按钮&#xff0c;点击可切换翻页方式。左右翻页方式可点击翻…

显影不干净如何解决?

知识星球&#xff08;星球名&#xff1a;芯片制造与封测社区&#xff0c;星球号&#xff1a;63559049&#xff09;里的学员问&#xff1a;光刻工序完成后&#xff0c;晶圆表面有部分图形容易出现显影不净是什么原因&#xff1f;有什么好的解决办法吗&#xff1f; 光刻工序流程 …

武汉星起航引领跨境新浪潮,一站式解决方案助力卖家驰骋亚马逊

在全球化浪潮下&#xff0c;跨境电商已成为外贸发展的新引擎&#xff0c;为无数创业者提供了全新的商业机遇。而在这场跨境电商的浪潮中&#xff0c;武汉星起航电子商务有限公司以其专业的一站式解决方案&#xff0c;成为众多创业者和卖家的得力助手&#xff0c;引领着他们成功…

信息系统项目管理师计算题讲解,考前必看

信息系统项目管理师考试中的计算题主要涉及项目管理类的计算&#xff0c;重点在于进度和成本的计算。案例计算题所占分值较高&#xff0c;务必要熟练掌握&#xff01;根据近年考题内容来看&#xff0c;主要涉及挣值计算和网络图&#xff0c;当然也可能会涉及其他内容&#xff0…

图片转pdf的java代码实现

一、实现方式 采用itextpdf和itext包&#xff0c;使用java代码&#xff0c;把图片转换为pdf. 支持文件格式&#xff1a;png&#xff0c;jpg, jpeg,gif 二、java代码实现 1、maven依赖 <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --><dependen…

【https】怎么免费实现https!

一、简介 实现 HTTPS&#xff08;Hyper Text Transfer Protocol Secure&#xff09;通常需要购买和配置 SSL/TLS 证书&#xff0c;这是确保网站或应用程序安全传输数据的关键步骤。然而&#xff0c;有一些方法可以在某些情况下“免费”地实现 HTTPS&#xff0c;但这通常涉及到…

重生奇迹mu再生宝石怎么用有什么用

重生奇迹mu再生宝石有2个用处&#xff1a; 1、在玛雅哥布林处给380装备加PVP属性4追4以上的380级装备,守护宝石一颗,再生宝石一颗,成功得到PVP装备,失败宝石消失,装备无变化&#xff1b; 2、给非套装点强化属性用法跟祝福,灵魂,生命一样直接往装备上敲,成功得到随机强化属性一…

Python框架Django入门教程

Django 是一个使用 Python 编程语言开发的、免费且开源的 Web 应用框架。它遵循 "DRY&#xff08;Dont Repeat Yourself&#xff09;" 原则&#xff0c;旨在简化创建功能丰富的、高效率的 Web 网站。Django 提供了模型-视图-控制器&#xff08;MVC&#xff09;架构的…

Bpmn.js使用(仅查看版)

Bpmn.js使用&#xff08;仅查看版&#xff09; 下载 npm install bpmn-js创建一个 Dom 节点来挂载画布元素。 <a-tabs v-model:activeKey"activeKey" change"tabsChange"><a-tab-pane key"1" tab"审批记录"><a-tabl…

LLM 可以从简单数据中学习吗?

在 10 月份的一次周会结束后&#xff0c;我提到 SFT 训练后的 Loss 曲线呈现阶梯状&#xff0c;至于为什么&#xff0c;并没有人有合理的解释&#xff0c;加上当时的重心是提升次日留存率&#xff0c;Loss 曲线呈现阶梯状与次日留存率的关系还太远&#xff0c;即使有问题&#…

99、技巧-下一个排列

这个问题要求生成一个数组的下一个排列。所谓“下一个排列”指的是&#xff0c;在所有数字相同但顺序不同的排列中&#xff0c;找出数字序列中刚好比当前序列大的下一个序列。如果当前序列已经是这些排列中的最大值&#xff0c;则下一个排列应该是最小的排列。 思路解释 要解…

【CTFHub】HTTP 请求方式 302跳转 cookie WP

1.请求方式 打开给出的URL进入一个页面&#xff0c;提示原方法是GET&#xff0c;用CTFHUB方法就能获得flag 思路&#xff1a;抓包&#xff0c;将GET方法改成CTFHUB方法进行重新发送请求&#xff0c;查看响应情况 1.打开代理服务器 2.打开BurpSuite 刷新页面获得拦截 3.发送…

天猫最热销的三款随身WiFi,哪一款直播最好用?2024公认最好的随身WiFi,天猫上的随身wifi是正规产品吗

近期有小伙伴问我&#xff1a;“小编、小编我要当户外博主了&#xff0c;想买一个随身WiFi&#xff0c;但是天猫榜单前三的随身WiFi自己都没有听说过&#xff0c;到底入手哪个比较好&#xff1f;”三款随身WiFi呢&#xff0c;分别是格行随身WiFi、迅优随身WiFi、小米随身WiFi&a…

Minimal-Supervised Medical Image Segmentation via Vector Quantization Memory

文章目录 Minimal-Supervised Medical Image Segmentation via Vector Quantization Memory摘要方法实验结果 Minimal-Supervised Medical Image Segmentation via Vector Quantization Memory 摘要 辅助重构分支&#xff1a;该分支通过提供额外的监督并产生学习视觉表示所需…

【JavaEE精炼宝库】多线程1(认识线程 | 创建线程 | Thread 类)

目录 一、认识线程 1.1 线程的概念&#xff1a; 1.2 为什么需要线程&#xff1a; 1.3 面试题.谈谈进程和线程的区别&#xff1a; 1.4 Java的线程和操作系统线程的关系&#xff1a; 二、创建线程 2.1 创建线程的5种写法&#xff1a; 2.1.1 写法1.继承 Thread 类&#xf…

JS实现初始化、动态点击切换激活样式

食用须知&#xff0c;不懂得把代码交给AI解释一下&#xff0c;明白流程就会用了&#xff0c;本文只有js与html&#xff0c;样式代码一概没有&#xff1a; 效果展示 1、点击显示的盒子代码 <div data-v-e1dd37c4"" class"news-container main-width-contain…