【vue系列-06】vue的组件化编程

一,vue组件

1,什么是vue组件

下图摘自官网,其底层主要是利用封装的思想,将一个大的组件拆分成多个小组件,并且在一个组件中一定会有一个vm的root根组件。组件和组件之间可以嵌套,组件就是实现应用中局部功能代码和资源的集合。代码主要有一些css,html,js等组成;资源主要由MP3,MP4,zip压缩包等文件组成。这样就可以实现代码复用,简化项目编码,提高开发和运行效率。

在这里插入图片描述

2,单文件组件和非单文件组件

二者区别

非单文件组件:顾名思义就是不是单文件组件,表示一个文件中包含有n个单文件组件。类似于一个大文件还没有拆分成多个小文件,全部聚集在一起,这样子的代码不容易维护,耦合性高,并且复用性低。

单文件组件:就是说一个组件中只包含一个文件。利用封装的思想,将组件从一个全部挤在一起的大型组件抽取出来,拆分成多个小组件,实现代码复用性高,更加的容易维护。

3,非单组件的基本使用

在创建组件时,和之前最原始的创建组件方式稍有不同,如果不是root根组件,其内部不需要el关键字,由于最终这个组件都是被vm的根节点所管理,因此其内部不需要el关键字,并且通过Vue.extend来创建非根组件,其内部的data元素只能用函数式,不能用对象式。其代码实现如下

<body>
    <!-- 一个容器,可以用于接收vue实力传来的数据,然后展示 -->
    <div id="root">
        <!-- 3,编写组件标签 -->
        <school></school>
        <student></student>
    </div>
    <script type="text/javascript" >
        Vue.config.productionTip = false   //阻止vue启动时提示生产提示
        const school = Vue.extend({
    
     //1,创建school组件
            template:`
                <div>
                    <h1>学校名称是:{
    
    {
    
    schoolName}}</h1>    
                    <h1>学校地址是:{
    
    {
    
    address}}</h1>
                </div>
            `,
            data(){
    
      //数据只能以函数式返回,不能以对象式
                return {
    
    
                    schoolName:'北京大学',
                    address:'北京'
                }
            }
        })
        const student = Vue.extend({
    
      //1,创建student组件
            template:`
                <div>
                    <h1>学生姓名是:{
    
    {
    
    studentName}}</h1>    
                    <h1>学生年龄是:{
    
    {
    
    age}}</h1>
                </div>
            `,
            data(){
    
        //数据只能以函数式返回,不能以对象式
                return {
    
    
                    studentName:'zhs',
                    age:18
                }
            }
        })
        //2,注册组件,局部注册
        new Vue({
    
    
            el:'#root',
            components:{
    
     //用于注册组件
                school,
                student
            }
        })
    </script>
</body>

总结来说就分三步,第一步就是创建组件,第二步就是注册组件,第三步就是编写组件标签到对应的父组件中。

如果组件需要变成全局组件,那么其第二步的注册组件的方式需要改成如下,这样这个book就变成了全局组件,在所有的vm中都可以使用。

Vue.component('book',book);

4,vue组件命名规范

4.1,一个单词组成

在官方文档中,如果是一个单词组成,那么可以直接使用这个单词作为组件名,也可以将这个单词的首字母大写之后再作为组件名。

Components:{
    
    
    school:'school; //方式一
    School:'school'; //方式二
}

4.2,多个单词组成

如果组件名是由多个单词组成的,那么可以全部让字母小写,单词与单词之间用一个 - 连接,也可以让多个单词直接使用大写字母拼接在一起(需要使用脚手架)。

Components:{
    
    
    `my-school`:'school;
    MySchool:'school'
}

并且在命名组件时,尽可能回避html中已有的元素名称,如h1,H1等都不行。并且在注册组件时,也可以简写将这个Vue.extend({}) 直接写成 {},如下。

const s = {
    
    ...}

虽然说这里并没有显示的调用这个 Vue.extend,但是底层源码是会将这个补上的。

5,组件与组件间的嵌套

如上面的school组件,是一个root根组件下面的子组件,现在又想在school组件中再注册一个组件,形成一个嵌套组件,那么其代码实现如下。这里暂时还没有用到脚手架,因此在定义这个组件时,这个幼儿园组件要在这个定义在这个学校的前面,然后需要将子组件注册到这个父组件中,要和谁嵌套就将谁注册哪个组件中。

//定义一个幼儿园组件,实现和学校的嵌套,这里使用简洁式,省去Vue.extend
const kindergarten = {
    
    
    template:`
        <div>
            <h1>学校名称是:{
    
    {
    
    schoolName}}</h1>    
            <h1>学校地址是:{
    
    {
    
    address}}</h1>
        </div>
    `,
    data(){
    
    
        return {
    
    
            schoolName:'幼儿园',
            address:'深圳南山区'
        }
    }
}
//1,创建组件
const school = Vue.extend({
    
    
    template:`
        <div>
            <h1>学校名称是:{
    
    {
    
    schoolName}}</h1>    
            <h1>学校地址是:{
    
    {
    
    address}}</h1>
            <kindergarten></kindergarten>
        </div>
    `,
    data(){
    
    
        return {
    
    
            schoolName:'北京大学',
            address:'北京'
        }
    },
    components:{
    
    
        kindergarten,kindergarten
    }
})

6,VueComponent组件

上面的这个school的组件的本质,其就是一个名为Component的构造函数,由Vue.extend所生成。即在写school这个标签时,vue解析时就会创建这个school的组件的实例对象,即执行如下语句

new VueComponent(options)

在每次调用Vue.extend的时候,返回的都是一个全新的组件对象。其实这个用java理解也很简单,就是new出来的东西不会是同一个东西。如下,其实这两个东西并不相等

