08-非单文件组件VC

6/3/2022

# 1, 组件化开发

Vue特点: 组件化、声明式编程、虚拟DO+DIFF

  • 组件:component

# 1.1, 什么是组件化开发

组件化开发思想

  • 将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展;
  • 但如果,我们讲一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了
  • 如果我们将一个个功能块拆分后,就可以像搭建积木一下来搭建我们的项目
  • 现在整个的大前端开发都是组件化的天下
  • 无论从三大框架(Vue、React、Angular),还是跨平台方案的Flutter,甚至是移动端都在转向组件化开发,包括小程序的开发也是采用组件化开发的思想
  • 组件: 复用的【代码 + 资源(图片、样式、视频)】集合在一起即为组件

以组件化的思想考虑整个项目

  • 将一个完整的页面分成很多个组件
  • 每个组件都用于实现页面的一个功能块
  • 而每一个组件又可以进行细分
  • 而组件本身又可以在多个地方进行复用
  • 组件化提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用
  • 任何的应用都会被抽象成一颗组件树

# 1.2, 组件的基本的使用

Vue框架中从书写角度出发:分为两大类组件

  • 单文件组件: 一个文件即为一个组件, 这个文件的尾缀务必是.vue,目前我们不会学习
  • 非单文件组件: 一个文件里面,可以定义多个组件,这个文件尾缀.html.

非单文组件使用分为三步骤

  • 第一步: 定义
    • 定义一个组件:利用的是Vue.extend方法去定义组件
    • extend方法里面也需要传递配置对象,extend配置对象与Vue配置对象几乎一模一样!!!
  • 第二步: 注册
    • 注册,某一个地方需要组件,进行注册。在components配置项进行注册
  • 第三步: 使用
    • 使用,【是以自定义标签的形式使用,首字母一般大写】

