一. 组件

组件可以理解成项目的零件

一个 项目 就是由多个 组件 构成的

举例

一个房子是一个Vue应用, 那么客厅/卧室/厨房/卫生间就是组件

一个电脑是一个Vue应用, 那么硬盘/内存/主板/显示器/键盘就是组件

组件分为

  • 全局组件
  • 局部组件

1 全局组件

顾名思义, 全局都可以使用的组件

1) 完成Vue三步曲

在 src 目录下创建09_全局组件.html, 编写基础的vue模板

示例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>09_全局组件</title>
  7. <!-- 1. 引入vue.js -->
  8. <script src="../node_modules/vue/dist/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 2. 编写div元素 -->
  12. <div id="app"></div>
  13. <!-- 3. 编写vue实例 -->
  14. <script>
  15. const vm = new Vue({
  16. el: '#app'
  17. })
  18. </script>
  19. </body>
  20. </html>

2) 定义全局组件

语法

  1. Vue.component('组件名', {组件参数})

示例

  1. Vue.component('com1', {
  2. template: '<button @click="count++">你点了我{{count}}次</button>',
  3. data() {
  4. return {
  5. count: 0
  6. }
  7. }
  8. })
  • 组件没有el参数, 原因是组件不会和具体的页面元素绑定
  • 组件必须有template参数, 原因是组件需要渲染页面, template就是需要渲染的html
  • 组件也是一个Vue的实例, 所以在组件中也有data/methods等
  • data必须是一个函数, 并返回一个对象

3) 引用组件

在html中, 通过组件名引用组件

  1. <!-- 2. 编写div元素 -->
  2. <div id="app">
  3. <!-- 引用组件 -->
  4. <com1></com1>
  5. <com1></com1>
  6. <com1></com1>
  7. </div>

我们发现每个组件互不干扰,都有自己的count值。怎么实现的?

重点

组件中的data属性必须是函数

当我们定义这个 <com1> 组件时,它的data 并不是像这样直接提供一个对象:

  1. data: {
  2. count: 0
  3. }

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

  1. data: function () {
  2. return {
  3. count: 0
  4. }
  5. }

如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

4) 全局使用

创建一个新的vue实例vm2

  1. const vm2 = new Vue({
  2. el: '#app2'
  3. })

创建新的div元素app2

html

  1. <div id="app2">
  2. <com1></com1>
  3. </div>

发现在app2中, 也可以引用com1组件, 这样定义的就是全局组件, 所有的vm实例都可以引用

5) 小结

全局组件的使用步骤

  1. 定义组件
  2. 引用组件

2 局部组件

一般在单页面应用(SPA)中使用较多的是局部组件

注意

局部组件只属于某一个Vue实例, 通过comopnents添加(挂载)

  • 通常将组件参数单独定义, 方便工程化时管理
  • 通常将组件模板单独定义, 方便工程化时管理

1) 完成Vue三步曲

在 src 目录下创建10_局部组件.html, 编写基础的vue模板

示例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>10_局部组件</title>
  7. <!-- 1. 引入vue.js -->
  8. <script src="../node_modules/vue/dist/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 2. 编写div元素 -->
  12. <div id="app"></div>
  13. <!-- 3. 编写vue实例 -->
  14. <script>
  15. const vm = new Vue({
  16. el: '#app'
  17. })
  18. </script>
  19. </body>
  20. </html>

2) 定义局部组件

模板部分

  1. <!-- 组件模板 -->
  2. <template id="tmp">
  3. <button @click="count++">
  4. 你点了我{{count}}次
  5. </button>
  6. </template>

js部分

  1. // 定义组件对象
  2. const com1 = {
  3. template: '#tmp', // 定义组件模板
  4. data() { // 定义属性
  5. return {
  6. count: 0
  7. }
  8. }
  9. }

3) 挂载组件

在vue实例中挂载组件

  1. const vm = new Vue({
  2. el: '#app',
  3. components: {
  4. // 组件名: 组件对象
  5. son: com1
  6. }
  7. })
  • 在vue实例中, 通过components完成挂载

4) 引用组件

在html中, 通过组件名引用组件

  1. <!-- 2. 编写div元素 -->
  2. <div id="app">
  3. <!-- 引用组件 -->
  4. <son></son>
  5. </div>

5) 小结

局部组件的使用步骤

  1. 定义组件模板
  2. 定义组件对象
  3. 在vue实例中挂载组件
  4. 引用组件

二. 组件通信

通常一个单页应用(SPA)会以一棵嵌套的组件树的形式来组织

