一. 组件
组件可以理解成项目的零件
一个 项目 就是由多个 组件 构成的
举例
一个房子是一个Vue应用, 那么客厅/卧室/厨房/卫生间就是组件
一个电脑是一个Vue应用, 那么硬盘/内存/主板/显示器/键盘就是组件
组件分为
- 全局组件
- 局部组件
1 全局组件
顾名思义, 全局都可以使用的组件
1) 完成Vue三步曲
在 src 目录下创建09_全局组件.html, 编写基础的vue模板
示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>09_全局组件</title><!-- 1. 引入vue.js --><script src="../node_modules/vue/dist/vue.js"></script></head><body><!-- 2. 编写div元素 --><div id="app"></div><!-- 3. 编写vue实例 --><script>const vm = new Vue({el: '#app'})</script></body></html>
2) 定义全局组件
语法
Vue.component('组件名', {组件参数})
示例
Vue.component('com1', {template: '<button @click="count++">你点了我{{count}}次</button>',data() {return {count: 0}}})
- 组件没有el参数, 原因是组件不会和具体的页面元素绑定
- 组件必须有template参数, 原因是组件需要渲染页面, template就是需要渲染的html
- 组件也是一个Vue的实例, 所以在组件中也有data/methods等
- data必须是一个函数, 并返回一个对象
3) 引用组件
在html中, 通过组件名引用组件
<!-- 2. 编写div元素 --><div id="app"><!-- 引用组件 --><com1></com1><com1></com1><com1></com1></div>
我们发现每个组件互不干扰,都有自己的count值。怎么实现的?
重点
组件中的data属性必须是函数!
当我们定义这个 <com1> 组件时,它的data 并不是像这样直接提供一个对象:
data: {count: 0}
取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {return {count: 0}}
如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!
4) 全局使用
创建一个新的vue实例vm2
const vm2 = new Vue({el: '#app2'})
创建新的div元素app2
html
<div id="app2"><com1></com1></div>
发现在app2中, 也可以引用com1组件, 这样定义的就是全局组件, 所有的vm实例都可以引用
5) 小结
全局组件的使用步骤
- 定义组件
- 引用组件
2 局部组件
一般在单页面应用(SPA)中使用较多的是局部组件
注意
局部组件只属于某一个Vue实例, 通过comopnents添加(挂载)
- 通常将组件参数单独定义, 方便工程化时管理
- 通常将组件模板单独定义, 方便工程化时管理
1) 完成Vue三步曲
在 src 目录下创建10_局部组件.html, 编写基础的vue模板
示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>10_局部组件</title><!-- 1. 引入vue.js --><script src="../node_modules/vue/dist/vue.js"></script></head><body><!-- 2. 编写div元素 --><div id="app"></div><!-- 3. 编写vue实例 --><script>const vm = new Vue({el: '#app'})</script></body></html>
2) 定义局部组件
模板部分
<!-- 组件模板 --><template id="tmp"><button @click="count++">你点了我{{count}}次</button></template>
js部分
// 定义组件对象const com1 = {template: '#tmp', // 定义组件模板data() { // 定义属性return {count: 0}}}
3) 挂载组件
在vue实例中挂载组件
const vm = new Vue({el: '#app',components: {// 组件名: 组件对象son: com1}})
- 在vue实例中, 通过
components完成挂载
4) 引用组件
在html中, 通过组件名引用组件
<!-- 2. 编写div元素 --><div id="app"><!-- 引用组件 --><son></son></div>
5) 小结
局部组件的使用步骤
- 定义组件模板
- 定义组件对象
- 在vue实例中挂载组件
- 引用组件
二. 组件通信
通常一个单页应用(SPA)会以一棵嵌套的组件树的形式来组织

页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
- 左侧内容区又分为上下两个组件
- 右侧边栏中又包含了 3 个子组件
各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求
主要分为两种情况:
- 父向子 传递数据
- 子向父 传递数据
1 父组件向子组件传值
1) 完成 Vue 三步曲
在 src 目录下创建11_父向子传值.html, 编写基础的 vue 模板
示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>11_父向子传值</title><!-- 1. 引入vue.js --><script src="../node_modules/vue/dist/vue.js"></script></head><body><!-- 2. 编写div元素 --><div id="app"></div><!-- 3. 编写vue实例 --><script>const vm = new Vue({el: '#app'})</script></body></html>
2) 定义子组件
在 vue 对象中, 使用 components 定义一个局部组件
components: {// 组件名: {组件参数}son: {template: '<h3></h3>',}}
3) 引用子组件
在 html 中通过组件名, 通过组件名引用组件
<div id="app"><son></son></div>
4) 传值
父组件向子组件传递数据的步骤
- 修改 html, 在子组件标签中添加一个属性 f2s
<div id="app"><!-- 1. 在son标签中, 添加一个属性 --><son f2s="父组件给子组件的数据"></son></div>
- 修改 js, 在子组件中使用 props 接收
components: {son: {template: '<h3></h3>',props: ['f2s']}}
- 在子组件的模板中使用
components: {son: {template: '<h3>{{ f2s }}</h3>',props: ['f2s']}}
5) 使用属性绑定
也可以和父组件中的一个数据绑定起来使用
<div id="app"><!-- 1. 在son标签中, 添加一个属性 --><son :f2s="msg"></son></div>
6) 小结
父向子传值的步骤
- 在子组件标签中添加一个属性, 发送数据
- 在子组件中通过
props, 接收数据
2 子组件向父组件传值
1) 完成 Vue 三步曲
在 src 目录下创建12_子向父传值.html, 编写基础的 vue 模板
示例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>12_子向父传值</title><!-- 1. 引入vue.js --><script src="../node_modules/vue/dist/vue.js"></script></head><body><!-- 2. 编写div元素 --><div id="app"></div><!-- 3. 编写vue实例 --><script>const vm = new Vue({el: '#app'})</script></body></html>
2) 定义子组件
在 vue 对象中, 使用 components 定义一个局部组件
components: {// 组件名: {组件参数}son: {template: '<button>点我</button>',}}
3) 引用子组件
在 html 中通过组件名, 通过组件名引用组件
<div id="app"><son></son></div>
4) 传值
子组件向父组件传递数据的步骤
- 在子组件模板中绑定一个方法
components: {//1. 定义组件son: {template: '<button @click="sendMsg">点我</button>',}}
- 在方法中向父组件提交(emit)一个事件
components: {//1. 定义组件son: {template: '<button @click="sendMsg">点我</button>',methods: {sendMsg(){// 调用$emit, 向父组件提交一个send事件this.$emit('send', "子组件->父组件")}}}}
- 在子组件标签中监听事件(绑定方法)
<div id="app"><!-- 2. 引用组件 --><son @send="handleSend"></son></div>
- 在父组件中编写处理程序
methods: {handleSend(msg){alert('收到子组件的数据'+msg)}},
5) 小结
子向父传值的步骤
- 在子组件中绑定一个方法, 向父组件提交一个事件
- 在子组件标签中绑定一个方法, 监听事件
- 在父组件中编写处理程序
