定义 实现应用中局部功能代码和资源的集合 为什么要用组件化编程? 传统方式编写:依赖关系混乱,不好维护,且代码复用率不高 模块化编写:只关注解决js,复用js,简化js的编写与效率 组件方式编写:好维护、复用率更高、提高运行效率

在组件出现之前,我们开发基本都是用html、js、css,

1 组件

单文件组件

一个文件中只有1个组件

非单文件组件

一个文件中包含有n个组件

1.1 组件使用流程

1 创建组件

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

1 不写el。最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器 2.data必须写成函数。避免组件被复用时,数据存在引用关系,data是对象会导致,组件值改变会影响另一个组件的值

使用template可以配置组件结构。 在Vue2官网中中也明确规定,组件的data必须是一个函数 在这里插入图片描述

const School = Vue.extend({
        name:'School', // 组件名
        template:`<div>School----</div>`,
        data(){
            return{}
        },
        methods:{}
})

2 注册组件

const vm = new Vue({
        el: '#root',
        components:{School},
        data() {
            return {
            }
        },
        
    })

3 使用组件

<div id="root">
   <School></School>
</div>

1.2 组件细节点

1.关于组件名:

  • 单个单词组成: 第一种写法(首字母小写):school 第二种写法(首字母大写):Schoo1
  • 多个单词组成: 第一种写法(kebab-case而名): my-school(不建议如此) 第二种写法(CamelCase命名): Myschool (需要Vue脚手架支持)

(1).组件名尽可能回避HTML中已有的元素名称,例如: h2、H2都不行。 (2).可以使用name配置项指定组件在开发者工具中呈现的名字。 2.关于组件标签: 第一种写法: < school></ schoo1> 第二种写法: < school/> (不用使用脚手架时,< schoo1/>会导致后续组件不能渲染) 3 简写方式: const school = Vue.extend(options) 可简写为: const school = options

1.3 关于VueComponent

1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的 2.只需要写< school/>或< school></ school>,Vue解析时会帮我们创建school组件的实例对象。 即Vue帮我们执行的:new VueComponent(options) 3.特别注意: 每次调用Vue.extend,返回的都是一个全新的VueComponent!!!! 4.关于this指向:

(1).组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均指向[VueComponent实例对象] (2).new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均指向[Vue实例对象]。 5.VueComponent的实例对象,可称之为: 组件实例对象。 vue的实例对象,一般都简称为vm。

2 Vue与VueComponent的关系(内置关系)

在了解Vue与组件的关系之前,我们要先了解一下原型链 原型 原型又分为显式与隐式 显式:每一个类(构造函数)都有一个显式原型 prototype(对象) 隐式:每一个实例化对象都有一个隐式原型 proto(对象)

    function getObj(){
        this.a = 1
        this.b = 2
    }
    // 打印出该对象的所有属性和属性值
    console.dir(getObj)
    const obj = new getObj() // 创建实例
    console.log('实例的原型',obj.__proto__)
    console.log('构造函数原型是否等于实例的原型',obj.__proto__ === getObj.prototype)

在这里插入图片描述 console.dir:打印出该对象的所有属性和属性值 实例的原型__propto等于构造函数的原型prototype vm.__propto === obj.prototype

Vue与组件的关系

正常来说一个构造函数的实例 实例的的原型__proto__指向 = 构造函数的原型对象

通过构造函数创建一个实例,顺着实例的原型链向上查找,发现最终指向的是Object构造函数的原型对象

graph LR
A[实例] -- __proto__--> B[原型对象]
B --__proto__--> C[Object的原型对象]
function getObj(){
        this.a = 1
        this.b = 2
    }
    const d = new getObj() // 创建实例
    console.log('隐式实例',d)

在这里插入图片描述 如果不引入Vue实例的原型链,应该如上所示,但是引入Vue后。Vue对VueCompomnent的原型队形的 __proto__指向进行了修改,指向了Vue的原型对象 在这里插入图片描述

3 单文件组件

使用命令好之前请把环境配置好:node、npm或yarn、vue-cli 低版本的vue可以匹配高版本的vue-cli 反过来就会失败 命令行创建一个Vue项目

vue create 项目名

创建完成根据提示运行项目yarn serve 在这里插入图片描述 封装组件 helloWorld.vue 在这里只有hellWorld.vue一个文件,就将组件实现了,这个组件就是一个单文件组件

<template>
  <div class="hello">
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
  </div>
</template>

<script>
// 完整的组件注册写法,注册完成后,将组件暴露出去,方便
// import Vue from 'vue'
// const HelloWorld = Vue.extend({
//   name: 'HelloWorld',
//   props: {
//     msg: String
//   }
// })
// export default HelloWorld

// 实际开发中会省略extend的
export default {
  name: 'HelloWorld', // 组件中的name值尽量都要写,防止用户随意更改组件名
  props: {
    msg: String
  }
}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

组件注册到App.vue文件中使用,App.vue注册到main.js文件中使用 每一个.vue文件都相当于一个组件,最终都由main.js去new Vue,其他组件就不需要单独的去new Vue了

graph LR
A[组件] -- 注册 --> B[App.vue]
B --注册--> C[main.js]

Tips:

组件命名:School.vue 或 MySchool.vue 每一个组件都相当于一个小型的VM,组件间不会互相影响