Vue 组件   组件通信 - 图1

页面首先分成了顶部导航、左侧内容区、右侧边栏三部分

  • 左侧内容区又分为上下两个组件
  • 右侧边栏中又包含了 3 个子组件

各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求

主要分为两种情况:

  • 父向子 传递数据
  • 子向父 传递数据

1 父组件向子组件传值

1) 完成 Vue 三步曲

在 src 目录下创建11_父向子传值.html, 编写基础的 vue 模板

示例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>11_父向子传值</title>
  7. <!-- 1. 引入vue.js -->
  8. <script src="../node_modules/vue/dist/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 2. 编写div元素 -->
  12. <div id="app"></div>
  13. <!-- 3. 编写vue实例 -->
  14. <script>
  15. const vm = new Vue({
  16. el: '#app'
  17. })
  18. </script>
  19. </body>
  20. </html>

2) 定义子组件

在 vue 对象中, 使用 components 定义一个局部组件

  1. components: {
  2. // 组件名: {组件参数}
  3. son: {
  4. template: '<h3></h3>',
  5. }
  6. }

3) 引用子组件

在 html 中通过组件名, 通过组件名引用组件

  1. <div id="app">
  2. <son></son>
  3. </div>

4) 传值

父组件向子组件传递数据的步骤

  1. 修改 html, 在子组件标签中添加一个属性 f2s
  1. <div id="app">
  2. <!-- 1. 在son标签中, 添加一个属性 -->
  3. <son f2s="父组件给子组件的数据"></son>
  4. </div>
  1. 修改 js, 在子组件中使用 props 接收
  1. components: {
  2. son: {
  3. template: '<h3></h3>',
  4. props: ['f2s']
  5. }
  6. }
  1. 在子组件的模板中使用
  1. components: {
  2. son: {
  3. template: '<h3>{{ f2s }}</h3>',
  4. props: ['f2s']
  5. }
  6. }

5) 使用属性绑定

也可以和父组件中的一个数据绑定起来使用

  1. <div id="app">
  2. <!-- 1. 在son标签中, 添加一个属性 -->
  3. <son :f2s="msg"></son>
  4. </div>

6) 小结

父向子传值的步骤

  1. 在子组件标签中添加一个属性, 发送数据
  2. 在子组件中通过props, 接收数据

2 子组件向父组件传值

1) 完成 Vue 三步曲

在 src 目录下创建12_子向父传值.html, 编写基础的 vue 模板

示例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>12_子向父传值</title>
  7. <!-- 1. 引入vue.js -->
  8. <script src="../node_modules/vue/dist/vue.js"></script>
  9. </head>
  10. <body>
  11. <!-- 2. 编写div元素 -->
  12. <div id="app"></div>
  13. <!-- 3. 编写vue实例 -->
  14. <script>
  15. const vm = new Vue({
  16. el: '#app'
  17. })
  18. </script>
  19. </body>
  20. </html>

2) 定义子组件

在 vue 对象中, 使用 components 定义一个局部组件

  1. components: {
  2. // 组件名: {组件参数}
  3. son: {
  4. template: '<button>点我</button>',
  5. }
  6. }

3) 引用子组件

在 html 中通过组件名, 通过组件名引用组件

  1. <div id="app">
  2. <son></son>
  3. </div>

4) 传值

子组件向父组件传递数据的步骤

  1. 在子组件模板中绑定一个方法
  1. components: {
  2. //1. 定义组件
  3. son: {
  4. template: '<button @click="sendMsg">点我</button>',
  5. }
  6. }
  1. 在方法中向父组件提交(emit)一个事件
  1. components: {
  2. //1. 定义组件
  3. son: {
  4. template: '<button @click="sendMsg">点我</button>',
  5. methods: {
  6. sendMsg(){
  7. // 调用$emit, 向父组件提交一个send事件
  8. this.$emit('send', "子组件->父组件")
  9. }
  10. }
  11. }
  12. }
  1. 在子组件标签中监听事件(绑定方法)
  1. <div id="app">
  2. <!-- 2. 引用组件 -->
  3. <son @send="handleSend"></son>
  4. </div>
  1. 在父组件中编写处理程序
  1. methods: {
  2. handleSend(msg){
  3. alert('收到子组件的数据'+msg)
  4. }
  5. },

5) 小结

子向父传值的步骤

  1. 在子组件中绑定一个方法, 向父组件提交一个事件
  2. 在子组件标签中绑定一个方法, 监听事件
  3. 在父组件中编写处理程序