前言
组件(Component)是 Vue.js 最强大的功能之一。
组件可以扩展 HTML 元素,封装可重用的代码。
组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
组件化设计已经成为构建可维护和可扩展应用程序的关键策略之一。而 Vue.js 作为一个流行的前端框架,以其简单易用、灵活和高效的特点,成为开发者的首选。
这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。
组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以是原生 HTML 元素的形式,以 is
特性扩展。
一、Vue.js组件示例
以下是一个简单的Vue.js组件示例,展示了如何创建一个计数器组件:
javascript
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
};
},
methods: {
increment() {
this.count++;
},
decrement() {
this.count--;
},
},
};
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
这个组件包括了三个主要部分:
<template>
:定义了组件的结构,包括显示当前计数count
的<p>
标签和两个按钮,分别用于增加和减少计数。<script>
:定义了组件的逻辑,包括一个名为data
的函数,返回一个包含计数count
的对象,以及定义了increment
和decrement
方法的对象。<style scoped>
:定义了组件的局部样式,使按钮有一些外观上的区别。
这个组件可以被嵌入到Vue应用中使用,并且可以通过传递props来定制化。
二、组件注册
一个 Vue 组件在使用前需要先被"注册",这样 Vue 才能在渲染模板时找到其对应的实现。组件注册有两种方式:全局注册和局部注册。
2.1、全局注册
我们可以使用 Vue 应用实例的 .component() 方法,让组件在当前 Vue 应用中全局可用。
javascript
import { createApp } from 'vue'
const app = createApp({})
app.component(
// 注册的名字
'MyComponent',
// 组件的实现
{
/* ... */
}
)
如果使用单文件组件,你可以注册被导入的 .vue
文件:
javascript
import MyComponent from './App.vue'
app.component('MyComponent', MyComponent)
.component()
方法可以被链式调用:
javascript
app
.component('ComponentA', ComponentA)
.component('ComponentB', ComponentB)
.component('ComponentC', ComponentC)
全局注册的组件可以在此应用的任意组件的模板中使用:
javascript
<!-- 这在当前应用的任意组件中都可用 -->
<ComponentA/>
<ComponentB/>
<ComponentC/>
所有的子组件也可以使用全局注册的组件,这意味着这三个组件也都可以在彼此内部使用。
2.2、局部注册
局部注册意味着组件只能在某个父组件中使用。通常使用局部注册可以防止全局命名冲突。
相比之下,局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确。
在使用 <script setup>
的单文件组件中,导入的组件可以直接在模板中使用,无需注册:
javascript
<script setup>
import ComponentA from './ComponentA.vue'
</script>
<template>
<ComponentA />
</template>
如果没有使用 <script setup>
,则需要使用 components
选项来显式注册:
javascript
import ComponentA from './ComponentA.js'
export default {
components: {
ComponentA
},
setup() {
// ...
}
}
对于每个 components
对象里的属性,它们的 key 名就是注册的组件名,而值就是相应组件的实现。上面的例子中使用的是 ES2015 的缩写语法,等价于:
javascript
export default {
components: {
ComponentA: ComponentA
}
// ...
}
请注意:局部注册的组件在后代组件中不可用 。在这个例子中,ComponentA
注册后仅在当前组件可用,而在任何的子组件或更深层的子组件中都不可用。
2.3、Prop
prop 是父组件用来传递数据的一个自定义属性。
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
javascript
<div id="app">
<child message="hello!"></child>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
2.4、动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
javascript
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:message="parentMsg"></child>
</div>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
三、组件的数据
组件的数据是独立的,数据应当定义在 data 函数中,而不是对象中。这是为了确保每个组件实例有自己独立的数据。
javascript
export default {
data() {
return {
message: 'Hello, Vue!'
};
}
};
四、组件的生命周期钩子
Vue 组件提供了一系列的生命周期钩子函数,允许我们在组件的不同阶段执行代码。Vue 的生命周期可以概括为:创建、挂载、更新、销毁。常用的生命周期钩子有:
1)beforeCreate: 实例初始化之后,数据观测和事件配置之前调用。
2)created: 实例已创建,数据观测和事件配置已完成,但DOM未生成。
3)beforeMount: 在挂载之前调用,相关的render函数首次调用之前。
4)mounted: 实例挂载到DOM之后调用。
5)beforeUpdate: 数据变化时调用,更新DOM之前触发。
6)updated: 数据变化后,更新DOM后调用。
7)beforeDestroy: 实例销毁之前调用。
8)destroyed: 实例销毁后调用。
javascript
export default {
data() {
return {
message: 'Hello, Vue!'
};
},
created() {
console.log('Component created!');
},
mounted() {
console.log('Component mounted!');
},
beforeDestroy() {
console.log('Component will be destroyed');
},
destroyed() {
console.log('Component destroyed');
}
};