1. 前言
Vue.js是一个基于组件的Javascript框架,组件化编程是核心思想之一。通过组件化,Vue允许开发者将用户页面拆分成独立,可重用的部分,从而提升代码的可维护性,可读性以及可服用性。
本文主要讲解在Vue2中组件化编程模式
2. 组件的定义
组件是一个具有独立功能的Vue实例,具有自己的数据,模板,样式与逻辑。每个组件可以相互交互,接收输入(props),并可以产生输出(事件),从而形成一个灵活的用户界面
3. 组件化编程的结构
3.1 组件创建
Vue组件最常用的创建方式是使用Vue单文件组件,包含以下三个部分
- 模板(Template):定义组件的HTML结构
Vue规定,在组件的模板中我们需要创建一个父标签囊括所有的标签
-
脚本(Script):定义组件的逻辑和数据
-
样式(Style):定义组件的CSS样式
以下是一个完整Vue组件模板:
javascript
<template>
</template>
<style>
</style>
<script>
</script>
3.2 Vue.app
使用Vue.app集成所有的子组件(components),是应用的核心,管理应用的状态和组件
javascript
<template>
</template>
<style>
</style>
<script>
export component from './...'
export default{
components:{} //注册组件
}
</script>
3.3 main.js
应用的入口Javascript文件,管理应用的状态与组件。
创建Vue实例,定义路由,状态管理,以及全局组件和插件的配置
javascript
// main.js
import Vue from 'vue';
import App from './App.vue';
import Greeting from './Greeting.vue'; // 导入组件
// 全局注册组件
Vue.component('Greeting', Greeting);
new Vue({
render: h => h(App),
}).$mount('#app');
3.4 index.html
应用文件的入口文件,提供挂载点
javascript
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
4. 组件的注册
组件可以在全局或局部进行注册
- 全局注册
定义:全局注册是指在Vue应用的整个生命周期,组件都可以被任何地方的模板使用
javascript
// main.js
import Vue from 'vue';
import App from './App.vue';
import Greeting from './Greeting.vue'; // 导入组件
// 全局注册组件
Vue.component('Greeting', Greeting);
new Vue({
render: h => h(App),
}).$mount('#app');
优点:方便在多个组件中使用同一个组件,尤其是在大型应用中
缺点:如果有多个同名组件,全局注册可能会导致命名冲突
- 局部注册
定义:组件只可以在其父组件之中使用,其他组件无法访问该组件
在组件的components选项中进行注册
javascript
<template>
<div>
<Greeting></Greeting>
<div>
</template>
<style>
</style>
<script>
import Greeting from './Greeting.vue'
export default{
components:{
Greeting;
}
}
</script>
5. 组件的通信
5.1 数据传递
在子组件中使用props定义子组件中相关属性,父组件通过数据代理模式传递父组件的数据或者方法至子组件
javascript
//父组件
<ChildComponent :message="parentMessage" />
//子组件
export default{
props:['message'],
}
5.2 事件传递
事件传递主要是通过this.$emit函数出发自定义事件,将数据传递给父组件
javascript
this.$emit('事件名',数据)
将会触发该事件,并传递对应的数据
只需要在父组件上设定好对应的事件,以及事件触发之后执行的函数,数据传递至函数,子组件便将数据传递给父组件了。
子组件:
javascript
<template>
<button @click='sendData'>Click me</button>
</template>
<script>
export default{
methods:{sendData(){this.$emit('childEvent','Hello')}} //通过调用该方法触发事件
}
<script>
父组件:
javascript
<template>
<child @childEvent='handle'></child>
</template>
<script>
export default {
components:{child}
methods:{handle(message){console.log('这是子组件传来的数据',message)}}
}
</script>
5.3 插槽
插槽是一种非常重要的功能,用于实现组件的内容分发。插槽允许开发者在父组件中嵌套内容到子组件中,从而在不修改子组件代码的情况下灵活地定制其内容
5.3.1 默认插槽
子组件:
javascript
<template>
<div class='child'>
<slot></slot>
</div>
</template>
父组件:
javascript
<template>
<child>
<p>This is slot</p>
</child>
</template>
<script>
export default{
components:{child}
}
</script>
5.3.2 具名插槽
具名插槽允许一个组件中定义多个插槽,每个插槽都拥有自己的名字,这样父组件可以选择性的传递内容到不同的插槽位置
子组件:
javascript
<template>
<div class="child">
<header><slot name="header"></slot></header> <!-- 具名插槽 -->
<main><slot></slot></main> <!-- 默认插槽 -->
<footer><slot name="footer"></slot></footer> <!-- 具名插槽 -->
</div>
</template>
父组件:
javascript
<template>
<div>
<child-component>
<template v-slot:header>
<h1>This is the header content</h1>
</template>
<p>This is the default slot content.</p>
<template v-slot:footer>
<footer>Footer content goes here</footer>
</template>
</child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
}
}
</script>
5.3.3 插槽作用域
插槽不仅仅是用来传递静态内容,还可以向插槽传递数据通过插槽作用域,父组件可以将数据传递到子组件中的插槽,子组件可以在插槽模板内使用这些数据
javascript
<template>
<div class="child">
<slot :message="childMessage"></slot> <!-- 传递数据到插槽 -->
</div>
</template>
<script>
export default {
data() {
return {
childMessage: 'Hello from child!'
}
}
}
</script>
父组件:
javascript
<template>
<div>
<child-component>
<!-- 使用插槽作用域来访问子组件传递的内容 -->
<template v-slot:default="slotProps">
<p>{{ slotProps.message }}</p> <!-- 输出从子组件传递来的数据 -->
</template>
</child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
}
}
</script>