11.Vue - 组件——组件名、非单文件组件、单文件组件

目录

一、 组件

1.1 了解组件

1.2 非单文件组件

1.2.1 使用步骤

1.2.2 效果图

1.3 组件嵌套

1.4 VueComponent

二、 非单文件组件总结

2.1 el 定义问题

2.2 data函数问题

2.3 注册组件方式

2.4 内置关系

2.4.1 铺垫知识

2.4.2 内置关系

2.5 总结

三、单文件组件


一、 组件

1.1 了解组件

传统方式编写应用

11.Vue - 组件——组件名、非单文件组件、单文件组件_第1张图片

组件方式编写应用

11.Vue - 组件——组件名、非单文件组件、单文件组件_第2张图片

组件:实现应用中局部功能代码和资源的集合

所有的组件都必须听大哥vm的指挥,并且组件可以产生嵌套

组件可以复用编码,简化项目编码,提高运行效率

11.Vue - 组件——组件名、非单文件组件、单文件组件_第3张图片

模块:一个模块也就是一个JS文件

模块化后可以复用JS,简化JS的编写,提高JS运行效率

模块化:应用中的JS都以模块来编写,那这个应用就是一个模块化的应用

一个JS文件太大,我们可以拆分成许多份,也就是模块化应用

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

一个组件太大,可以按照功能点拆成许多份,不同的功能点就是一个组件,这样就是一个组件化

Vue中组件有两种形式

  • 非单文件组件

    一个文件中包含n个组件

  • 单文件组件

    一个文件中只包含1个组件。文件名是a.vue而不是a.html,后缀名称发生了改变

1.2 非单文件组件

将下面的形式改成非单文件组件

    
    
       

学校名称:{{schoolName}}

       

学校地址:{{address}}

       
​        

学生姓名:{{studentName}}

       

学生年龄:{{age}}

   

data: {
       schoolName:'qilugongyedaxue',
       address:'济南',
       studentName:'zhangjingqi',
       age:18
}

11.Vue - 组件——组件名、非单文件组件、单文件组件_第4张图片

1.2.1 使用步骤

我们可以将学校信息创建为一个组件,将学生信息创建为一个组件

  1. 创建组件

    template是一个模板字符串,在使用template需要有一个根元素,我们一般设置为div标签

    
//创建school组件
    //Vue.extent扩展,创建组件的API
    //这个school不是组件名,只是一个中转的变量
    const school = Vue.extend({
        // 用div包裹,但是这个div最终不会出现在页面上
        template: `
                 

学校名称:{{schoolName}}

                 

学校地址:{{address}}

                                     
`       ,        data() { ​            return {                schoolName: 'qiludongyedaxue',                address: '济南',           }       },        methods: {            showName() {                alert(this.schoolName)           }       },   }) ​    // 创建student组件    //这个student不是组件名,只是一个中转的变量    const student = Vue.extend({        template: `
                       

学生姓名:{{studentName}}

                       

学生年龄:{{age}}

                     
`       ,        data() {            return {                studentName: '张三',                age: 18           }       }   })

  1. 局部注册组件

     
 new Vue({
            el:'#root',
            // 这个地方依然可以写数据,依然可以用
            data:{
 
            },
            // 注册组件(局部注册)
            components:{
                // 这个地方是key:value的形式,key是组件的名字 value就是我们上面定义的const,我们上面创建的const不是组件名,是我们中转的变量,下面的key才是组件名
                // school:school,
                // student:student
                // 下面是简写
                school,
                student
            }
     )}

  1. 编写组件标签

 
        
                         

               

我们代码中组件标签开头字母是小写,但是在Vue开发工具中是大写的

11.Vue - 组件——组件名、非单文件组件、单文件组件_第5张图片

1.2.2 效果图

11.Vue - 组件——组件名、非单文件组件、单文件组件_第6张图片

完整代码


​

​

    
    初始vue
​
    
    
​

​

    
                       

           

1.3 组件嵌套

在下图中,蓝色框和和橙色框中的组件就是嵌套,蓝色框组件嵌套了两个橙色框组件,并且有一个上下级关系

蓝色框称为父组件

橙色框称为子组件

11.Vue - 组件——组件名、非单文件组件、单文件组件_第7张图片

下面完成school组件嵌套student组件

也就是父组件school,子组件student



    
        
         初识vue
        
         
    
    
        
                   
             

我们上面定义的模式是vm组件管理app组件,然后app组件管理其他相关组件

11.Vue - 组件——组件名、非单文件组件、单文件组件_第8张图片

1.4 VueComponent

我们可以输出一下定义的组件

const school = Vue.extend({
            // 用div包裹,但是这个div最终不会出现在页面上
            // 嵌套了student组件
            template:`
                 

学校名称:{{schoolName}}

                 

