初学Vue(全家桶)-第11天(vue2):组件

初学Vue

组件

1、模块与组件、模块化与组件化

  • 什么是模块
    向外界提供特定功能的js程序,一般就是一个js文件,起到了复用js、简化js编写、提高js运行效率的作用。

  • 什么是组件
    用来实现局部特定功能效果的代码集合(html/css/js/image等),起到复用编码、简化项目编码、提高运行效率的作用。

  • 什么是模块化
    当应用中的js都以模块来编写,那这个应用就是一个模块化应用

  • 什么是组件化
    当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用

在这里插入图片描述

2、非单文件组件与单文件组件

  • 非单文件组件
    一个文件中包含n个组件
  • 单文件组件
    一个文件中只包含一个组件

2.1 非单文件组件

步骤:
1、创建组件
2、注册组件
3、使用组件(组件标签)

  • 局部注册组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../../JS/vue.js"></script>
    <title>Document</title>
</head>

<body>
    <!-- 准备一个容器 -->
    <div id="root">
        <!-- 3、编写组件标签,使用定义好的组件 -->
        <school></school>
        <hr>
        <student></student>
    </div>
    <script>
        Vue.config.productionTip = false;

        // 1、创建组件
        // 创建一个school组件
        const school = Vue.extend({
      
      
            // 组件的基本结构用template配置项决定(注意用div包裹)
            template: `
                <div>
                    <h2>学校名称:{
       
       {schoolName}}</h2>
                    <h2>学校地址:{
       
       {address}}</h2>
                </div>
            `,

            // 注意组件里面不需要写el配置项,因为最终所有组件都会被一个vm管理,由vm决定服务对象
            // data配置项必须写成函数形式
            data() {
      
      
                return {
      
      
                    schoolName: "清华大学",
                    address: "北京",
                }
            }

        })

        // 创建一个student组件
        const student = Vue.extend({
      
      
            template: `
                <div>
                    <h2>学生姓名:{
       
       {studentName}}</h2>
                    <h2>学生年龄:{
       
       {age}}</h2>
                </div>
            `,

            data() {
      
      
                return {
      
      
                    studentName: "李明",
                    age: 23,
                }
            }
        })

        // 2、局部注册组件
        const vm = new Vue({
      
      
            el: "#root",
            // 组件相关的配置项
            components: {
      
      
                school: school,
                student: student
            }
        })
    </script>
</body>

</html>

开发者工具查看
在这里插入图片描述

  • 全局注册组件
<body>
    <!-- 3、使用组件标签 -->
    <div id="root1">
        <hello></hello>
    </div>
    <!-- 在不同的vm对象中也能使用全局注册的标签 -->
    <div id="root2">
        <hello></hello>
    </div>

    <script>
        // 1、创建组件
        const hello = Vue.extend({
      
      
            template: `
                <div>
                    <div>你好呀!!{
       
       {name}}</div>
                </div>
            `,
            data(){
      
      
                return {
      
      
                    name:"李明"
                }
            }
        })

        // 2、全局注册组件
        Vue.component("hello",hello);

        new Vue({
      
      
            el: "#root1",
        })

        new Vue({
      
      
            el: "#root2",
        })
    </script>
</body>

问题1:为什么data配置项必须写成函数的形式而不可以写成对象形式?
当data写成单独一个对象时,如果有多个用户对data进行修改,那么改的就是同一个data对象。例如:

<!DOCTYPE html> 
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../../JS/vue.js"></script>
    <title>Document</title> </head>
<body>    
<script>
       // 这是一个对象
       const data = {
       
       
           a:1,
           b:2
       }

       // 有两个对象同时想使用data中的数据
       const x1 = data;
       const x2 = data;    
</script> 
</body>
</html> 

在这里插入图片描述
因为这个x1和x2都指向data,而data最内存中的地址是固定的,也就是说改变了x1中的值,就是改变了data的值,同时x2因为也指向data,那么x2也改变。


写成函数时可以通过return返回一个新对象,如下:

    <script>
        // 这是一个函数
        function data() {
       
       
            return {
       
       
                a: 1,
                b: 2
            }
        }

        // 有两个对象同时想使用data中的数据
        const x1 = data();
        const x2 = data();
    </script> 
   	</body>

在这里插入图片描述
分析:写成函数形式时,每次调用函数,都会返回一个新的对象,每一个对象都是单独存在的,各自占一片内存,互不影响。
问题2:注册组件的components配置项中,key值和value值的意义?
key值是使用组件时的名字,也就是组件标签,value值时创建组件时起的临时名字。
问题3:证明组件可以重复使用?

