Vue组件之间传值

news2024/11/22 17:40:14

聊一聊vue里面组件之间的传值

首先总结一下vue里面传值的几种关系:
在这里插入图片描述
如上图所示, A与B、A与C、B与D、C与F组件之间是父子关系; B与C之间是兄弟关系;A与D、A与E之间是隔代关系; D与F是堂兄关系,针对以上关系 我们把组件之间传值归类为:
1.父子组件之间的通讯
2.非父子组件之间的通讯(兄弟组件 隔代关系组件)

vue里面组件通许的方式:

  1. props/$emit
  2. $children / $parent
  3. ref / refs
  4. provide / reject
  5. eventBus
  6. $attrs / $linteners
  7. vuex
  8. localStorage / sessionStorage

1.父组件向子组件传值

<template>
  <div class="section"><com-article :articles="articleList"></com-article></div>
</template>
<script>
import comArticle from './test/article.vue'
export default {
  name: 'HelloWorld',
  components: { comArticle },
  data() {
    return { articleList: ['1', '2', '3'] }
  }
}
</script>

<template>
  <div><span v-for="(item, index) in articles" :key="index">{{ item }}</span></div>
  <script>
    export default {
        props: ['articles']
      }
</script>

2.子组件向父组件传值

<template>
  <div class="section">
    <com-article :articles="articleList" @onEmitIndex="onEmitIndex"></com-article>
    <p>{{ currentIndex }}</p>
  </div>
</template>
<script>
import comArticle from './test/article.vue'
export default {
  name: 'HelloWorld',
  components: { comArticle },
  data() {
    return { currentIndex: -1, articleList: ['小姐姐', '小妹妹', '小富婆'] }
  },
  methods: {
    onEmitIndex(idx) {
      this.currentIndex = idx
    }
  }
}
</script>

// prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop
只读,不可被修改,所有修改都会失效并警告。


<template>
  <div>
    <div v-for="(item, index) in articles" :key="index" @click="emitIndex(index)">{{ item }}</div>
  </div>
</template><script>
export default {
  props: ['articles'],
  methods: {
    emitIndex(index) {
      this.$emit('onEmitIndex', index)
    }
  }
}
</script>

二. $children / $parent 直接简单点写法:

 this.$parent
 this.$children

这种方式是直接通过children 或者parent获取组件上的所有对象实例,并且他还是一个数组,我们一般要获取需要这么写
this.$children[0].age,通过索引获取到自己想要的子组件,当子组件比较多的时候,如果后期某个子组件删除了或者新增,对应的索引有可能会发生变化,既不利于维护,所以在实际开发中用的比较少。
同样的this. $parent获取父组件的所有实例对象,当涉及到公共子组件的时候,定义的名称可能耦合性比较高,如果以这种方式去修改父组件的状态,很容易出问题,甚至调试都很不方便,所以也一般用的比较少。

3. ref / refs
ref:如果在普通的 DOM 元素上使用,引用指向的就是DOM 元素,可以操作dom元素的方法,如果用在子组件上,引用就指向组件实例,可以通过实例直接调用子组件的方法或数据

<template>
    <span>{{name}}</span>
</template>
<script>
export default {
  data() {
    return {
      name: 'xxxx'
    }
  },
}
</script>

<template>
  <component-a ref="comA"></component-a>
  <span ref="spanRef">1234</span>
  <a-button type="primary" @click="handleClick">xx</a-button>
</template>
<script>
export default {
  methods: {
    handleClick(){
      console.log(this.$refs.spanRef.innerHtml); // 1234
      const comA = this.$refs.comA;
    console.log(comA.name)
    }
  },
}
</script>

4.provide / reject

5.eventBus
eventBus可以作为全局组件通信(任意的两个组件,没有任何关联的组件),可以直接进行交流的通讯方案,eventBus通常用来做全局范围内通信的一个常用方案,非常灵活 使用简单而且很轻
在vue2里面的使用:

import Vue from 'vue'
// main.js 中
 
// 第一种定义方式
Vue.prototype.$eventBus = new Vue()
 
// 第二种定义方式
window.eventBus = new Vue();

**触发事件:**
// params 多个参数
this.$eventBus.$emit('eventName', param1,param2,...)

//使用方式二定义时
eventBus.$emit('eventName', param1,param2,...)

**监听事件**
//使用方式一定义时
this.$eventBus.$on('eventName', (param1,param2,...)=>{
    //需要执行 逻辑代码
    // params 多个参数
})
 
//使用方式二定义时
eventBus.$on('eventName', (param1,param2,...)=>{
    //需要执行 逻辑代码
})