学校地址:{{address}}

                                     
`           ,            data(){                                return{                 schoolName:'qilugongyedaxue',                 address:'济南',               }           },            components:{                // 注意!这里嵌套的时候有一个先后关系,一定要先创建student组件                student           }       }) ​ console.log('@',school)

发现是一个构造函数,组件的本质就是一个构造函数

11.Vue - 组件——组件名、非单文件组件、单文件组件_第9张图片

  1. school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的

    11.Vue - 组件——组件名、非单文件组件、单文件组件_第10张图片

  2. 我们只需要写,Vue解析时会帮我们创建school组件的实例对象

    即Vue帮我们执行的:new VueComponent(options)

  3. 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!

school与hello是两个VueComponent,只不过两个长得一样,功能也一样

11.Vue - 组件——组件名、非单文件组件、单文件组件_第11张图片

下面验证即可

console.log('@',school === hello)

image-20231113170354588

或者是通过下面的原码,每次创建组件的时候都是重新定义的一个变量Sub

11.Vue - 组件——组件名、非单文件组件、单文件组件_第12张图片

  1. 关于this的指向

  • 组件配置中

    data函数、methods中的函数、watch中的函数、computed中的函数,this指向的均是vc实例对象

  • new Vue配置中

    data函数、methods中的函数、watch中的函数、computed中的函数,this指向均是vm实例对象

vc和vm 的功能是一个样子的,也有数据代理

11.Vue - 组件——组件名、非单文件组件、单文件组件_第13张图片

  1. VueComponent的实例对象,以后简称vc,也可称为组件实例对象

组件是可复用的Vue实例,所以它们与new Vue 接收相同的选项,例如data、computed、watch、methods以及声明周期钩子等。

仅有的例外是像el这样跟实例特有的选项

vm能通过el决定为哪个容器进行服务,vc不能

二、 非单文件组件总结

2.1 el 定义问题

我们在使用Vue.extent创建组件的时候编写了el:'#root',这种情况是会报错的,

提示el仅仅被使用在实例身上并且使用new关键字调用的时候

    
const school = Vue.extent({
            // 用div包裹,但是这个div最终不会出现在页面上
            template:`
                 

学校名称:{{schoolName}}

                 

学校地址:{{address}}

                                     
`           ,            el:'#root',   //如果存在此语句的话,也会报错                    // 如果data写成这种形式会报错,只能写成函数的形式            data:{               schoolName:'qilugongyedaxue',               address:'济南',           } )}

image-20231113150828713

那我们不写el指定根容器,那怎么知道为谁服务

因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器

创建组件的时候从来不说组件为谁服务,组件就是一块砖,哪里需要往哪搬,最终为谁服务看大哥vm的指示

2.2 data函数问题

假如我们在非单文件组件中如下所示定义data,就会报错

data:{
    schoolName:'qilugongyedaxue',
    address:'济南',
}

image-20231113151444643

data(){
   return{
       schoolName:'qilugongyedaxue',
       address:'济南',
   }
}

为什么非要写成一个函数

是因为对象的引用关系。假如A组件和B组件同时引用了school组件,然后A组件中对schoolName进行修改,那B组件中引用的schoolName也会跟着修改,可能会导致B组件页面渲染发生问题

但是写成一个函数的形式,A组件和B组件之间修改就不会互相影响了。因为我们每次调用data的时候都是返回一个全新的对象

2.3 注册组件方式

组件的注册分为局部注册和全局注册

  • 局部注册

    这种方式使用的较多

   
 // 创建student组件
    const student = Vue.extend({
        template: `
                       

学生姓名:{{studentName}}

                       

