vue组件间传值的8种方式

您所在的位置:网站首页 vue组件如何传值 vue组件间传值的8种方式

vue组件间传值的8种方式

2023-04-22 07:32| 来源: 网络整理| 查看: 265

组件间传值问题

一、A→B→C祖孙传值类型

A→B→C传值方式是工作中最常见的传值方式,依次是组件的包含顺序。

1、props/$emit

当然,我们可以利用两次props接收参数,直到参数从A传到C,这种方式不再赘述。

2、vuex

还有通过vuex,不过有点大材小用,引起state维护的参数过多等,这种方式也不赘述了。

3、provide、inject传值

provice/inject传值的方式,适合所有的向下传值类型,层级可以很深,多用于组件开发。业务开发中很少用到。

A组件 // provide作为一个属性使用,和data,methods等统级,将要传递给子孙的属性放在里面 provide() { return { toSon: 'this is to my son' } }, 复制代码

B、C等子孙组件 // inject是一个对象 inject: { toSon: { default: '' // 设置接收属性的默认值 } }, // inject也可以是一个数组 inject:['toSon'] 复制代码

4、attr、attr、attr、listeners传值

*这两个属性都是绑在组件B上面的,组件B起到一个承上启下的作用。attr用于将A组件传递过来的属性,下传给C组件attr用于将A组件传递过来的属性,下传给C组件attr用于将A组件传递过来的属性,下传给C组件listeners用于将C组件发射的数据,上传给A组件inheritAttrs用于设置属性,当设置为false时候,dom上则不会出现属性。

尚不明确的点inheritAttrs

A组件 methods: { listenComponentC(data) { } } 复制代码

B组件 inheritAttrs: false 复制代码

