4.Vue组件
阅读原文时间:2023年07月08日阅读:1

一、组件化开发概述

  1.组件化开发思想

    标准

    分治:不同的功能分配到不同的组件中

    重用:

    组合

  2.编程中的组件化思想体现

  3.组件化规范:

    Web Components

      我们希望尽可能多的重用代码

      自定义组件的方式不太容易(html、css和js)

      多次使用组件可能导致冲突

    Web Components通过创建封装好功能的定制元素解决上述问题

    Vue部分实现了上述规范

    不同的功能封装到不同的组件中,组件可以组合以形成完整的应用

二、组件的注册

  2.1 全局组件注册语法

    Vue.component(组件名称,{

      data:组件数据,

      template:组件模板内容

    })

  例:

1 // 定义一个名为button-counter的组件
2 Vue.component('button-counter',{
3 data:function(){
4 return{
5 count:0
6 }
7 },
8 template:``
9 });

  2.2 组件的用法

1

2 3 4 5

    注:组件可以重用,且组件之间是相互独立的

  2.3 组件注册注意事项

    1.data必须是一个函数

      分析函数与普通对象的对比

    2.组件模板内容必须是单个的根元素

      分析实际演示效果

    3.组件模板内容可以是模板字符串

      模板字符串需要浏览器提供支持(ES6语法)

    4.组件的命名方式

      短横线

      Vue.component('my-component',{/*…*/})

      驼峰式

      Vue.component('MyComponent',{/*…*/})

      如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件

  2.4 局部组件注册

    var ComponentA = { /* … */}

    var ComponentB = { /* … */}

    var ComponentC = { /* … */}

    new Vue({

      el:'#app',

      components:{

        'component-a':ComponentA,

        'component-b':ComponentB,

        'component-c':ComponentC,

      }

    })

1 var HelloWorld = {
2 data:function(){
3 return{
4 msg:'Hello World'
5 }
6 },
7 template:`

{{msg}}
`
8 };
9
10 var HelloTom = {
11 data:function(){
12 return{
13 msg:'Hello Tom'
14 }
15 },
16 template:`
{{msg}}
`
17 };
18
19 var HelloJerry = {
20 data:function(){
21 return{
22 msg:'Hello Jerry'
23 }
24 },
25 template:`
{{msg}}
`
26 };
27 var vm = new Vue({
28 el:'#app',
29 data:{
30
31 },
32 components:{
33 'hello-world':HelloWorld,
34 'hello-tom':HelloTom,
35 'hello-jerry':HelloJerry
36 }
37 })

    注:局部组件只能在父组件中使用,不能在其他的组件中使用

三、Vue调试工具

  3.1 调试工具安装

    (1) 克隆仓库

    (2) 安装依赖包

    (3) 构建

    (4) 打开Chrome扩展页面

    (5) 选中开发者模式

    (6) 加载已解压的扩展,选择shells/chrome

四、组件间数据交互

  4.1 父组件向子组件传值

    1.子组件中通过props接收父组件传递过来的内容,具体通过属性名来接收

    2.父组件通过属性将值传递给子组件,属性绑定有两种方式,一是写死,二是动态绑定

    3.属性可以传递多个,具体可以在props中多加参数

1

2 {{pmsg}} 3 4 5

1 Vue.component('menu-item',{
2 props:['title','content'],
3 data:function(){
4 return{
5 msg:'子组件自身的数据'
6 }
7 },
8 template:`

{{msg + '----' + title + '----' + content}}
`
9 })
10 var vm = new Vue({
11 el:'#app',
12 data:{
13 pmsg:'父组件中的内容',
14 ptitle:'父组件传向子组件的动态绑定的数据'
15 }
16 })

   4.2 props属性名规则

     1.在props中使用驼峰的形式,模板中需要使用短横线的形式

     2.字符串形式的模板中没有这个限制   

1

2 {{pmsg}} 3 4

1 Vue.component('third-com',{
2 props:['testTitle'],
3 template:`

{{testTitle}}
`
4 })
5 Vue.component('menu-item',{
6 props:['menuTitle'],
7 template:`
{{menuTitle}}
`
8 })
9 var vm = new Vue({
10 el:'#app',
11 data:{
12 pmsg:'父组件中的内容',
13 ptitle:'动态绑定属性'
14 },
15 })

    4.3 props属性值类型

      字符串  String

      数值     Number

      布尔值  Boolean

      数组     Array

      对象     Object 1

 2<!--       

3 字符串  String
4 数值   Number
5 布尔值  Boolean
6 数组   Array
7 对象   Object
8 -->
9
10

