vue 的组件之间传值(父子组件,兄弟组件,祖孙组件,任意组件)

本文主要是介绍vue 的组件之间传值(父子组件,兄弟组件,祖孙组件,任意组件),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. props / $emit

  • props 父组件传值给子组件
  • $emit 子组件传值给父组件

props:

// 父组件
<template><div><Child v-bind:list="users"></Child></div> 
</template>
<script>import Child from "./components/Child" //子组件export default {name: 'App',components:{Child},data(){return{users:["Eric","Andy","Sai"]             }}}   }
</script>// 子组件
<template><ul><li v-for="item in list">{{ item }}</li></ul>
</template>
<script>export default {name: 'child',props:{list:{           //这个就是父组件中子标签自定义名字type:Array,     //对传递过来的值进行校验required:true   //必添}}}
</script>

$emit:

// 子组件
<template><div><h1 @click="changeTitle">{{ title }}</h1> //绑定一个点击事件</div>
</template>
<script>export default {name: 'header',data() {return {title:"子组件title"}},methods:{changeTitle() {this.$emit("titleChanged", "子向父组件传值")}}}
</script>// 父组件
<template><div><header v-on:titleChanged="updateTitle"></header><h2>{{ title }}</h2></div>
</template>
<script>
import Header from "./components/Header"export default {name: 'App',components:{ Header },data(){return{title:"传递的是一个值"}},methods:{updateTitle(e){   //声明这个函数this.title = e;}}}
</script>

2. $attrs / $listeners

  • $attrs:包含了父作用域中不被 Prop 所识别的特性绑定(class 和 style 除外),当一个组件没有申明任何 prop 时,这里会包含所有父作用域的绑定(class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件
  • $listeners:包含了父作用域中的 v-on 事件监听器(不包含 .native 修饰器的),可以通过 v-on="$listeners" 传入内部组件

$attrs与$listeners 是两个对象,$attrs 里存放的是父组件中绑定的非 Props 属性, $listeners里存放的是父组件中绑定的非原生事件。

// childCom1
<template><div class="border"><h2>childCom1</h2><child-com2 title="前端工匠" :aoo="aoo" :boo="boo" :coo="coo":style="{background: '#f2f2f2'}" class="box"@msgChanged="updateMsg"></child-com2><p>{{msg}}</p></div>
</template><script>
import ChildCom2 from '@/views/childCom2.vue'
export default {name: 'childCom1',components: { ChildCom2 },data () {return {aoo: 'Html',boo: 'CSS',coo: 'Javascript',msg: ''}},methods: {updateMsg (msg) {this.msg = msg}}
}
</script>
// childCom2
<template><div class="border"><h2>childCom2</h2><p>childCom2的$attrs: {{ $attrs }}</p><child-com3 v-bind="$attrs" v-on="$listeners"></child-com3></div>
</template>
<script>
const childCom3 = () => import('./childCom3.vue')
export default {name: 'childCom2',components: {childCom3},inheritAttrs: false,props: {aoo: String}
}
</script>

注意: 这里是 v-bind= 和 v-on=。 这里v-on是等号。

// childCom3
<template><div class="border"><h2>childCom3</h2><p @click="changeMsg">childCom3的$attrs: {{ $attrs }}</p></div>
</template>
<script>
export default {name: 'childCom3',inheritAttrs: true,props: {coo: String,title: String},methods: {changeMsg () {this.$emit('msgChanged', '我是childCom3的数据')}}
}
</script>

childCom2 中,$attrs 里没有 style 和 class 的内容。因为 props 中申明了 aoo ,所以也没有 aoo 。

关于 inheriAttrs 的作用

childCom2 中 inheriAttrs:false,childCom3 中 inheriAttrs:true。渲染 DOM 如下:

可以看到为 true 时,childCom3 组件中的根节点上绑定了 $attrs 的属性

3. provide / inject

  • provide 在祖先中提供变量
  • inject 在后代中注入变量

provide / inject 只能用于父传子,反向不能传递。

// grandpa.vue
export default {name: 'grandpa',// provide: {//   name: '前端工匠'// },provide () {return {name: '前端工匠',num: this.count}},data () {return {count: 3}}
}// grandson.vue
export default {name: 'grandson',inject: ['name', 'num'],created () {console.log(this.name)console.log(this.num)}
}

此时传递的数据,不是响应式的。grandpa 中修改 count 的值,grandson 中的 num 并不会改变。

实现响应式的两种方法:

  • provide祖先组件的实例,然后在子孙组件中注入依赖,这样就可以在子孙组件中直接获取或者修改祖先组件的实例的属性,不过这种方法有个缺点就是这个实例上挂载很多没有必要的东西比如props, methods。
  • Vue.observable 优化响应式 provide

第一种方法示例如下:

// grandpa.vue
export default {name: 'grandpa',// provide () {//   return {//     name: '前端工匠',//     num: this.count//   }// },provide () {return {grandpaInfo: this}},data () {return {name: '前端工匠',count: 3}},methods: {changeNum () {this.count++}}
}
// grandson.vue
export default {name: 'grandson',// inject: ['name', 'num'],inject: ['grandpaInfo'],created () {// console.log(this.name)// console.log(this.num)console.log(this.grandpaInfo.name)console.log(this.grandpaInfo.count)}
}

此时 grandpa 中的count 改变,grandson 中的 count 也会跟着变化

inject 也可以对祖先传过来的实例重新命名:

export default {name: 'grandson',// inject: ['grandpaInfo'],inject: {grandpaInfoObj: {from: 'grandpaInfo',default () {return {}}}},created () {// console.log(this.grandpaInfo.name)// console.log(this.grandpaInfo.count)console.log(this.grandpaInfoObj.name)console.log(this.grandpaInfoObj.count)}
}

第二种方法示例如下:

// grandpa.vue
import Vue from 'vue'
export default {name: 'grandpa',provide () {this.grandpaInfo = Vue.observable({name: '前端工匠',count: 3})return {grandpaInfo: this.grandpaInfo}}
}
// grandson.vue
export default {name: 'grandson',inject: ['grandpaInfo'],created () {console.log(this.grandpaInfo.name)console.log(this.grandpaInfo.count)}
}

此时 grandpa 中修改 this.grandpaInfo 中的值,grandson 中的值跟着改变。

4. $parent / $children

  • $parent 访问父实例
  • $children 访问子实例

// parent.vue
<script>
import Child from './child.vue'
export default {name: 'parent',components: { Child },data () {return {title: '我是父组件',childTitle: ''}},methods: {sayHello () {console.log('hello')},getChild () {this.childTitle = this.$children[0].titlethis.$children[0].sayBye()}}
}
</script>
// child.vue
<script>
export default {name: 'child',data () {return {title: '我是子组件',parentTitle: ''}},methods: {sayBye () {console.log('bye')},getParent () {this.parentTitle = this.$parent.titlethis.$parent.sayHello()}}
}
</script>

使用 $parent 和 $children 时,需要注意以下几点:

  • 使用 $parent 时,注意一些UI框架的组件嵌套。比如页面中如果 child 组件的外层有 el-row 包裹,那 child 的$parent 是 el-row 实例,需继续向上查找,才是 parent 组件实例。
  • 使用 $children 时,注意 children 的下标,是页面最终呈现时的下标。比如,如果 child 组件上有一个动态组件,只有某种情况下才显示,平时不显示。那么当动态组件显示时,child 的下标就会发生变化。

5.事件总线 eventbus ,$emit / $on

创建 bus 文件(新建js文件)

import Vue from 'vue'
export defult new Vue

使用:使用 bus 的组件,必须引入 bus 文件

// 组件 aa ,发送数据
<template><div><h3>aa组件</h3><button @click="sendMsg">将数据发送给bb组件</button></div>
</template>
<script>
import bus from './bus'
export default {methods: {sendMsg(){bus.$emit('sendTitle','传递的值')}     }
}
</script>
// 组件 bb,接收数据
<template><div>接收aa传递过来的值:{{msg}}</div>
</template>
<script>
import bus from './bus'
export default {data(){return {mag: ''}}mounted(){bus.$on('sendTitle',(val)=>{this.mag = val})}
}
</script>

6. $root

$root 获取当前 vue 组件的根组件实例。

当兄弟组件之间传值,或者是跨层级传值时,可以将数据挂载到根实例上,然后其他组件从根实例上获取。

// child1.vue
methods: {setData () {this.$root.myData = '使用$root传递数据'}
}// child2.vue
methods: {getData () {console.log(this.$root.myData)}
}

7. ref

如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。

给子组件添加 ref ,在父组件中可以通过 this.$refs.['设置的名称'] 访问子组件实例。

// parent.vue
<template><div class="border"><h2>parent</h2><child2 ref="child2"></child2><div @click="getChild">获取子节点数据</div></div>
</template><script>
import Child2 from './child2.vue'
export default {name: 'parent',components: { Child2 },methods: {getChild () {console.log(this.$refs.child2.type)}}
}
</script>

// child2.vue
<script>
export default {name: 'child2',data () {return {type: 'css'}}
}
</script>

需要注意的是,如果组件有循环,那 this.$refs.child2 获取到的是 Array:

<child2 ref="child2"v-for="(item, index) in list":key="index"></child2>export default {name: 'parent',data () {return {list: ['a', 'b', 'c']}}
}

此时 this.$refs.child2 的值为

8. vuex

组件间传值,也可以使用 vuex。利用 vuex 实现数据共享。

这篇关于vue 的组件之间传值(父子组件,兄弟组件,祖孙组件,任意组件)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/598334

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

day-51 合并零之间的节点

思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