const a1 = new A();
const a2 = new A();

而且通过vue的源码也可以发现,每次这个sub对象都是一个全新的对象,因此也可以得知每次返回的都是一个全新的组件对象。

Vue.extend = function (extendOptions) {
    
    
    var Sub = function VueComponent(options) {
    
    
        this._init(options);
    };
    return Sub;
}

VueComponent的实例对象,也可以简称为vc,也可以称为组件实例对象。并且在这个vue的实例对象vm中,管理着一个个vc对象。

7,Vue和VueComponent的关系

7.1,Vue的原型对象

在引入这个vue.js之后,那么这个Vue组件的对象就有了,并且一定会有一个属性名为prototype,这个值就是对应的原型对象 ,那么这个vue原型对象上面的所有的这个函数,都可以被实例对象直接使用了。

而这个直接引入js所生成的vue对象,这个对象中有一个显示属性prototype,而直接通过new关键字构造出来的实例对象也一定会有一个隐式的__property__属性,那么这个实例对象也会通过这个属性直接指向这个Vue的原型对象。

由于这个实例的隐式属性,永远指向自己的缔造者的对象。这个原型对象也是一个对象,那么肯定也会指向自己的缔造者的对象,因此可知这个vue的原型对象的这个隐式属性 __property__,指向的就是自己的制造者对象Object。
在这里插入图片描述

7.2,VueComponent的原型对象

这个VueComponent和这个Vue的底层逻辑是一样的,VueComponent这个组件的原型对象一定会有一个显示属性prototype,该值一定是指向他的缔造者对象;这个VueComponent的实例对象也一定会有一个隐式属性 __property__,该值指向的肯定也是他的缔造者对象,即VueComponent的原型对象。

但是这个VueComponent的原型对象和vue的原型对象不一样,vue的原型对象是直接指向Object对象,但是这个VueComponent的原型对象实例加了一层,是将这个VueComponent的原型对象的隐式属性指向Vue的原型对象,(21:57),

在这里插入图片描述

通过上图可知,VueComponent这个组件就是想让这个Vue的原型对象做一个兜底,首先去VueComponent的原型对象上找东西,没有的话再去VueComponent的原型对象上找东西,没有的话再去Vue的原型对象上找东西,没有的话再交给Object的原型对象。

这样做的好处就是:让组件实例对象(vc)也可以访问到Vue原型上的属性和方法

VueComponent.prototype.__proto__ === Vue.prototype

而这个组件实例对象可以近似的认为就是一个小的vm,就是一个vue的实例对象,不同点就是这个vc不能用这个el属性,并且他的data只能写函数式,不能用对象式。

8,单文件组件

上面说了这么多都是在聊多文件组件,接下来主要理解一下什么时单文件组件。在此之前,需要先安装一个插件,这个推荐使用 vetur 这个插件。在安装完插件之后,新建一个.vue的文件,然后其结构主要如下,分别是由组件的结构,组件交互相关的代码(数据,方法等等),组件的样式等组成。在安装了这个插件之后,直接< + 回车就可以出现以下代码。

<template>
    <div>
        <!-- 组件的结构 -->
    </div>
</template>

<script>
	export default {
    
    
    	//组件交互相关的代码   
	}
</script>

<style>
    /* 组件的样式 */
</style>

8.1,单文件组件的实现

那么接下来就根据这个多文件中的school和Student的这两组件,用这个单文件实现一下,主要会定义一些Student.vue,School.vue,App.vue,main.js,index.js,其步骤如下:

1,School.vue

这里主要编写一些关于学校的样式,数据结构个数据交互

<template>
    <div>
        <h1>学校姓名是:{
    
    {
    
    name}}</h1>    
        <h1>学校地址是:{
    
    {
    
    address}}</h1>
    </div>
</template>

<script>
    export default {
    
    
        name:'School',
        data(){
    
    
            return{
    
    
                name:'',
                age:''
            }
        }
    }
</script>

<style>
</style>

2,Student.vue

<template>
    <div>
        <h1>学生姓名是:{
    
    {
    
    name}}</h1>    
        <h1>学生年龄是:{
    
    {
    
    age}}</h1>
    </div>
</template>

<script>
    export default {
    
    
        name:'Student',
        data(){
    
    
            return{
    
    
                name:'',
                age:''
            }
        }
    }
</script>

<style>
</style>

3,App.vue

这个组件主要是作为一个汇总组件,将其他的所有的子组件汇总到该组件中。

<template>
    <div>
        <!-- 引入组件 -->
        <School></School>
        <Student></Student>
    </div>
</template>

<script>
    //引入组件
    import School from './School.vue'
    import Student from './School.vue'
    export default {
    
    
        name:'App',
        components:{
    
    
            School,
            Student
        }
    }
</script>

<style>
</style>

4,main.js

import App from './App'

new Vue({
    
    
    el:'#root',
    template:`<App></App>`,
    components:{
    
    
        App
    }
})

5,index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue的单文件组件学习</title>
</head>
<body>
    <!-- 根组件 -->
    <div id="root"></div>
    <!-- 先引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script> 
    <!-- 再引入main.js -->
    <script type="text/javascript" src="./main.js"></script>
</body>
</html>

这样就就完全的通过单文件代替多文件的编写了,当然这里只是一个初步的示例,具体的还得安装脚手架来跑通整个流程

<title>Vue的单文件组件学习</title>
```

这样就就完全的通过单文件代替多文件的编写了,当然这里只是一个初步的示例,具体的还得安装脚手架来跑通整个流程

猜你喜欢

转载自blog.csdn.net/zhenghuishengq/article/details/128706399