注意点

  • 不能书写el、组件的响应式数据务必比是函数写法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 
        vue的特点:
            1)组件化开发    component
            2)声明式编程
            3)虚拟DOM+DIFF

     -->
    <!-- 定义的容器 -->
    <div id="app">
        <Hello></Hello>
        <Hello></Hello>
        <Hello></Hello>
        <Hello></Hello>
        <Hello></Hello>
    </div>

    <script>

        // 在extend中传组件的配置项
        // 之前new Vue时,传递的配置项,在Vuex.extend中基本上都可以配置
        let Hello = Vue.extend({
            // el 只有要根组件中才可以配置el,在普通组件中不能配置el
            template:"<h2>我是Hello组件</h2>", // 配置当前组件对应的模板
        })


        // 注册组件分两类:
        //    1)全局注册   先不讲
        //    2)局部注册   
        let vm = new Vue({
            el:"#app",
            data(){
                return {
                 
                }
            },
            components:{
                Hello
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
    <style>
        *{
            margin: 0px;
            padding: 0px;
        }
        .box{
            width: 300px;
            height: 150px;
            background-color: skyblue;
        }
        button{
            width: 50px;
            height: 25px;
        }
        .box1{
            width: 300px;
            height: 150px;
            margin: 10px 0;
            background-color: pink;
        }
    </style>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">
        <!-- 使用组件就相当于使用标签 -->
        <Count></Count> <br>
        <Count></Count> <br>
        <Count></Count> <br>
        <Count></Count> <br>
        <Count></Count> <br>
        <Box></Box>  <br>
        <Box></Box>  <br>
        <Box></Box>  <br>
        <Box></Box>  <br>
    </div>

    <script>
        let Hello = Vue.extend({
            template: "<h1>我是Hello组件</h1>"
        })

        let Count = Vue.extend({
            components:{
                Hello
            },
            data(){
                return{
                    count:0
                }
            },
            methods:{
                add(){ this.count++ },
                minus(){ this.count-- }
            },
            template: `
                <div class="box">
                    <Hello></Hello>
                    <button @click="minus">-</button>
                    <span>{{count}}</span>
                    <button @click="add">+</button>
                </div>
            `
        })

        let Box = Vue.extend({
            data(){
                return{
                    f:16
                }
            },
            template:`
                <div class="box1">
                    <p :style="{fontSize:f+'px'}" @click="f++">我是一个孤独的P标签</p>
                </div>
            `
        })

        let vm = new Vue({
            el: "#app",
            components:{
                Count,
                Box
            },
            data() {
                return {

                }
            }
        });
    </script>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

为什么组件的响应式务必要书写为函数

<script>
    function data() {
        return {
            a: 1
        };
    }

    let c1 = data();
    let c2 = data();
    c1.a = 100;
    console.log(c1 === c2);
    console.log(c1, c2);
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.3, 根组件的template

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">
        <div>我是一个DIV</div>
    </div>

    <script>
        // 对于根组件来说,可以在两个地方,指定模板
        //    1)el对应容器内部的html代码段
        //    2)配置template,用来指定模板
        //    如果指定了template,它的优先级更高
        let vm = new Vue({
            el: "#app",
            template:`
                <div>haha</div>
            `,
            data() {
                return {

                }
            }
        });
        vm.$mount("#app")
    </script>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">
    </div>

    <script>
        // 定义Count组件
        const Count = Vue.extend({
            data() {
                return {
                    count: 1
                };
            },
            template: `
                <div>
                   <button @click="count++">加</button>
                   <span>{{count}}</span>
                   <button @click="count--">减</button>    
                </div>
             `
        });
        // 定义Box组件
        const Box = Vue.extend({
            data() {
                return {
                    f: 16
                };
            },
            template: `
               <div>
                  <p :style="{fontSize:f+'px'}" @click="f+=10">I love Vue!!!</p> 
               </div>
            `
        })
        
        // 定义App组件
        const App = Vue.extend({
            components:{
                Count,
                Box
            },
            template:`
                <div>
                    App组件
                    <hr>
                    <Count></Count>
                    <Count/>
                    <hr>
                    <Box/>
                    <Box/>
                </div>
            `
        })
        
        let vm = new Vue({
            components:{
                App
            },
            template:`
                <div>
                    <App></App>
                </div>
            `,
            data() {
                return {

                }
            }
        });
        vm.$mount("#app")
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

# 1.4, 全局注册组件

定义为全局组件 : 定义一次, 可以在任意地方直接使用,不需要注册。

  • 第一个参数:全局组件的名字(字符串) 第二个参数: 组件(不能书写为字符串)
  • 全局组件一般在这种情况下才会使用: 项目当中很多地方(组件),大家频繁使用某一个功能
  • 你就可以把这个功能封装为全局组件,定义一次,可以在任意地方直接使用【不需要引入、不需要注册】直接使用。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 定义的容器 -->
    <div id="app1">
        <div>
            我是DIV1
            <hr>
            <Count></Count>
        </div>
    </div>

    <div id="app2">
        <div>
            我是DIV2
            <hr>
            <Count></Count>
        </div>
    </div>

    <script>
        // 定义Count组件
        const Count = Vue.extend({
            data() {
                return {
                    count: 1
                };
            },
            template: `
                <div>
                   <button @click="count++">加</button>
                   <span>{{count}}</span>
                   <button @click="count--">减</button>    
                </div>
             `
        });

        // 注册组件分两种:
        //    1)局部注册   在哪里注册,在对应的模板中使用
        //    2)全局注册   只需要注册一次,可以在任何地方使用

        // 全局注册  在项目中,有些组件为了使用方法,都会使用全局注册
        Vue.component("Count",Count)

        let vm1 = new Vue({
            el:"#app1",
            // components:{
            //     Count
            // },
            data(){
                return {
                 
                }
            }
        });
        let vm2 = new Vue({
            el:"#app2",
            // components:{
            //     Count
            // },
            data(){
                return {
                 
                }
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

# 1.5, VM与组件的关系

Vue框架中组件, 实质是Vue.extend函数返回的构造函数VueComponent

  • 组件它是一个构造函数,那么在使用组件的时候,不应该new Student,咱们不需要手动去调用
  • Vue框架查看网页, 看到了标签,Vue框架帮你new VueComponent
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">

    </div>

    <script>
        // 定义Count组件
        // extend返回一个构造函数,叫VueComponent
        const Count = Vue.extend({
            data() {
                return {
                    count: 1
                };
            },
            template: `
                <div>
                   <button @click="count++">加</button>
                   <span>{{count}}</span>
                   <button @click="count--">减</button>    
                </div>
             `
        });
        // VueComponent   VueComponent是一个类,构造器
        // 按理说,我们需要去new VueComponent  得到一个普通组件实例
        // 但是我们没有new   Vue底层会帮我们new 
        // 一个组件说白了,也是一个对象,只不过这个对象不需要我们去new 
        console.log(Count);
        // c叫组件对象  这是我们new出来的
        let c = new Count();
        // 也可以使用Vue原型对象上的属性或方法
        console.log(c.$data);

        // Vue  vm   VueCompoent  vc


        // Vue也叫类,也叫构造器
        // new Vue得到一个vm实例
        let vm = new Vue({
            el: "#app",
            data() {
                return {
                    a:1
                }
            }
        });

        // console.log(vm.$data);
    </script>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>

<body>
    <!-- 定义的容器 -->
    <div id="app">
        <Student></Student>
    </div>

    <script>
        Vue.prototype.coding = function(){
            console.log("开始打代码了...");
        }

        // 当我们使用Vue.extend 得到一个VueComponent构造器
        // 不需要我们new  Vue底层会帮我们new 
        let Student = Vue.extend({
            data() {
                return {
                    info: 'I love Vue!!!'
                };
            },
            template: `
                <h1 @click="changeInfo">{{info}}</h1>
            `,
            methods: {
                changeInfo() {
                    // this.info = "I love React!!!"
                    // 问:this是谁?
                    // 答:vc
                    // 组件内的this,不是vm,不是vm,不是vm,是VueComponent类的实例
                    // 看上去和vm很像,但实际上,两者是不同东西
                    // 组件内的this,就是VueComponet类的实例,可以叫它VC
                    // this.coding();  

                    console.log(this.__proto__.__proto__ === Vue.prototype);
                }
            }
        });


        let vm = new Vue({
            el: "#app",
            components:{
                Student
            },
            data() {
                return {
                    a: 1
                }
            },
            methods:{
                ok(){
                    // this表示vm
                    console.log(this);
                }
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

Vue.extend创建组件简写方式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <!-- 引入Vue.js,人家向外暴露一个Vue类  new Vue -->
    <script src="../lib/vue2.7.8.js"></script>
</head>
<body>  
    <!-- 定义的容器 -->
    <div id="app">
        <!-- <Abc></Abc> -->
        <App></App>
    </div>

    <script>
        // 是Vue.extend的简写形式
        // 定义组件
        let App = {
            // 为了在调试工具中显示正确的组件名,通常会配置name选项
            name:"App",
            data(){
                return{
                    name:"wc"
                }
            },
            template:`
                <div>
                    <h1 @click="handler">{{name}}</h1>
                </div>
            `,
            methods:{
                handler(){
                    this.name = "xq";
                    console.log(this);
                }
            }
        }

        let vm = new Vue({
            el:"#app",
            components:{
                // Abc表示注册名  App表示组件名
                // "Abc":App

                App
            },
            data(){
                return {
                 
                }
            }
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Last Updated: 12/25/2022, 10:02:14 PM