目录
- 本章涵盖知识点
- 回顾
- 组件开发与复用
- 组件的创建和注册
- 全局定义
- 局部定义
- 单文件组件(.vue 文件)
- 组件的注册方式
- 在实例中注册
- 在 Vue 中注册
- 组件的 props
- 定义 props
- 传递 props
- 组件事件
- 自定义事件的创建和触发
- 父组件监听子组件事件
- 父组件处理事件
- Vue 实现逻辑复用的两种方式
- 插件 (Plugins)
- 混入 (Mixins)
- 内容分发--插槽(Slots)
- 默认插槽
- 具名插槽
- 作用域插槽
- 使用插槽
- 作用域插槽的使用
- 组件通信方式
- 1. 父子组件通信
- Props 和 Events
- 实例演示
- 2.Event Bus (非官方,但常用)
- 3.`$attrs` 和 `$listeners` (v-bind 与 v-on)
- 4.provide/inject (2.2.0+)
- 实例演示
- 5. 状态管理库(Vuex)
- 实例演示
- 6.ref
- 7. `$parent` / `$children`
- 常见使用场景可以分为三类:
- 结语
本章涵盖知识点
- 组件的基本概念和作用
- 组件的创建和注册
- 组件的 props、事件和自定义事件
- 三类插槽(slot)的使用
- 组件间常见的
7种
通信方式
回顾
在前两篇文章中,我们分别介绍了 Vue.js 的基础知识,包括 Vue 实例、模板语法、数据绑定、事件处理等。本文将主要学习组件化,组件化是 Vue.js 的核心概念之一,它允许开发者将界面拆分成独立、可复用的组件,使得开发大型应用变得更加简单和高效。
正文开始
,如果觉得文章对您有帮助,请帮我三连+订阅,谢谢
💖💖💖
组件开发与复用
组件的创建和注册
Vue 组件是可复用的 Vue 实例,拥有自己的模板、数据和方法。
全局定义
// 全局注册组件
Vue.component('my-component', {
template: '<div>我是全局组件!</div>',
})
局部定义
// 在特定实例中局部注册组件
new Vue({
components: {
'my-component': {
template: '<div>我是局部组件!</div>',
},
},
})
单文件组件(.vue 文件)
<template>
<div>A single file component!</div>
</template>
<script>
export default {
// component definition
}
</script>
组件的注册方式
在实例中注册
new Vue({
components: {
'my-component': MyComponentDefinition,
},
})
在 Vue 中注册
// 全局注册后可以在任何实例中使用
Vue.component('my-component', MyComponentDefinition)
组件的 props
Props 是父组件向子组件传递数据的一种方式。
定义 props
// 在 JavaScript 中是 camelCase 的
props: ['id', 'name', 'isCompleted']
传递 props
<todo-item id="1" name="Learn Vue" :is-completed="false"></todo-item>
组件事件
组件可以向父组件触发自定义事件。
自定义事件的创建和触发
methods: {
notifyParent: function () {
this.$emit('custom-event', 'Hello from child!');
}
}
父组件监听子组件事件
<child-component @custom-event="handleCustomEvent"></child-component>
父组件处理事件
methods: {
handleCustomEvent: function (message) {
console.log(message);
}
}
Vue 实现逻辑复用的两种方式
插件 (Plugins)
可以全局或局部地添加功能。
// 插件
Vue.use({
install(Vue) {
Vue.prototype.$myGlobalMethod = function () {
// ...
}
},
})
混入 (Mixins)
可以包含可复用的组件逻辑。
// myMixin.js
// 混入
export default {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
},
},
}
// 定义一个使用混入对象的组件
var Component = Vue.extend({
mixins: [myMixin],
})
内容分发–插槽(Slots)
插槽是 Vue 组件用于内容分发的机制。
默认插槽
<!-- 子组件 -->
<template>
<div>
<slot>默认插槽内容</slot>
</div>
</template>
具名插槽
<!-- 子组件 -->
<template>
<div>
<slot name="header">Default header</slot>
<slot name="footer">Default footer</slot>
</div>
</template>
作用域插槽
<!-- 子组件 -->
<template>
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item">text</slot>
</li>
</ul>
</template>
使用插槽
<child-component>
<template v-slot:header>Header content</template>
<template v-slot:footer>Footer content</template>
Default content
</child-component>
作用域插槽的使用
<child-component>
<template v-slot="slotProps">
<div>{{ slotProps.item.defaultText }}</div>
</template>
</child-component>
组件通信方式
1. 父子组件通信
Props 和 Events
- Props:父组件可以通过
props
向子组件传递数据。 - Events:子组件可以使用
$emit
向父组件发送事件。
实例演示
<!-- 子组件 -->
<template>
<button @click="increment">Increment</button>
</template>
<script>
export default {
props: ['initialCount'],
methods: {
increment() {
this.$emit('increment', this.initialCount + 1)
},
},
}
</script>
<!-- 父组件 -->
<template>
<child-component :initial-count="count" @increment="count++"></child-component>
</template>
2.Event Bus (非官方,但常用)
通过一个事件总线(通常是一个 Vue 实例)来通信。
// 创建一个中央事件总线
const EventBus = new Vue()
// 在组件中
EventBus.$emit('custom-event', 'some data')
EventBus.$on('custom-event', data => {
// 处理事件
})
3.$attrs
和 $listeners
(v-bind 与 v-on)
$attrs
:包含父作用域中不作为 prop 被识别(且获取)的属性绑定(class
和style
除外)。$listeners
(在 Vue 2.x 中):包含了父作用域中的(不含.native
修饰器的)v-on 事件监听器。它可以通过v-on="$listeners"
传入内部组件。
4.provide/inject (2.2.0+)
- provide:祖父组件可以使用
provide
来提供数据。 - inject:后代组件可以使用
inject
来注入数据。
实例演示
// 祖父组件
provide() {
return {
someData: this.someData
};
}
// 后代组件
inject: ['someData'],
5. 状态管理库(Vuex)
Vue 探索之旅:第六站 — Vue 的状态管理
对于复杂应用,可以使用 Vuex 来集中管理状态。
实例演示
// Vuex store
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
})
// 组件中
this.$store.commit('increment')
6.ref
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
// 父组件
<template>
<component-a ref="comA"></component-a>
</template>
<script>
export default {
mounted () {
const comA = this.$refs.comA;
console.log(comA.title); // Vue.js
}
}
</script>
// component-a 子组件
export default {
data() {
return {
title: 'Vue.js',
}
},
}
7. $parent
/ $children
使用
$parent
和$children
可能会导致组件之间的耦合度增加,这可能会使组件更难以重用和测试。因此,通常推荐使用 props 和 events 来实现父子组件之间的通信。
<template>
<div>
<h1>这是父组件</h1>
<child-component1></child-component1>
<child-component2></child-component2>
<button @click="callChildMethod">调用子组件方法</button>
</div>
</template>
<script>
import ChildComponent1 from './ChildComponent1.vue'
import ChildComponent2 from './ChildComponent2.vue'
export default {
components: {
ChildComponent1,
ChildComponent2,
},
methods: {
callChildMethod() {
// 遍历所有子组件并调用它们的方法
this.$children.forEach(child => {
if (child.someMethod) {
child.someMethod()
}
})
},
},
}
</script>
<!-- ChildComponent1.vue -->
<template>
<div>
<h2>我是子组件1</h2>
<p>父组件的标题是: "{{ parentTitle }}"</p>
</div>
</template>
<script>
export default {
name: 'ChildComponent1',
mounted() {
// 访问父组件的属性
this.parentTitle = this.$parent.someProperty || '父组件标题'
},
data() {
return {
parentTitle: '',
}
},
methods: {
someMethod() {
alert('子组件1的方法被调用了!')
},
},
}
</script>
常见使用场景可以分为三类:
-
父子通信:
- 父向子传递数据是通过 props,子向父是通过 events($emit)
- 通过父链 / 子链也可以通信($parent / $children)
- ref 也可以访问组件实例
- provide / inject API
- a t t r s / attrs/ attrs/listeners
-
兄弟通信:
- Bus
- Vuex
-
跨级通信:
- Bus
- Vuex
- provide / inject API
- a t t r s / attrs/ attrs/listeners
结语
通过本文,我们详细了解了 Vue 组件化开发的各个方面,包括组件的多种创建和注册方式、props 的定义和传递、自定义事件的创建和触发、以及插槽的多种类型和用法。这些知识将帮助我们构建更加模块化和可复用的 Vue 应用。