1 Vue.component('menu-item',{
2 props:['pstr','pnum','pboo','parr','pobj'],
3 template:`

4
{{"传递的是字符串" + pstr}}

5
{{"传递的是数字" + pnum}}

6
{{"传递的是布尔值" + pboo}}

7
数组:

8
    9
  • {{item}}
  • 10

11
{{"传递的是对象:"}}{{pobj.name}}{{pobj.age}}

12
`
13 })
14 var vm = new Vue({
15 el:'#app',
16 data:{
17 pmsg:'父组件中的内容',
18 pstr:'hello',
19 pnum:12,
20 pboo:true,
21 parr:['apple','orange','banana'],
22 pobj:{
23 name:'lisi',
24 age:12
25 }
26 }
27 })

    4.4 子组件向父组件传值

      注:props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据

      1. 子组件通过自定义事件向父组件传值

        

      2. 父组件监听子组件事件

        

1

2
{{pmsg}}

3 @enlarge-text='handle'>
4

1 /*
2 props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据
3 */
4 Vue.component('menu-item',{
5 props:['parr'],
6 template:`
7

8
    9
  • {{item}}
  • 10
11 12 13

14 `
15 })
16 var vm = new Vue({
17 el:'#app',
18 data:{
19 pmsg:'父组件中内容',
20 parr:['apple','orange','banana'],
21 fontSize:10
22 },
23 methods: {
24 handle:function(){
25 // 扩大字体大小
26 this.fontSize += 5;
27 }
28 },
29 })

      3. 子组件通过自定义事件向父组件传递消息

        

      4. 父组件监听子组件的事件

        

        $event是固定的

1

2
{{pmsg}}

3 @enlarge-text='handle($event)'>
4

1 Vue.component('menu-item',{
2 props:['parr'],
3 template:`
4

5
    6
  • {{item}}
  • 7
8 9 10 11

12 `
13 })
14 var vm = new Vue({
15 el:'#app',
16 data:{
17 pmsg:'父组件中内容',
18 parr:['apple','orange','banana'],
19 fontSize:10
20 },
21 methods: {
22 handle:function(val){
23 // 扩大字体大小
24 this.fontSize += val;
25 }
26 },
27 })

    4.5 非父子组件间传值

      1. 单独的事件中心管理组件间的通信

        var eventHub = new Vue()

      2. 监听事件与销毁事件

        eventHub.$on('add-todo',addTodo)

        eventHub.$off('add-todo')

      3. 触发事件

        eventHub.$emit('add-todo',id)

1

2
父组件
3
4 5 6

1 // 提供事件中心
2 var hub = new Vue();
3
4 Vue.component('test-tom',{
5 data:function(){
6 return{
7 num:0
8 }
9 },
10 template:`
11

12
TOM:{{num}}

13
14 15

16

17 `,
18 methods: {
19 handle:function(){
20 // 触发兄弟组件的事件
21 hub.$emit('jerry-event',2);
22 }
23 },
24 mounted:function(){
25 // 监听事件
26 hub.$on('tom-event',(val) =>{
27 this.num += val;
28 });
29 }
30 });
31 Vue.component('test-jerry',{
32 data:function(){
33 return{
34 num:0
35 }
36 },
37 template:`
38
39
JERRY:{{num}}

40
41 42

43

44 `,
45 methods: {
46 handle:function(){
47 // 触发兄弟组件的事件
48 hub.$emit('tom-event',1);
49 }
50 },
51 mounted:function(){
52 // 监听事件
53 hub.$on('jerry-event',(val) =>{
54 this.num += val;
55 });
56 }
57 });
58
59 var vm = new Vue({
60 el:'#app',
61 data:{
62
63 },
64 methods: {
65 handle:function(){
66 hub.$off('tom-event');
67 hub.$off('jerry-event');
68 }
69 },
70 })

五、组件插槽

    5.1 组件插槽的作用

      父组件向子组件传递内容

      hi ->

    5.2 组件插槽的基本用法

      1.插槽的位置

        Vue.component('alert-box',{

          template:`

            

            Error!

            

            

              `

        })

      2.插槽的位置

        Something bad happened       

1

2 啦啦啦 3 4

1 Vue.component('alert-box',{
2 template:`
3

4 ERROR: 5 默认内容 6

7 `
8 })
9 var vm = new Vue({
10 el:'#app',
11 data:{
12
13 }
14 })

    5.3 具名插槽用法

      1.插槽定义

      

        

          

        

        

          

        

        

          

        

      

      2.插槽内容

        

          

标题内容

          

主要内容1

          

主要内容2

          

底部内容

        

    5.4 作用域插槽

      应用场景:父组件对子组件内容进行加工处理

六、基于组件的案例 - 购物车

    6.1 按照组件化的方式实现业务需求

      根据业务功能进行组件化划分

        (1) 标题组件 展示文本

        (2) 列表组件 列表展示、商品数量变更、商品删除

        (3) 结算组件 计算商品总额

      实现整体布局和样式效果

        划分独立的功能组件

        组合所有的子组件形成整体结构

        逐个实现各个组件功能

        标题组件

        列表组件

        结算组件