**移除事件,在开发过程中,当离开当前页面时要取消坚挺,避免事件被反复出发,和造成内存泄漏**
//使用方式一定义时
this.$eventBus.$off('eventName');
 
//使用方式二定义时
eventBus.$off('eventName');

EventBus的原理是什么? 直接上代码

class MyEventBus {
    constructor() {
        // 存储所有事件对应的回调的对应关系
        /**
         * key : [ callback, callback ]
         */
        this.items = {};
    }
    // 监听
    $on(eventName, callback) {
        if (!this.items[eventName]) {
            //一个事件可能有多个监听者
            this.items[eventName] = [];
        }
        this.items[eventName].push(callback)
        // 简化版写法 等同于上面
        // (this.items[eventName] ||= []).push(callback)
    }
    // 触发监听
    $emit(eventName, ...args) {
        if (!this.items[eventName]) return;
        this.items[eventName].forEach(ca => ca(...args))
    }
    // 去掉监听
    $off(eventName) {
        this.items[eventName] = []
    }
}
export default new MyEventBus();

Vue3种移除了$on $off等自带自定义事件的相关方法,因此在vue3中使用mitt来代替eventBus

    //在utils目录下,新建 mitt.js 文件,写入下面代码进行封装
    import mitt from 'mitt'
    const emitter =new mitt()
    export default emitter

   // 在使用中直接引入
    import emitter from '../api/mitt'
    emitter.on('foo', e => console.log(e) )  //emitter
    emitter.emit('foo', 'emitter')

  // 用法 引入封装好的mitt即可直接使用mitt,但需要注意:注册事件最好在钩子onMounted中进行,并且注册的事件需要在onUnmounted钩子中移除。如果不移除同样有可能会造成反复调用,和内存泄漏等问题
    // 引入 mitt
    import emitter from '../api/mitt'
    // 注册
    emitter.on('eventName', function(e) {
        console.log(e)
    })
    // 调用
    emitter.emit('eventName', 'emitter')
    // 移除
    emitter.off('eventName')


5. $attrs / $linteners

$attrs:用于多层次组件传递参数(组件标签的attribute,class和style除外),爷爷辈组件向孙子辈组件传递参数(注:参数不能被父辈prop识别,一旦被父辈prop识别且获取,则孙子辈组件不能获取到该参数) 并且 v-bind不能被简写

$listeners:用于多层次组件传递事件监听器,爷爷辈组件向父辈、孙子辈、曾孙子辈……组件传递事件(与 $attrs 不同,不存在半路被拦截的情况)v-on 不能用简写 @,虽然不报错,但是也不生效

<template>
  <div>
    GrandFather:
    <index1 :dataMessage="dataMessage" :dataCode="dataCode" :dataList="dataList" :grendClick="grendClick"
      @hancleClick="handleClick" @handleSelect="handleSelect" aaa="this is a undefiend" />
  </div>
</template>

<script>
import Index1 from "./index1";
export default {
  props: { dataStatus: Number },
  components: { Index1 },
  data() {
    return {
      a: 0,
      dataMessage: 1234,
      dataCode: "400",
      dataList: [1, 2, 3, 4, 5],
    };
  },
  methods: {
    handleClick() {
      console.log(1234);
    },
    handleSelect() {
      console.log(456);
    },
    grendClick() {
      console.log("grendClick");
    },
  },
};
</script>

<script>
import Index2 from './index2.vue';
export default {
   inheritAttrs: false,
  components: { Index2},
  props: {
    dataMessage: {
      default: 0,
      type: Number
    },
    grendClick: {
      default: () => {
        return Function
      }
    }
  },
  data() { return {  adus: '12345'  } },
  created() {
    // 这个从一级组件的dataMessage被当前页截取了。
    console.log(this.dataMessage, 'dataMessage');
  },
  methods: {
    handleClickB() {
      console.log('this is B');
      this.grendClick()
    },
  },
}
</script>

<template>
  <div>
    <span>GrandSon</span>
    <a-button type="primary" @click="handleClickC">GrandSon</a-button>
    <span ref="spanRef">1234</span>
  </div>
</template>

<script>
export default {
  inheritAttrs: false,
  methods: {
    handleClickC() {
      console.log(this.$attrs, 'attrs'); // 从最上级带过来的变量
      console.log(this.$listeners, 'listeners'); // 从最上级带过来方法
    },
  },
}
</script>

关于Vue的inheritAttrs的理解:
vue官网对于inheritAttrs的属性解释:默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。
如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false。

直接看效果: 当设置为true,默认是为true的
在这里插入图片描述

