Vue基础2:传值方法

Description

传值就是为了联动,能够及时准确传值获取值才是王道。

Valuation Methods 

props和$emit

props是父传子,$emit是子传父。

props的使用

父组件传出值

<tableList ref="table" :options="options" :header-data="Columns" :table-data="Data" />

 父组件的中的子组件标签上我们加入的options,headerData,tableData三个变量是准备要传给子组件的。

子组件收到值

props: {tableData: {type: Array,default: () => {return []}},headerData: {type: Array,default: () => {return []}},options: {type: Object,default: () => {return {multiSelect: true, // boolean 是否多选singleSelect: false, // boolean 是否单个checkboxisindex: false, // boolean 是否展示序列号stripe: true, // boolean 斑马纹border: true, // boolean 纵向边框size: 'medium', // String  medium / small / mini  table尺寸fit: true, // 自动撑开pagination: true, // 是否有分页numPage: false}}},}

 延申

属性/方法作用
type传值的类型
default默认值;如果没有传,就使用
requied值为true/false,代表是否父组件是否必须传
validator(val){}可以判断父组件传过来的值是否有效

props:{name:{type:String,default:'默认为王三',required:true,validator(val){return val>0&&val<10}}}

 $emit的使用

子组件传出值

that.$emit('usbKeyForm', that.usbKeyForm)

父组件收到值

<certificateDialog :ssuingName="ssuingName" @usbKeyForm="usbKeyForm"/>methods: {usbKeyForm(val) {this.SerialNumber = val.SerialNumber},
}

思考:为什么两种方法不一样呢?

首先要明白传值的前提,为什么要传值,因为作用域。其实在Vue.js中每个组件都有自己的作用域,而且每个组件定义了一个props属性可以去接收父组件传过来的值,而且定义了type类型就是为了确定父级传过来的值的类型就是我们需要的,当然也可以修饰数据。如果加入required属性,值为true的时候,要求父组件必须要传的。default是设置默认值的,如果父组件没有传我们就使用默认值。所以我们经常看到使用props时候经常使用type+default两个属性搭配使用。

$emits传值原理是通过事件系统进行传值的,因为作用域是上下关系,你要是像下上关系,就得需要闭包传值。

$attrs和$listeners

组件关系A组件---》B组件----》C组件;大家都知道props和$emit是最常用的传值方法,但是仅限A到B或者B到A,如果A到C或者C到A呢?就需要用到$attrs和$listeners了

$attrs的使用

$attrs可以继承父组件里边的属性数据,并且携带下去。

通俗地来说就是如果从父组件传过来的值,没有在子组件中被接收,那么这些值就会被存在$attrs对象中。

 爷组件传出值

<son title="aaaaaaaaaaa" name="李四"/>

子组件收到值(子组件作为中间组件继续传递  v-bind="$attrs"

<template><div>儿子组件:{{$attrs.name}}<div><sunzi v-bind="$attrs"/></div></div>
</template><script>
import sunzi from './sunzi.vue';
export default {inheritAttrs: true,components:{sunzi},mounted(){console.log(this.$attrs)  //{title:"aaaaaaaaaaa" name:"李四"}}
}

孙子组件收到值(孙子组件使用 inheritAttrs: false)

<template><div>孙:{{name}}{{title}}</div>
</template><script>
export default {inheritAttrs: false,props: ["name","title", //注意props里的参数名称不能改变,必须和父组件传递过来的是一样的],data() {return {};},mounted(){console.log(this.$attrs) //可直接使用数据或者调用根组件的方法}
};

或者

 
<template><div>或者:{{$attrs.name}},{{$attrs.title}}</div>
</template><script>
export default {inheritAttrs: false,data() {return {};},mounted(){console.log(this.$attrs)//可直接使用数据或者调用根组件的方法}
};
</script>

inheritAttrs: false 的含义是不希望本组件的根元素继承父组件的attribute,同时父组件传过来的属性(没有被子组件的props接收的属性),也不会显示在子组件的dom元素上,但是在组件里可以通过其$attrs可以获取到没有使用的注册属性。

inheritAttrs: false 是不会影响 style 和 class 的绑定

inheritAttrs: true

 inheritAttrs: false  不想继承所有父组件的内容,同时也不在组件根元素dom上显示属性

$listeners的使用

包含了父作用域中的(不包含.native修饰器的)v-on事件监听器。它可以通过v-on="$listeners"传入内部组件–在创建更高层次的组件时非常有用。

通俗地来说就是可以从孙子组件发送事件到父子组件中。

//Father.vue
<template><div class="father"><span>父亲</span><Son @event="event"></Son></div>
</template><script>
import Son from "../components/Son.vue";
export default {components: {Son,},methods: {event() {console.log("从GrandSon组件发送过来的数据");},},
};
</script><style>
</style>//Son.vue
<template><div class="son"><span>儿子</span><GrandSon v-on="$listeners"></GrandSon></div>
</template><script>
import GrandSon from "../components/GrandSon.vue";
export default {components: {GrandSon,},
};
</script><style>
</style>//GrandSon.vue
<template><div class="grandson"><span>孙子</span><button @click="click">发送事件</button></div>
</template><script>
export default {methods: {click() {this.$emit("event");},},
};
</script><style>
</style>

普通的emit只能从子组件传到父组件,通过$listeners,我们可以实现从孙子组件把事件传到父子组件,不需要通过emit逐层传递。

$attrs和$listeners主要用来父孙组件之间传值,有的同学说也可以用provide和inject来实现父孙组件之间传值,但需要注意的是provide和inject只能从父组件向孙组件传值,不能从孙组件向父组件传值,这种情况就需要使用$attrs和$listeners来实现了。

中央事件总线 

上面两种方式处理的都是清楚父子组件之间的关系情况下传输数据,而如果不清楚两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。

 使用方法:可以声明一个全局变量来使用事件中心,但如果在使用 webpack 之类的模块系统,这显然不合适。
每次使用都手动 import 进来也很不方便,所以本文使用 vue-bus 插件。

vue-bus npm地址

vue-bus github地址

安装及引入

npm install vue-bus --save

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装 vue-bus:

// main.js
import Vue from 'vue';
import VueBus from 'vue-bus';
Vue.use(VueBus);

在组件中使用

假设有两个Vue组件需要通信 ,在 A 组件的按钮上面绑定了点击事件发送一则消息,想通知 B 组件。

// A 组件
<template><div class="wrap"><button @click="sendMsg">触发</button></div>
</template><script>
export default {data(){return {Amsg:'我是来自A组件的信息',}},methods:{sendMsg(){this.$bus.emit('changeMsg', this.Amsg );this.$bus.emit('doOnce','我只会触发一次');}},
}
</script>
// B 组件
<template><div><h3>{{Bmsg}}</h3></div>
</template><script>
export default {data(){return {Bmsg:'我是B组件',}},methods:{getMsg(msg){this.Bmsg = msg;console.log(msg);}},created(){/** 接收事件* 这种写法也体现了:A 组件调用 B 组件中的方法。如果只是传递数据,可参考如下简化写法:* this.$bus.on('changeMsg', (msg) => { this.Bmsg = msg });*/ this.$bus.on('changeMsg', this.getMsg);// 此侦听器只会触发一次this.$bus.once('doOnce', (txt) => { console.log(txt) });},// 组件销毁时,移除EventBus事件监听beforeDestroy() {this.$bus.off('changeMsg', this.getMsg);},
}
</script>

小总结

eventBus 适合小项目、数据被更少组件使用的项目,对于中大型项目数据在很多组件之间使用的情况 eventBus 就不太适用了。eventBus 其实就是一个发布订阅模式,利用 Vue 的自定义事件机制,在触发的地方通过 $emit 向外发布一个事件,在需要监听的页面,通过 $on 监听事件。

provide和inject 

简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。

需要注意的是这里不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据。

概念解析

成对出现:provide和inject是成对出现的

作用:用于父组件向子孙组件传递数据

使用方法:provide在父组件中返回要传给下级的数据,inject在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据。

使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject可以轻松实现跨级访问父组件的数据

代码解释

写法一

//父组件
provide: {user: 'John Doe'}--------------------
//子组件
inject: ['user']
//使用
console.log(this.user)


缺点:如果我们尝试在此处提供一些组件实例 property,则这将不起作用,

 provide: {todoLength: this.todos.length // 将会导致错误 'Cannot read property 'length' of undefined`},


写法二

 provide() {return {todoLength: this.todos.length}},


缺点:数据不会响应变化

写法三(推荐)

在 setup() 中使用 provide 时,我们首先从 vue 显式导入 provide 方法。这使我们能够调用 provide 时来定义每个 property。

provide 函数允许你通过两个参数定义 property:

property 的 name ( 类型)
property 的 value

//父组件
import { provide } from 'vue'
export default {setup() {provide('location', 'North Pole')//location 键(标识符)-- North Pole //值 provide('geolocation', {longitude: 90,latitude: 135})}
}
// 子组件

v-model

简述

父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(‘input',val)自动修改v-model绑定的值

代码 

Vue.component('child',{props:{value:String, //v-model会自动传递一个字段为value的prop属性    },data(){      return {mymessage:this.value}},methods:{changeValue(){        this.$emit('input',this.mymessage);//通过如此调用可以改变父组件上v-model绑定的值      }},template:`      <p><input type="text" v-model="mymessage" @change="changeValue"></p>  })Vue.component('parent',{template:`      <p><p>this is parent compoent!</p><p>{{message}}</p><child v-model="message"></child></p>    `,data(){      return {message:'hello'}}})  var app=new Vue({el:'#app',template:`      <p><parent></parent></p>    `})

$parent和$children

简述

在组件内部可以直接通过子组件$parent对父组件进行操作,父组件通过$children对子组件进行操作.

代码 

Vue.component('child',{props:{value:String, //v-model会自动传递一个字段为value的prop属性    },data(){      return {mymessage:this.value}},methods:{changeValue(){        this.$parent.message = this.mymessage;//通过如此调用可以改变父组件的值      }},template:`      <p><input type="text" v-model="mymessage" @change="changeValue"></p>  })Vue.component('parent',{template:`      <p><p>this is parent compoent!</p><button @click="changeChildValue">test</button ><child></child></p>    `,methods:{changeChildValue(){        this.$children[0].mymessage = 'hello';}},data(){      return {message:'hello'}}})  var app=new Vue({el:'#app',template:`      <p><parent></parent></p>    `})

 vuex处理组件之间的数据交互

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

localStorage / sessionStorage 

这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。

通过window.localStorage.getItem(key) 获取数据

通过window.localStorage.setItem(key,value) 存储数据

注意用JSON.parse() / JSON.stringify() 做数据格式转换

localStorage / sessionStorage可以结合vuex,实现数据的持久保存,同时使用vuex解决数据和状态混乱问题。

 大总结

传值方法特点及使用场景
props/$emit确定父子关系的父子组件
$attrs/$listeners确定关系的多层组件之间
中央事件总线不确定关系的组件,但是适合小项目,因为这个是借助于事件
provide/inject通过provide/inject可以轻松实现跨级访问父组件的数据,比较消耗性能
v-model父传子使用,但是有了props为什么我要用这个呢,所以用处不大
$parents/$children在组件内部可以直接通过子组件$parent对父组件进行操作,父组件通过$children对子组件进行操作.
vuex处理公共数据,更组件无关系,专门的数据状态管理。
浏览器缓存为了长时间留存数据使用的,用的也比较多。
$ref/$refs获取实Dom上的数据,从上至下

smallSkill:我们传值时候为了不影响的父值的变化,我们可以用变量接收的方法去解决这个问题(这个面试常常问到)

结束语:

本文就到此结束了,希望大家共同努力,早日拿下 Vue💪💪。

如果文中有不对的地方,或是大家有不同的见解,欢迎指出 🙏🙏。

如果大家觉得所有收获,欢迎一键三连💕💕。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin

Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片&#xff0c;Kotlin <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.RE…

合宙Air724UG LuatOS-Air LVGL API控件--图表 (Chart)

图表 (Chart) 一幅图胜过一千个字&#xff0c;通过图表展示出的数据内容能让用户更快速有效的了解数据特征。 代码示例 – 创建图表 chart lvgl.chart_create(lvgl.scr_act(), nil) lvgl.obj_set_size(chart, 200, 150) lvgl.obj_align(chart, nil, lvgl.ALIGN_CENTER, 0, …

docker 笔记1

目录 1.为什么有docker ? 2.Docker 的核心概念 3.容器与虚拟机比较 3.1传统的虚拟化技术 3.2容器技术 3.3Docker容器的有什么作用&#xff1f; 3.4应用案例 4. docker 安装下载 4.1CentOS Docker 安装 4.2 Docker的基本组成 &#xff1f;&#xff08;面试&#xff09…

OpenShift 4 - 用 Prometheus 和 Grafana 监视用户应用定制的观测指标(视频)

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.13 的环境中验证 文章目录 OpenShift 的监控功能构成部署被监控应用用 OpenShift 内置功能监控应用用 Grafana 监控应用安装 Grafana 运行环境配置 Grafana 数据源定制监控 Dashboard 演示视…

剑指 Offer 57 - II. 和为s的连续正数序列(简单)

题目&#xff1a; class Solution { public:vector<vector<int>> findContinuousSequence(int target) { //本题使用滑动窗口&#xff08;双指针&#xff09;int i1, j1; //定义左右边界&#xff0c;一般是左闭右开int sum0; //窗口内的和vector&…

弹性盒子的使用

一、定义 弹性盒子是一种用于按照布局元素的一维布局方法&#xff0c;它可以简便、完整、响应式地实现各种页面布局。 容器中存在两条轴&#xff0c;主轴和交叉轴(相当于我们坐标轴的x轴和y轴)。我们可以通过flex-direction来决定主轴的方向。 主轴&#xff08;main axis&am…

设计模式行为模式-命令模式

文章目录 前言定义结构工作原理优点适用场景消息队列模式Demo实现分写业务总结 前言 定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;用于将请求封装为对象&#xff0c;从而使你可以使用不同的请求、队列或者日志请求来参数化其他对象…

MySQL高阶语句(三)

一、NULL值 在 SQL 语句使用过程中&#xff0c;经常会碰到 NULL 这几个字符。通常使用 NULL 来表示缺失 的值&#xff0c;也就是在表中该字段是没有值的。如果在创建表时&#xff0c;限制某些字段不为空&#xff0c;则可以使用 NOT NULL 关键字&#xff0c;不使用则默认可以为空…

zookeeper 集群

zookeeper 集群 1、zookeeper 集群说明 initLimit 是Zookeeper用它来限定集群中的Zookeeper服务器连接到Leader的时限 syncLimit 限制了follower服务器与leader服务器之间请求和应答之间的时限 服务器名称与地址&#xff1a;集群信息&#xff08;服务器编号&#xff0c;服务器…

kubesphere安装Maven+JDK17 流水线打包

kubesphere 3.4.0版本&#xff0c;默认支持的jav版本是8和11&#xff0c;不支持17 。需要我们自己定义JenKins Agent 。方法如下&#xff1a; 一、构建镜像 1、我们需要从Jenkins Agent的github仓库拉取master最新源码&#xff0c;最新源码里已经支持jdk17了。 git clone ht…

代码随想录算法训练营第39天 | ● 62.不同路径 ● 63. 不同路径II

文章目录 前言一、62.不同路径二、63.不同路径II总结 前言 动态规划 一、62.不同路径 深搜动态规划数论 深搜&#xff1a; 注意题目中说机器人每次只能向下或者向右移动一步&#xff0c;那么其实机器人走过的路径可以抽象为一棵二叉树&#xff0c;而叶子节点就是终点&#…

JS算法与树(二)

前言 二叉搜索树&#xff08;BST&#xff09;存在一个问题&#xff1a;当你添加的节点数够多的时候&#xff0c;树的一边可能会非常的深。而其他的分支却只有几层。 AVL树 为了解决上面的问题&#xff0c;我们提出一种自平衡二叉搜索树。意思是任何一个节点左右两侧子树的高度之…

多级缓存 架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;多次遇到一个很重要的面试题&#xff1a; 20w的QPS的场景下&#xff0c;服务端架构应如何设计&#xff1f;10w的QPS…

python爬虫-Selenium

一、Selenium简介 Selenium是一个用于Web应用程序测试的工具&#xff0c;Selenium 测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。模拟浏览器功能&#xff0c;自动执行网页中的js代码&#xff0c;实现动态加载。 二、环境配置 1、查看本机电脑谷歌浏览器的版…

Qt之进程通信-IPC(QLocalServer,QLocalSocket 含源码+注释)

文章目录 一、IPC通信示例图1.1 设置关键字并连接的示例图1.2 进程间简单的数据通信示例图1.3 断开连接的示例图1.3.1 由Server主动断开连接1.3.2 由Socket主动断开连接 1.4 Server停止监听后的效果二、个人理解与一些心得三、一些疑问&#xff08;求教 家人们&#x1f602;&am…

【ES6】JavaScript的Proxy:理解并实现高级代理功能

在JavaScript中&#xff0c;Proxy是一种能够拦截对对象的读取、设置等操作的机制。它们提供了一种方式&#xff0c;可以在执行基本操作之前或之后&#xff0c;对这些操作进行自定义处理。这种功能在许多高级编程场景中非常有用&#xff0c;比如实现数据验证、日志记录、权限控制…

【网络教程】群晖如何正确的安装openwrt旁路由

文章目录 准备安装导入镜像创建虚拟机访问旁路由旁路由网络设置准备 我这里的环境是群晖DSM7.2版本首先大家需要预先安装套件Virtual Machine Manager,这里就省略了 根据个人需求去下载openwrt的固件,下载的时候选择x86的img镜像文件,这里也可以直接使用我使用的这个固件(资…

RISC-V 中国峰会 | OpenMPL引人注目,RISC-V Summit China 2023圆满落幕

RISC-V中国峰会圆满落幕 2023年8月25日&#xff0c;为期三天的RISC-V中国峰会&#xff08;RISC-V Summit China 2023&#xff09;圆满落幕。本届峰会以“RISC-V生态共建”为主题&#xff0c;结合当下全球新形势&#xff0c;把握全球新时机&#xff0c;呈现RISC-V全球新观点、新…

8.27周报

文章目录 前言论文阅读摘要介绍模型算法 总结 前言 本周学习了GAN论文《Generative Adversarial Nets》&#xff0c;了解GAN主要由两部分组成&#xff1a;生成器和判别器&#xff0c;知道生成器G和判别器D的作用及原理&#xff0c;相比于其他的生成模型&#xff0c;了解GAN的优…

Postman的高级用法—Runner的使用​

1.首先在postman新建要批量运行的接口文件夹&#xff0c;新建一个接口&#xff0c;并设置好全局变量。 2.然后在Test里面设置好要断言的方法 如&#xff1a; tests["Status code is 200"] responseCode.code 200; tests["Response time is less than 10000…