1.组件
- 组件定义:
一个组件就是一个功能体,内部封装了数据和方法,集成了html、css和js。
每个组件都是Vue的实例对象。
- 组件优点:
封装可复用的代码
- 组件与模块化区别:
组件化:主要从ui界面上进行划分。例如前端的组件化,方便ui组件的调用。
模块化:主要从代码逻辑的角度进行划分,方便代码分层开发,保证每个功能模块职责单一。
- 组件分类:
- 非单文件组件(.html)
- 单文件组件(.vue)
2.非单文件组件 (.html)
1、Vue中使用组件的三大步骤:
- 一、定义组件(创建组件)
- 二、注册组件
- 三、使用组件(写组件标签)
2、如何定义一个组件?
-
1.使用
Vue.extend(options)
创建,其中options和new Vue(options)传入的options几乎一样,区别如下:- 1.el 不能写:组件不单为谁而服务,可以用在任何地方。
- 2.data必须写成函数,为什么?
组件被复用时,data就被复制一份,对象间的复制传递的是引用,修改一个实例的属性,其他被复制的实例数据也会受到影响。 若是函数,每次复用调用函数会获得一个新对象,保证了数据的独立,互不干扰。 简单来说避免组件被复用时,数据存在引用关系.
- 3.配置组件结构:使用
template
,只是过渡,真实开发不用。- template:' ' 写单行html结构
- template:`` 写多行html结构
- template 中必须有一个根节点,template不渲染自身标签
-
2.注册组件
- 1.局部注册:在
new Vue
的时候传入components:{}
选项 - 2.全局注册:使用
Vue.component('组件名',引用的组件)
- 1.局部注册:在
-
3.使用组件标签:
-
[脚手架专用,不使用脚手架导致后续组件无法渲染]
3、组件几个注意点:
- 1、注册名命名(注册名和使用标签始终是对应的)
- 1个单词
- 纯小写,使用标签也是纯小写
- 首个字母大写,使用标签也是首字母大写(跟开发者工具呼应)
- 多个单词
- kabab-case:全小写中间用-
my-school
,使用标签同样对应, - CamelCase每个单次首字母大写,
MySchool
,使用标签同样对应,
[脚手架专用]
- kabab-case:全小写中间用-
- 备注:
- 1.禁止使用html已有标签名作为注册组件名
- 2.关于name
- 若定义组件时指定了name,则开发者工具使用name作为呈现的名字,首字母依旧会大写
- 若定义组件时未指定name,则开发者工具使用注册的组件名作为呈现名字,首字母大写
- 1个单词
- 2、关于组件标签
-
[自闭合标签脚手架专用]
- 3、一个简写形式
-
const school = Vue.extend(options)
生成并返回VC构造函数,再拿过来用- 显示使用Vue.extend会立即生成并返回VueComponent构造函数。注册components对象只是做了引用,页面使用标签时(页面渲染)再new实例化(页面会传不同参数)
-
const school = options
用的时候再调用Vue.extend生成并返回VC构造函数,再拿过来用- 创建school时只是对象,注册componnets引入对象,在页面使用组件标签时再判断对象或VC构造函数,对象再调用Vue.extend,然后实例化
-
4、组件的定义和使用
// 1、创建组件
//显示使用Vue.extend会立即生成并返回VueComponent构造函数
//components对象只是做了引用,页面使用标签时(页面渲染)再new实例化
const s = Vue.extend({
name:'',//组件名称
//模板结构
template:`
你好{{msg}}
`,
data(){
return{
msg:'tom'
}
}
})
备注:
1.配置对象与new Vue()传入对象几乎一致,区别有两点:
- 1.el属性不能写,因为组件不属于谁,vm可以将其用在任何处,而el只能用于new创建的实例身上。
- 2.data对象要用函数返回,否则报错。vue这样设计的原因是,对象传递的是引用,修改组件会影响到其他组件。而函数返回{},就是返回一个新对象,组件内可以维护自己的私有变量。
2.非单文件html中,模板结构只能写template,只是过渡,真实开发不用。
template:'' //写单行html结构
template:`` //写多行html结构
template:'' //template中必须有一个根节点,template不渲染自身标签
// 2、注册组件
// 局部注册
new Vue({
el:'#root',
components:{
school // school:school的简写:注册的名字和引用的变量同名可以使用 school:school
school:s //school为注册的组件名字,s为中转变量
},
})
//全局注册
Vue.component('school',s)//school:注册的组件名,s:引入的中转变量
3.组件嵌套
- 嵌套
- 组件注册给谁了,就在谁那使用
- 引出app概念
- 一般采用app管理所有组件,vm只管理app组件,app是vm之下,组件之上
- template
- template里必须有一个根节点,vm中使用template会覆盖el挂载的节点
//定义student组件
const student = Vue.extend({
name:'student',
template:`
{{name}}
`,
data(){
return {
age:18
}
}
})
//定义school组件,school中引入子组件student
const school = Vue.extend({
name:'school',
template:`
学校名称:{{name}}
`,
data(){
return {
name:'大学'
}
},
components:{
student //注册组件(局部)
}
})
//定义hello组件
const hello = Vue.extend({
template:`{{msg}}
`,
data(){
return { msg:'hello!' }
}
})
//定义app组件
const app = Vue.extend({
template:`
`,
components:{
school,hello
}
})
//创建vm
new Vue({
//注意,vm使用template显示内容,会替换掉root的div
//如果在div里使用组件标签,则包含root的div
template:' ',
el:'#root',
components:{app} //注册组件(局部)
})
5.VueComponent
1.
Vue.extend
调用后生成并返回一个名为VueComponent
的构造函数,school组件实际就是VueComponent的构造函数。2.我们只需要写
或
,Vue解析时会帮我们创建school组件的实例对象,
即Vue执行:new VueComponent(options)
,携带传给子组件的传参option。3.特别注意:
每次调用Vue.extend
,返回的都是一个全新的VueComponent
!因为代码里是var sub,每次都生成一个新的函数-
4.组件执行的原理总结:
- 1、Vue.extend生成返回不同的构造函数作准备。
- 2、数据改变引起模板解析。模板解析时,寻找components对象的组件引用,
- 若是构造函数传递不同参数实例化对象;
- 若是对象,调用Vue.extend返回构造函数再实例化
-
5.关于this指向:
- (1).组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。 - (2).new Vue(options)配置中:
data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
- (1).组件配置中:
6.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
6.一个重要的内置关系
- 一个重要的内置关系:
VueComponent.prototype.__proto__ === Vue.prototype
- 为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
- vm与vc区别在于,vc不能传el属性,且vc的data必须函数式返回对象,其他都一样。
防止组件被多次引用时数据存在引用关系
//创建一个Demo的实例对象
const d = new Demo() //构造函数
console.log(Demo.prototype) //构造函数的原型对象,也叫显示原型属性
console.log(d.__proto__) //实力对象的原型对象,也叫隐式原型属性
console.log(Demo.prototype === d.__proto__) // 指向同一对象
Vue.prototype === vm.__proto__ //vue构造函数原型对象也是实力对象的原型对象
vm.__proto__.__proto__ === Vue.prototype.__proto__ === Object //vue原型对象是继承自object
VueComponent.prototype.__proto__ === Vue.prototype
//VueComponent原型对象是继承自vue原型对象,所以VueComponent原型对象的原型对象是vue的原型对象
//这样VueComponent组件就有了vue的方法和属性
7.单文件组件 (.vue)
-
1、命名
- school my-school
- School My-School 好处是与开发者工具呈现呼应
- name最好与文件名一致
2、.vue文件
3、针对html、js、css,vue设计了