<!-- 准备一个容器 -->
    <div id="root">
        <!-- 3、编写组件标签,使用定义好的组件 --
        <school></school>
        <hr>
        <student></student>
        <student></student>
        <student></student>
    </div>

在这里插入图片描述
在这里插入图片描述


使用组件的几个注意点:
1、组件标签的命名
(1)单个单词时,首字母大写或则和小写都行,例如:school或者School
(2)多个单词组成时
第一种方式:单词用横杠隔开,单词全部小写,并且用引号包裹起来,例如:“my-school”
第二种方式:每个单词首字母大写,例如:MySchool,这种方式必须在使用脚手架的前提下。
(3)组件尽量避免与html中保留的标签同名。

2、使用组件标签时有两种方式,一种时双标签,例如:< school></ school>,另一种时自闭合标签,例如< school/>,这种方式的使用前提是使用脚手架

组件嵌套

  • 平级定义多个组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../../JS/vue.js"></script>
    <title>组件嵌套</title>
</head>

<body>
    <!-- 3、使用组件 -->
    <div id="root">
        <school></school>
        <student></student>
        <teacher></teacher>
    </div>
    <script>
        // 1、创建组件
        // school组件
        const school = Vue.extend({
      
      
            name:"school",
            template: `
                <div>
                    <div>学校名字:{
       
       {name}}</div>
                    <div>学校地址{
       
       {address}}</div>
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "清华大学",
                    address: "北京"
                }
            }
        })
        // 学生组件
        const student = Vue.extend({
      
      
            name:"student",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "小明",
                    age: 21
                }
            }
        })
        // 老师组件
        const teacher = Vue.extend({
      
      
            name:"teacher",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "张老师",
                    age: 31
                }
            }
        })

        // 创建vm对象
        new Vue({
      
      
            el: "#root",
            
            // 2、注册组件
            components:{
      
      
                school,
                student,
                teacher
            }
        })
    </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述

  • 在一个组件中嵌套其他组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../../JS/vue.js"></script>
    <title>组件嵌套</title>
</head>

<body>
    <!-- 3、使用组件 -->
    <div id="root">
        <school></school>
    </div>
    <script>
        // 1、创建组件
        // 嵌套时需要先定义子组件,创建了子组件后,父组件才能将其注册

        // 学生组件(子组件)
        const student = Vue.extend({
      
      
            name:"student",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "小明",
                    age: 21
                }
            }
        })

        // 老师组件(子组件)
        const teacher = Vue.extend({
      
      
            name:"teacher",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "张老师",
                    age: 31
                }
            }
        })

        // school组件(父组件)
        const school = Vue.extend({
      
      
            name:"school",
            template: `
                <div>
                    <div>学校名字:{
       
       {name}}</div>
                    <div>学校地址{
       
       {address}}</div>
                    <student></student>
                    <teacher></teacher>
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "清华大学",
                    address: "北京"
                }
            },
            // 注册子组件
            components:{
      
      
                student,
                teacher
            }
        })
        
        // 创建vm对象
        new Vue({
      
      
            el: "#root",
            
            // 2、注册组件
            components:{
      
      
                school,
            }
        })
    </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述
打开开发工具同样也可以看到嵌套关系
在这里插入图片描述

注意点:
(1)使用嵌套时,子组件的创建需要在父组件创建之前,这样才能让子组件成功注册到父组件中形成嵌套关系
(2)在子组件注册到父组件后,一定记得要在父组件的template配置项中使用组件
(3)注册关系图如下:
在这里插入图片描述

  • 在vm下定义一个app组件,用来管理vm中的所有组件
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../../JS/vue.js"></script>
    <title>组件嵌套</title>
</head>

