Vue 父子组件的访问
父子组件的通信
-
首先,我们指导正常情况下子组件是不能访问父组件或者Vue实例的数据的
-
但是,在开发中,往往一些数据确实需要从上层传递到下层
- 比如在一个页面中,我们从服务器请求到了很多的数据。
- 其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
- 这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)
-
那如何进行父子组件间的通信呢?Vue官方提到
- 通过props向子组件传递数据
- 通过事件向父组件发送消息
-
在下面的代码中,我直接将Vue实例当做父组件,并且其中包含子组件来简化代码。
-
真实的开发中,Vue实例和子组件的通信和父组件和子组件的通信过程是一样的。
props基本用法
-
在组件中,使用选项props来声明需要从父级接收到的数据。
-
props的值有两种方式:
- 方式一:字符串数组,数组中的字符串就是传递时的名称。
- 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
-
我们先来看一个最简单的props传递:
<div id="app">
<child-cpn :message="message"></child-cpn>
</div>
<template id="child-cpn">
<div>显示的信息: {{message}}</div>
</template>
<script>
let app = new Vue({
el: '#app',
data: {
message: 'Hello lazy'
},
components: {
'child-cpn': {
template: '#child-cpn',
props: ['message']
}
}
})
</script>
- 步骤
- Vue实例中的data
- 子组件的props
- 通过:message='message'将data中的数据传给props
- 将props中的数据显示在子组件中
props数据验证
- 在前面,我们的props选项是使用一个数组。
- 我们说过,除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
- 验证都支持哪些数据类型呢?
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
Vue.components('my-components',{
props: {
// 基础的类型检查('null' 匹配任何类型)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function (){
return {message: 'Hello'}
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
- 当我们有自定义构造函数时,验证也支持自定义的类型
function Person (firstName, LastName){
this.firstName = firstName
this.lastName = lastName
}
Vue.component('blog-post', {
props: {
author: Person
}
})
子级向父级传递
-
props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。
-
我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。
-
什么时候需要自定义事件呢?
- 当子组件需要向父组件传递数据时,就要用到自定义事件了。
- 我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。
-
自定义事件的流程:
- 在子组件中,通过$emit()来触发事件。
- 在父组件中,通过v-on来监听子组件事件。
<!--父组件模板-->
<div id="app">
<!-- 监听子组件事件item-click -->
<cpn @item-click="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
<div>
<button v-for="item in categories"
@click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
// 1.子组件
const cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 'aaa', name: '热门推荐'},
{id: 'bbb', name: '手机数码'},
{id: 'ccc', name: '家用家电'},
{id: 'ddd', name: '电脑办公'},
]
}
},
methods: {
btnClick(item) {
// 发射事件: 自定义事件
this.$emit('item-click', item)
}
}
}
// 2.父组件
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
components: {
cpn
},
methods: {
<!-- 定义好一个函数 -->
cpnClick(item) {
console.log('cpnClick', item.id, item.name);
}
}
})
</script>
- 子组件cpn发射自定义事件item-click,携带参数item
- 父组件app在methods中定义一个函数
- 父组件app用v-on监听子组件事件item-click,并将事件指向一个在methods中定义好的函数
父子组件的访问方式: $children
-
有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
- 父组件访问子组件:使用$children或$refs
- 子组件访问父组件:使用$parent
-
$children的缺陷:
- 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
- 但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
- 有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
父子组件的访问方式: $refs
- $refs的使用:
- $refs和ref指令通常是一起使用的。
- 首先,我们通过ref给某一个子组件绑定一个特定的ID。
- 其次,通过this.$refs.ID就可以访问到该组件了。
<child-cpn1 ref="child1"></child-cpn1>
<child-cpn2 ref="child2"></child-cpn2>
<button @click="showRefsCpn"></button>
showRefscpn() {
console.log(this.$refs.child1.message);
console.log(this.$refs.child2.message);
}
父子组件的访问方式: $parent
- 如果我们想在子组件中直接访问父组件,可以通过$parent
- 注意事项:
- 尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。
- 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。
- 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
- 另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护
非父子组件通信
-
刚才我们讨论的都是父子组件间的通信,那如果是非父子关系呢?
- 非父子组件关系包括多个层级的组件,也包括兄弟组件的关系。
-
在Vue1.x的时候,可以通过$dispatch和$broadcast完成
- $dispatch用于向上级派发事件
- $broadcast用于向下级广播事件
- 但是在Vue2.x都被取消了
-
在Vue2.x中,有一种方案是通过中央事件总线,也就是一个中介来完成。
- 但是这种方案和直接使用Vuex的状态管理方案还是逊色很多。
本文来自博客园,作者:懒惰ing,转载请注明原文链接:https://www.cnblogs.com/landuo629/p/12426100.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?