当设置为false时后:这也算的上是一点点小优化策略吧
在这里插入图片描述
7.localStorage / sessionStorage
这个我们用的应该是比较多的,我们在vue里面用的比较多的Vul-ls

import Vue from 'vue'
import Storage from 'vue-ls'

// vue-ls 的配置
const storageOptions = {
    namespace: 'vue_',   // key 键的前缀(随便起)
  	name: 'ls',          // 变量名称(随便起) 使用方式:Vue.变量名称 或 this.$变量名称
  	storage: 'local'     // 作用范围:local、session、memory
}

Vue.use(Storage, storageOptions)
就不做具体的操作了

浏览器缓存里面有个可以监听缓存变化的方法:废话不多说 上代码

export const resetSetItem = (key: string, newVal: string) => {
  if (key === 'reportcenterList') {
    // 创建一个StorageEvent事件
    const newStorageEvent = document.createEvent('StorageEvent')
    const storage = {
      setItem: function (k, val) {
        sessionStorage.setItem(k, val)
        // 初始化创建的事件
        newStorageEvent.initStorageEvent('setItem', false, false, k, null, val, null, null)
        // 派发对象
        window.dispatchEvent(newStorageEvent)
      }
    }
    return storage.setItem(key, newVal)
  }
}

// 调用
    resetSetItem('reportcenterList', JSON.stringify(val))
  console.log('监听到数据变化')
  const reportcenterList = sessionStorage.getItem('reportcenterList') || ''

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

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

相关文章

【C++模拟实现】反向迭代器的实现

【C模拟实现】反向迭代器的实现 目录 【C模拟实现】反向迭代器的实现反向迭代器的代码示例反向迭代器的模拟实现要点引入iterator模版参数rbegin()和rend()的实现 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9.5 前言&#xff1a;本篇博客主要介绍反向迭代器的实现&…

数字孪生与GIS:智慧城市的未来之路

数字孪生和地理信息系统&#xff08;GIS&#xff09;是两个在现代科技中崭露头角的概念&#xff0c;它们的融合为智慧城市项目带来了革命性的机会。本文将解释数字孪生为何需要融合GIS&#xff0c;并以智慧城市项目为例进行说明。 数字孪生是一种虚拟模型&#xff0c;它精确地…

财报解读:多品牌故事下,贝泰妮能否持续领航功效护肤?

2023年上半年&#xff0c;在消费品零售大盘整体上行之际&#xff0c;我国化妆品零售市场也实现了回暖。据国家统计局数据&#xff0c;上半年&#xff0c;全国社会消费品零售总额为227588亿元&#xff0c;同比增长8.2%。其中&#xff0c;化妆品零售总额为2071亿元&#xff0c;同…

苹果电脑系统性能检测 Geekbench 6 for Mac

Geekbench 是一款流行的跨平台基准测试工具&#xff0c;用于评估计算机和移动设备的性能。它可以测量处理器、内存、图形处理器和存储设备等硬件的性能&#xff0c;并生成相应的性能评分。 Geekbench 提供了简单易用的用户界面&#xff0c;用户只需点击运行测试即可开始评估设…

攻防世界-Hear-with-your-Eyes

原题 解题思路 是一个没有后缀的文件&#xff0c;题目提示要用眼睛看这段音频&#xff0c;notepad打开文件&#xff0c;没什么东西。 加后缀zip再解压看看。 使用Audacity打开音频文件

使用 Web HID API 在浏览器中进行HID设备交互(纯前端)

文章目录 目的基础说明示例工程&#xff08;HID透传测试工具&#xff09;总结 目的 最近再搞HID透传 《STM32 USB使用记录&#xff1a;HID类设备&#xff08;后篇&#xff09;》 。 市面上的各种测试工具都或多或少存在问题&#xff0c;所以就自己写一个工具进行测试。目前来…

运动耳机选购攻略、好的运动耳机推荐

如今&#xff0c;蓝牙耳机不仅是手机的最佳伴侣&#xff0c;也成为了运动爱好者的必备装备。但是&#xff0c;在如此众多的蓝牙耳机中&#xff0c;你是否对选购感到困惑呢&#xff1f;实际上&#xff0c;选择适合运动的蓝牙耳机需要考虑许多因素&#xff0c;如舒适度、稳固性、…

app自动化测试(Android)

Capability 是一组键值对的集合&#xff08;比如&#xff1a;"platformName": "Android"&#xff09;。Capability 主要用于通知 Appium 服务端建立 Session 需要的信息。客户端使用特定语言生成 Capabilities&#xff0c;最终会以 JSON 对象的形式发送给 …

气象站的构成及功能应用