<body>
    <!-- 使用组件 -->
    <div id="root">
        <app></app>
    </div>
    <script>
        // 创建组件
        // 嵌套时需要先定义子组件,创建了子组件后,父组件才能将其注册

        // 学生组件(子组件)
        const student = Vue.extend({
      
      
            name:"student",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "小明",
                    age: 21
                }
            }
        })

        // 老师组件(子组件)
        const teacher = Vue.extend({
      
      
            name:"teacher",
            template: `
                <div>
                    <div>学生姓名:{
       
       {name}}</div>
                    <div>学生年龄:{
       
       {age}}</div>    
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "张老师",
                    age: 31
                }
            }
        })

        // school组件(父组件)
        const school = Vue.extend({
      
      
            name:"school",
            template: `
                <div>
                    <div>学校名字:{
       
       {name}}</div>
                    <div>学校地址{
       
       {address}}</div>
                    <student></student>
                    <teacher></teacher>
                </div>
            `,
            data() {
      
      
                return {
      
      
                    name: "清华大学",
                    address: "北京"
                }
            },
            // 注册子组件
            components:{
      
      
                student,
                teacher
            }
        })
        
        // 定义一个与school同级的组件
        const hello = Vue.extend({
      
      
            template:`
                <div>
                    <div>自强不息,厚德载物</div>    
                </div>
            `,
        })

        // 定义一个app组件,用来管理所有组件
        const app = Vue.extend({
      
      
            template:`
                <div>
                    <hello></hello>
                    <school></school>
                </div>
            `,
            components:{
      
      
                hello,
                school,
            }
        })
        // 创建vm对象
        new Vue({
      
      
            el: "#root",
            
            // 在vm中注册app组件
            components:{
      
      
                app
            }
        })
    </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 单文件组件

通常单文件组件不会单独出现,通常还会用到如下类型文件

  • 页面html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>单文件组件测试</title>
</head>
<body>
	<!--准备一个容器 -->
    <div id="root">
        <App></App>
    </div>
    <!-- 先让页面模板加载完再引入js文件 -->
    <!-- 先引入vue.js文件 -->
    <script src="../../../JS/vue.js"></script>
    <!-- 再引入入口文件 -->
    <script src="./main.js"></script>
</body>
</html>
  • main.js入口文件
// 引入vue
import vue from "vue"
// 引入App组件,这是所有组件的父组件
import App from "./app.vue"
// 创建vue实例
new Vue({
    
    
    el:"#root",
    // 注册App组件
    components:{
    
    
        App
    }
})
  • App.vue文件,管理所有组件
<template>
  <div>
      <Student></Student>
      <Teacher></Teacher>
  </div>
</template>

<script>
    // 引入组件
    import Student from "./Student";
    import Teacher from "./Teacher";
    // 暴露
    export default {
      
      
        name: "app",
        // 注册组件
        components: {
      
      
            Student,
            Teacher,
        },
    };
</script>

<style>
</style>
  • 其他单个单文件组件

Student.vue组件

<template>
  <!-- html代码,组件结构 -->
  <div>
    <div>学生姓名:{
   
   { name }}</div>
    <div>学生年龄:{
   
   { age }}</div>
  </div>
</template>

<script>

// 不做任何省略时
//#region 
/* 
export default student = Vue.extend({
    name: "student",
    data() {
        return {
        name: "小明",
        age: "21",
        };
    },
})
*/
//#endregion

// js代码,控制组件交互
export default {
      
      
  name: "student",
  data() {
      
      
    return {
      
      
      name: "小明",
      age: "21",
    };
  },
};
</script>

<style lang="">
/* css代码,组件样式渲染 */
</style>

Teacher.vue组件

<template>
  <div>
    <div>老师名字{
   
   { name }}</div>
    <div>老师年龄:{
   
   { age }}</div>
  </div>
</template>

<script>
export default {
      
      
  name: "teacher",
  data() {
      
      
    return {
      
      
      name: "张老师",
      age: 31,
    };
  },
};
</script>

<style>
</style>

注意点:
(1)在给单文件组件命名时,同样有如下规则,单个单词时,首字母可大可小,当多个单词时,要么单词全部小写,单词间用横杆‘-’隔开,要么单词首字母全部大写
(2)通常会定义一个App.vue组件来管理所有组件
(3)组件中也是可以通过template配置项来添加模板
(4)通过脚手架就可以一步将上面的文件全部创建好。

3、VueComponet构造函数

关于VueComponet:

  1. 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
  2. 当使用组件标签时,例如< school>< /school>,Vue解析时会帮我们创建school组件的示例对象,即Vue帮我们执行的:new VueComponent(options)
  3. 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent
  4. 组件中this的指向:
    (1)组件配置中:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this指向都是【VueComponent】
    (2)new Vue()配置中:
    data函数、methods中的函数,watch中的函数,computed中的函数,他们的this指向都是【vue实例】
  5. VueComponent的实例对象,可以简称vc(或者组件实例对象),vue中的实例对象简称vm。
  6. 组件实例对象和vue实例对象的区别
    虽然vm和vc对象很相似,vc中的配置vm中都有,但vm中有vc没有的,所以不能划上等号,有如下区别:
    (1)vm中可以使用el配置项来指定为那个容器服务,而vc中不能使用。
    (2)vm中的data配置项可以写成对象式,也可以写成函数式,而vc中的data只能写成函数式

4、Vue与VueComponent的内置关系

  • 一个重要的内置关系:VueComponent.prototype._proto_===Vue.prototype
    上面的等式说明:vc实例对象通过属性__proto__指向Vue这个原型对象。
  • 原因:
    使得组件实例对象(vc)可以访问到Vue原型上的属性、方法。
    如图:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lalala_dxf/article/details/125019253