组件的定义:实现应用中局部功能代码和资源的集合
代码包含:html、css、js 代码。
资源包含:各种图片、视频、音频、字体等资源文件。
非单文件组件:一个文件中包含有多个组件。( 一个a.html 文件中包含了多个组件)
用下图练习使用组件的过程:
常规实现代码:
<head>
<meta charset="UTF-8">
<title>基本使用title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>学校名称:{{ schoolName }}h2>
<h2>学校地址:{{ address }}h2>
<hr>
<h2>学生名称:{{ studentName }}h2>
<h2>学生年龄:{{ age }}h2>
div>
<script type="text/javascript">
Vue.config.productionTip = false
// 创建 Vue 实例对象 vm
new Vue({
el:"#root",
data:{
schoolName:"杭州电子科技大学",
address:"浙江杭州",
studentName:"张三",
age:22
}
})
script>
body>
根据页面结构,我们可以把学校的信息展示当做一个 school 组件,学生的信息当做另一个 student 组件来制作上图效果。
组件的创建与 Vue 实例对象 vm 的创建方式对比:
// 创建 school 组件
const school = Vue.extent({/* 配置对象 */})
// 创建 Vue 实例对象 vm
const vm = new Vue({/* 配置对象 */})
创建组件传入参数的配置对象和创建 Vue 实例对象 vm 传入参数的配置对象几乎一致。当我们把创建 Vue 实例对象 vm 传入的配置项直接复制到创建 school 组件的传入参数时,控制台会报两个错误:
const school = Vue.extent({
el:"#root", // 组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个Vue实例对象vm管理,由vm决定服务于哪个容器。
data:{
schoolName:"杭州电子科技大学",
address:"浙江杭州",
studentName:"张三",
age:22
}
})
1. el 配置项只能在 new Vue() 的配置对象中使用。el 是配置当前实例为哪个容器(div)服务的,当我们创建组件时,并不能确定该组件以后会用在什么地方,所以组件的创建不要写 el 配置项。
2. data配置项应该要写成一个函数,函数中返回数据对象。因为组件是会在多处使用的,通过函数返回组件数据对象的方式做到了不同地方引用的组件数据是相互独立的,操作互不影响。
正确的创建 school 和 student 组件,将组件中的结构 template 配置项也加入,template 配置项中只能有一个根元素。
const school = Vue.extend({
template:`
学校名称:{{ schoolName }}
学校地址:{{ address }}
`,
data() {
return {
schoolName: "杭州电子科技大学",
address: "浙江杭州",
}
}
})
const student = Vue.extend({
template:`
学生名称:{{ studentName }}
学生年龄:{{ age }}
`,
data() {
return {
studentName: "张三",
age: 22
}
}
})
局部注册:在一个 Vue 实例对象中注册组件,注册的组件只能提供给当前的 Vue 实例对象使用。
new Vue({
el:'#root',
// 组件注册配置项(局部注册)
components:{
xuexiao:school,
xuesheng:student
}
})
组件的注册可以在Vue 实例对象中通过 components 配置项去注册,配置项中用 {使用时的组件名:创建时的组件名, ...}
对象去注册组件。上例中把创建的 school 组件注册名为 xuexiao 的使用时组件名。
注意:一般注册的组件使用名和组件的创建名保持一致,且可以简写:
new Vue({
el:'#root',
// 组件注册配置项(局部注册)
components:{
school:school,
student // 简写
}
})
全局注册:在 Vue 的 component 属性上全局注册组件,注册的组件在所有的 Vue 实例对象上都可以使用 。
// Vue.component('使用时的组件名',创建时的组件名)
Vue.component('student',student)
<body>
<div id="root">
<school>school>
<hr>
<student>student>
div>
<script type="text/javascript">
Vue.config.productionTip = false
// 1.创建 school 组件
const school = Vue.extend({
template:`
学校名称:{{ schoolName }}
学校地址:{{ address }}
`,
data() {
return {
schoolName: "杭州电子科技大学",
address: "浙江杭州",
}
}
})
// 1.创建 student 组件
const student = Vue.extend({
template:`
学生名称:{{ studentName }}
学生年龄:{{ age }}
`,
data() {
return {
studentName: "张三",
age: 22
}
}
})
// 创建 Vue 实例对象 vm
new Vue({
el:"#root",
// 2.注册组件
components:{
school,
student
}
})
script>
body>
一、定义组件(创建组件)
使用 Vue.extend(options)创建,其中 options 和 new Vue(options)时传入的那个 options几乎一样,两点区别如下:
1. el 配置项不要写。------最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2. data 配置项必须写成函数。------ 避免组件被复用时,组件数据存在引用关系。
备注:使用 template 配置项可以配置组件结构。
二、如何注册组件
1. 局部注册:靠 new Vue 的时候传入 components 配置项注册。
2. 全局注册:靠 Vue.component(‘使用组件名’, 创建组件名) 注册。
三、使用组件标签:
组件使用名的命名规范
组件使用名由一个单词组成的
可以小写 school 或首字母大写 School ,因为 Vue 开发者工具里都会把组件名转成大写显示。所以很多开发人员习惯将一个单词的组件名写成首字母大写的形式,与开发工具显示对应,同时也与传统 HTML 标签做区分。
组件使用名由多个单词组成的
可以全小写 my-school ,中间用 ’ - ’ 连接。但局部注册组件是要写成 components{“my-school”:school} ,此时 Vue 的开发者工具里展示的是MySchool。
可以每个单词首字母大写MySchool。使用时也是
备注:
(1)组件使用名尽可能回避 HTML 中已有的元素名称,例如:h2、H2(h2会直接报错,H2会直接无效变成普通的h2标签)
(2)可以在创建组件时使用 name 配置项指定组件在开发者工具中呈现的名字。
组件的使用方式
(1)开始结束标签形式
(2)自闭合标签形式
创建组件的简写方式
const school = Vue.extend(options)
// 可简写为:
const school = options
组件的使用往往会出现嵌套关系,被嵌套的子组件需要注册到父组件中,使用也是在父组件的template配置项中使用。
一般开发都会有一个管理的 app 组件,管理其他所有实现功能的子组件,app 组件被唯一的 Vue 实例对象 vm 管理。
<body>
<div id="root">div>
<script type="text/javascript">
// 创建组件
const student = Vue.extend({
template:`
学生姓名:{{ name }}
学生年龄:{{ age }}
`,
data(){
return{
name:"张三",
age:18
}
}
})
// 打印组件
console.log(student);
// 创建 Vue 实例对象 vm
new Vue({
el:"#root",
template:` `,
components:{
student
}
})
script>
body>
VueComponent 是组件的构造函数。理论上构造函数的使用是 new VueComponent(options) 的形式。我们在使用组件时
vue 自动帮我们调用了 school 组件的构造函数 VueComponent()。
注意:所有定义组件都是返回一个全新的 VueComponent() 构造函数,在使用组件的时候都是调用对应的构造函数,只是名称一样而已。如下两个组件做验证:
<body>
<div id="root">div>
<script type="text/javascript">
Vue.config.productionTip = false
// 创建student组件
const student = Vue.extend({
template:`
学生姓名:{{ name }}
学生年龄:{{ age }}
`,
data(){
return{
name:"张三",
age:18
}
}
})
// 创建school组件
const school = Vue.extend({
template:`
学校名称:{{ name }}
学校地址:{{ address }}
`,
data(){
return{
name:"杭州电子科技大学",
address:"浙江杭州"
}
}
})
// 打印学生组件
console.log("学生组件:",student);
// 打印学校组件
console.log("学校组件:",school);
// 确认这两个组件是否相等
console.log("student===school??:",student === school);
// 创建 Vue 实例对象 vm
new Vue({
el:"#root",
template:`
`,
components:{
student,
school
}
})
script>
body>
我们可以在vue 源码中找到这个构造函数:
关于 VueComponent 知识汇总:
1、school 组件本质时一个名为 VueComponent 的构造函数,且不是程序员定义的,是 Vue.extend 生成的。
2、我们只需要写
或
,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)。
所有对象上都有 _proto_ 属性,指向缔造它的构造函数的原型对象。
所有的构造函数上都有 prototype 属性,指向自己的原型对象。
Vue 做了个重要的操作:将 VueComponent 构造函数的原型对象的原型对象指向了 Vue 构造函数的原型对象。这样做可以让组件实例对象(vc)可以访问到 Vue 原型上的属性、方法。