气象站是一种用于观测、记录和报告天气数据的设备。它是由数据采集系统、通讯系统、供电系统和立杆支架构成。 一、气象站的构成&#xff1a; 数据采集系统&#xff1a;用于测量气温、湿度、风速、风向、气压、降雨量、雪深等气象参数。 通讯系统&#xff1a;收集和处理传感…

深度解析lettuce,为什么单连接也可以处理高并发redis请求

简介 什么是lettuce Spring Boot自2.0版本开始默认使用Lettuce作为Redis的客户端&#xff08;注1&#xff09;。Lettuce客户端基于Netty的NIO框架实现&#xff0c;对于大多数的Redis操作&#xff0c;只需要维持单一的连接即可高效支持业务端的并发请求 —— 这点与Jedis的连接…

电子科大软件系统架构设计——面向对象建模基础

文章目录 面向对象建模基础UML建模语言UML模型图用例图活动图类图顺序图通信图状态机图构件图部署图包图对象图组合结构图扩展图交互概览图时间图 BPMN建模语言业务建模定义模型元素流对象活动事件网关 流数据人工制品泳池和泳道 建模案例订单采购流程建模电商系统订货业务流程…

ITIL重大事件管理综合指南

什么是ITIL中的重大事件 重大事件是一个高影响力的紧急问题&#xff0c;通常影响整个组织或其主要部分。重大事件几乎总是导致组织的服务变得不可用&#xff0c;从而导致该组织的业务受到打击&#xff0c;并最终影响其财务状况。重大事件可以通过两种方式影响组织的服务&#…

MATLAB中movmean函数用法

目录 语法 说明 示例 向量的中心移动平均值 向量的尾部移动平均值 矩阵的移动平均值 包含缺失值的向量的移动平均值 基于样本点计算移动平均值 仅返回满窗口平均值 movmean函数的功能是对数据进行移动求平均值。 语法 M movmean(A,k) M movmean(A,[kb kf]) M mov…

四川玖璨电子商务有限公司:短视频有什么运营

根据短视频有什么运营&#xff0c;短视频的拍摄工具多种多样。无论是在手机上拍摄还是使用专业摄影设备&#xff0c;拍摄短视频的目的都是为了吸引观众的注意力和提升内容的质量。从小花费到高投入&#xff0c;在不断发展的短视频行业中&#xff0c;拍摄方法也得到了不断创新和…

Hadoop YARN HA 集群安装部署详细图文教程

目录 一、YARN 集群角色、部署规划 1.1 集群角色--概述 1.2 集群角色--ResourceManager&#xff08;RM&#xff09; 1.3 集群角色--NodeManager&#xff08;NM&#xff09; 1.4 HA 集群部署规划 二、YARN RM 重启机制 2.1 概述 2.2 演示 2.2.1 不开启 RM 重启机制…

RHCA之路---EX280(7)

RHCA之路—EX280(7) 1. 题目 Configure quotas and limits for project shrimp so that: The ResourceQuota resource is named ex280-quota The amount of memory consumed across all containers may not exceed 1Gi The total amount of CPU usage consumed across all con…

Qt包含文件不存在问题解决 QNetworkAccessManager

这里用到了Qt的网络模块&#xff0c;在.pro中添加了 QT network 但是添加 #include <QNetworkAccessManager> 会报错说找不到&#xff0c;可以通过在项目上右键执行qmake后&#xff0c;直接#include <QNetworkAccessManager>就不会报错了&#xff1a;

固定资产管理怎么改革

固定资产管理改革需要考虑以下几个方面&#xff1a; 建立完善的管理制度和流程&#xff1a;制定固定资产管理的规章制度&#xff0c;明确各部门的职责和任务&#xff0c;规范资产采购、登记、领用、保管、维修、报废等流程。 采用先进的资产管理软件&#xff1a;通过采用先进的…

【python基础知识】5.for循环和while循环

文章目录 前言for...in...循环语句for循环&#xff1a;空房间for循环&#xff1a;一群排队办业务的人range()函数for循环&#xff1a;办事流程 while循环while循环&#xff1a;放行条件while循环&#xff1a;办事流程 两种循环对比 前言 上一关&#xff0c;我们学习了两种新的…

新23转债上市价格预测

新23转债 基本信息 转债名称&#xff1a;新23转债&#xff0c;评级&#xff1a;AA-&#xff0c;发行规模&#xff1a;11.6亿元。 正股名称&#xff1a;新泉股份&#xff0c;今日收盘价&#xff1a;53.17元&#xff0c;转股价格&#xff1a;51.35元。 当前转股价值 转债面值 / …