学生年龄:{{age}}

                     
`       ,        data() {            return {                studentName: '张三',                age: 18           }       }   }) ​    new Vue({        el: "#root",        //这里面继续写配置也可以        data: {       },        components: {            school,            student       }   })

  • 全局注册

//1.创建hello组件
const student = Vue.extend({....})
​
//2.全局注册组件
// 参数1:组件的名字;
// 参数2:传入我们定义的组件
Vue.component('hello',hello)

2.4 内置关系

2.4.1 铺垫知识

无论是函数身上的显示原型属性还是实例对象身上的隐式原型属性,都指向原型对象

//定义一个构造函数
function Demo(){
   this.a = 1
   this.b = 2
}
​
// 创建一个Demo实例对象
const d = new Demo()
​
//Demo.prototype显示原型属性
// 我们通过Demo.prototype已经拿到原型对象了
console.log(Demo.prototype)
​
//此构造函数所缔造出来的实例对象有一个__proto__属性(前后两个下划线)
//隐式原型属性
console.log(d.__proto__)

程序员通过显示原型属性操作原型对象,追加一个x属性,值为99

//拿到原型对象后往其身上加了一个x属性为99
Demo.prototype.x=99

访问刚刚添加的x属性值

console.log(d.x)
//两种方式都可以 
console.log(d.__proto__.x)

Demo自身没有x,就会去隐式里面找,就会找到x

11.Vue - 组件——组件名、非单文件组件、单文件组件_第14张图片

并且下面的结果其实是true

console.log(d.__proto__ === Demo.prototype)

2.4.2 内置关系

VueComponent.prototype.__proto__===Vue.prototype

可以使用下面的代码验证一下我们的结论

下面分析Vue与VueComponent的关系

  1. 当我们使用下面语句后,Vue实例引入进来

Vue构造函数就位,config、component....是Vue身上的属性和方法

11.Vue - 组件——组件名、非单文件组件、单文件组件_第15张图片

  1. Vue身上还有一个prototype属性

    Vue的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第16张图片

之前在学习el两种写法的时候见过$mount函数

其实vm身上是没有$mount函数的,但是顺着隐式原型链__proto__就可以找到$mount函数

vm.$mount('#root')

  1. new Vue可以创建Vue原型对象,创建的vm实例一定会有一个隐式原型对象__proto__

11.Vue - 组件——组件名、非单文件组件、单文件组件_第17张图片

  1. Vue的原型对象也会有隐式原型属性,并且指向Object的原型对象

    实例的原型属性永远指向自己缔造者的原型对象

    Vue原型对象的缔造者是Object原型对象

    Vue的实例对象的缔造者是Vue的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第18张图片

  1. 同理VueComponent函数身上也会有一个prototype,并且指向VueComponent的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第19张图片

  1. 假如编写了一个组件标签,随后Vue就帮我们new了一个VueComponent的实例对象vc

11.Vue - 组件——组件名、非单文件组件、单文件组件_第20张图片

  1. vc也是一个实例对象,身上也会有隐式原型属性,并且指向自己的缔造者的原型对象,即指向VueComponent的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第21张图片

  1. 同理VueComponent的原型对象也会有隐式原型属性,并且指向自己缔造者的原型对象,但是Vue做了一件事,没有让VueComponent的原型对象的隐式原型属性指向Object的原型对象,而是让VueComponent的原型对象的隐式原型属性指向Vue的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第22张图片

  1. 图示总览

    总的来说就是,VueComponent的原型对象的原型对象就是Vue的原型对象

11.Vue - 组件——组件名、非单文件组件、单文件组件_第23张图片

为什么要这么折腾一圈呢

当放在Vue的原型对象一个属性x=99,那vc首先会在自己实例对象身上找,找不到的话就会在隐式原型对象上找,也就是VueComponent的原型对象

继续在VueComponent的原型对象上找,如果找不到的话会在隐式原型对象上找,也就是Vue原型对象,最终找到了

假如说在Vue原型对象上也没有找到,会继续在Object原型对象身上找

11.Vue - 组件——组件名、非单文件组件、单文件组件_第24张图片

2.5 总结

  • Vue中使用组件步骤

  1. 定义组件(创建组件)

  2. 注册组件

  3. 使用组件(写组件标签)


  • 如何定义一个组件

使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有差别

区别

  1. el不写。最终所有的组件都要经过一个vm管理,由vm中的el决定服务哪个容器

  2. data必须写成函数。避免组件被复用时,数据存在引用关系(比如a,b同时用了data数据,a改了数据,那b得到的数据就是a改了之后的数据)

备注:使用template可以配置组件结构


  • 关于组件标签

第一种写法:

第二种写法:

备注:

不使用脚手架时,会导致后续组建不能渲染


  • 关于组件名

一个单词组成

第一种写法(首字母小写):school

第二种写法(首字母大写):School

多个单词组成

第一种写法(kebab-case命名):my-school

第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

备注

1. 组件名尽可能回避HTML中已有的元素名称,例如:h2,H2都不可以

2. 可以使用name配置项指定组件在开发者工具中呈现的名字,如下所示

给组件添加一个name配置项即可,其他地方都不改变

    
                       

           

   // 创建student组件
    const student = Vue.extend({
        name:'zhangjignqi',
        template: `
                       

学生姓名:{{studentName}}

                       

学生年龄:{{age}}

                     
`       ,        data() {            return {                studentName: '张三',                age: 18           }       }   }), ​        new Vue({        el: "#root",        data: { '22'            // }       },        components: {            school,            student       }   })

11.Vue - 组件——组件名、非单文件组件、单文件组件_第25张图片


  • 注册组件的简写方式

const school =Vue.extend(options)

可以简写为下面所示代码:

直接编写配置对象

const school = options

三、单文件组件

单文件组件的后缀是.vue文件

但是怎么编译怎么运行,需要学习脚手架

创建文件的命名可以参考2.5总结中的内容

一个单词组成

第一种写法(首字母小写):school.vue

第二种写法(首字母大写):School.vue

多个单词组成

第一种写法(kebab-case命名):my-school.vue

第二种写法(CamelCase命名):MySchool.vue(需要Vue脚手架支持)

一般页面的编写需要html、css、js,Vue为了完成这些常见的属性,提供了一些标签