一. 组件
组件可以理解成项目的零件
一个 项目 就是由多个 组件 构成的
举例
一个房子是一个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) 小结
子向父传值的步骤
- 在子组件中绑定一个方法, 向父组件提交一个事件
- 在子组件标签中绑定一个方法, 监听事件
- 在父组件中编写处理程序