C组件 inheritAttrs: false, async created() { console.log(this.$attrs) 输出可以发现$attrs对象是A组件传递过来的属性 }, methods: { propToComponentA() { const data = { name: '古天乐' } // b组件,c组件都可以监听事件propToComponentA this.$emit('propToComponentA',data) } }, 复制代码

这种方式比vuex轻量,而且很方便。

5、children、children、children、parent

有时候也有人用这种方式进行组件传值,我几乎不用。欧尔父组件调用子组件事件时候,为了少些代码,直接一个this.refs.childrenName.childrenField完事。childrenName是ref指向的子组件名称childrenField是子组件中的事件或者参数闲话少说,还是来说说refs.childrenName.childrenField 完事。childrenName 是ref指向的子组件名称childrenField 是子组件中的事件或者参数闲话少说,还是来说说refs.childrenName.childrenField完事。childrenName是ref指向的子组件名称childrenField是子组件中的事件或者参数闲话少说,还是来说说children、$parent

$children

在父组件中,通过children可以获得所有无序的子组件组成的数组。注意,当你想用children可以获得所有无序的子组件组成的数组。注意,当你想用children可以获得所有无序的子组件组成的数组。注意,当你想用children调用儿子组件中的方法或者参数时候,一定是需要等挂在完毕,在mounted中调用,或者是$nextTick

$parent

子组件可以通过this.$parent获取父组件实例。同样的,打点调用父组件的方法。

6、中央事件总线 emit/emit/emit/on

这个其实是一种思路,eventBus就是创建一个全局的eventBus,然后将你需要的变量、事件等都挂载在上面。需要的时候去获取。现在vue开发很少有人用这种方法了,有了vuex,谁还会去用呢。下面简单介绍一下。

创建全局响应式变量

一般在main.js中定义一个全局变量,挂在到window下

import Vue from 'vue' window.eventBus = new Vue() // 也可以挂载到vue原型链上,二选其一 Vue.prototype.$eventBus = new Vue(); 复制代码

从这里可以看出eventBus就是一个vue实例,但是是个很奇怪的实例,因为没有router,没有挂载app等,当然,这个实例肯定是响应式,这就是它的作用。接下来,要做的就是将开发中的兄弟组件之间需要传递的变量挂载到上面。

事件挂载到eventBus

C组件

// c组件发射了一名为dataFrom的事件,并挂载了数据this.dataA this.$eventBus.$emit('dataFrom', this.dataA); 复制代码

接收eventBus的事件

因为$eventBus是全局,且响应式的,任何一个组件都可以进行接收

this.$eventBus.$on('dataFrom', function (data) { // handle data code }); 复制代码

如果想接收一次事件后移除,就用$once

this.$eventBus.$once('dataFrom', function (data) { // handle data code }); 复制代码

7、组件v-modle传值,子传父B→A

有一种开发中的特殊情况,大家在封装属于自己的表单组件或者对element-ui的表单进行二次封装是时候一定遇到过。

举个栗子:

功能要求:我们要对el-input进行二次封装,功能为只能输入数字,,小数点最多保留两位。当尝试输入其他格式,或者尝试三位小数点时候给出 el-form-item__error 的提示。

解决思路:封装一个组件,正则校验只能输入数字。这里涉及到一个问题,如何给父组件传值,组件报错,同时,父组件如何给子组件绑定v-model ?

代码地址:github.com/taoorange/l…

我们的做法如下:

子组件

在子组件的props定义变量value,用来接收父组件绑定的v-model在子组件中,通过  this.$emit('input', val)将子组件处理好的父组件传递过来的数据,再回传绑定给父组件在子组件绑定的v-modle属性上。这其实是一个同时改变子父组件的逻辑。

子组件代码:

{{ slotName }} {{ errorMessage }} // 对做二次封装,主要用来处理数字输入的小数点保留问题 export default { name: 'NumberInput', props: { slotType: { type: String, default: 'append', }, slotName: { type: String, default: null, }, value: { type: [Number, String], default: null, }, size: { type: String, default: 'small', }, disabled: { type: Boolean, default: false, }, readonly: { type: Boolean, default: false, }, placeholder: { type: String, defalut: '请输入', }, remain: { type: [Number, String], default: 2, // 默认保留2位小数 }, // 限制是否只能输入为正整数 integerOnly: { type: Boolean, defalut: false, }, min: { type: Number, default: -999999999999, }, max: { type: Number, default: 99999999999999, }, // 限制是否只能为正数 positive: { type: Boolean, defalut: false, }, }, data() { return { errorMessage: '', } }, methods: { changeInput(value) { let val if (!this.integerOnly) { // 限制输入框只能为数字和小数点,限制可输入数字的位数 // 限制只能为正数 if (this.positive) { val = value.replace(/[^\d.]/g, '') } else { val = value.replace(/[^\d.-]/g, '') // val = value.replace(/[^\-?][\d][\.?][\d]/g, '') } // 校验小数点位数 if (val.toString().indexOf('.') > -1) { const a = val.toString().split('.') if (a[1].length > this.remain) { val = parseFloat(val).toFixed(this.remain) this.errorMessage = `仅支持${this.remain}位小数输入` } else { this.errorMessage = null } } } else { // 限制输入框只能为正整数 val = value.replace(/[^\d]/g, '') } if (val > this.max) { val = this.max } if (val && val < this.min) { val = this.min } this.$emit('input', val) }, }, } /deep/.el-input-group__append { padding: 0 5px; font-size: 13px; } 复制代码

父组件

在父组件中,我们通过v-model给子组件绑定值(子组件通过props中的value接收)。

// 设置了支持保留4位小数 复制代码 8、A→B&A→C模式

有下面一个场景:A组件拥有子组件B、C(或者更多),并且子组件props都接收类似的参数。此时,当B组件需要修改props参数时候,C组件也要跟着修改,有些麻烦,代码看起来比较冗余。那么,有没有什么办法,让B、C接受的参数,一起变化呢。答案是有的。

A组件: import SonComponent from './son-component' import SonComponent2 from './son-component2' export default { name: 'ComponentA', components: { SonComponent, SonComponent2 }, data() { return { modelSon: '父亲' } }, } 复制代码

B组件: export default { name: 'ComponentB', props: { modelSon: { type: String, default: '' } } } 复制代码

我的奇淫巧技是这样的,我们知道,当引入一个组件的时候,是可以获取到组件中的各种信息的,包括props。我们在C组件中,直接引入B组件的props,然后填入C组件的props中。这样,当B组件的props改变时候,C组件就自然修改了。代码如下:

C组件: import BigBrother from './son-component' export default { name: '', props: { ...BigBrother.props }, } 复制代码

其实这种方式算不上组件间通信,只能算是组件间获取参数的一种方式。这种奇淫巧技,工作中一般不常用。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3