Vue 非单文件组件
非单文件组件:一个文件中包含N个组件;
单文件组件:一个文件中只包含有1个组件,以 XXX.vue 为组件文件,需要打包;
传统做法
<div id="root">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<hr>
<h2>学员姓名:{{studentName}}</h2>
<h2>学员年龄:{{age}}</h2>
</div>
只输出学校和学员信息;
new Vue({
el: '#root',
data: {
schoolName: '51cto',
address: '北京',
studentName: '小明',
age: 18
},
methods: {
stop() {
console.log("停止");
this.$destroy()
}
},
})
看效果:
把这个页面改造成组件形式:可以把学校和学员分别做成组件;
组件做法
组件做法分三步:创建组件,注册组件,使用组件;
<div id="root">
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<school></school>
<hr>
<!-- 第三步:编写组件标签 -->
<student></student>
<student></student>
</div>
提示1:注册完组件后,可以在模板区以标签的形式引用;
// 第一步:创建学校组件
const school = Vue.extend({
// 组件中,不用配置 el 项,最终都由 vm 管理
// template 配置组件里模板;
// 注意:template 里面只允许有一个根元素,所以加个 div
template: `
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
// data 用函数返回对象的方式
data() {
return {
schoolName: '51cto',
address: '北京',
}
}
})
// 第一步:创建学员组件
const student = Vue.extend({ // Vue.extend 可以省略
template: `
<div>
<h2>学员姓名:{{studentName}}</h2>
<h2>学员年龄:{{age}}</h2>
</div>
`,
data() {
return {
studentName: '小明',
age: 18
}
}
})
new Vue({
el: '#root',
// 第二步:注册组件
components: {
school: school,
student: student,
},
data: {
msg:'学习Vue组件'
},
})
第一步:创建组件
使用 Vue.extend() 方法来创建组件,组件中使用数据、模板、方法、监视等操作都和 vm 中的使用方法一样,只有几个小区别;
1)组件中,不配置 el 选项,最终都统一由 vm 管理;
2)配置模板,template 里,只能有一个根,本例中,要在外层套个 DIV,写成模板字符串的形成好编辑,在单文件组件开发中要使用插件来帮助高效编写模板;
3)data 数据要写成函数式,return 出对象,复用的时候彼此不受影响;
data 写成对象式:
let data={
a:1,
b:2
}
let x = data;
let y = data;
x.a = 100;
console.log(y.a); // 100
对象式写法,x.a 修改了对象值,也会影响到 y.a 的值;
data 写成函数式:
function data(){
return {
a:1,
b:2
}
}
let x = data();
let y = data();
x.a = 100;
console.log(y.a); // 1
用函数返回对象的写法,x.a 的值改变了,不影响 y.a 的值;
所以,函数返回 data 的方式,每次调用时,都会返回全新的对象;
第二步:注册组件
组件注册后,再把组件放在模板中才有效果;
注册组件,也分为 局部注册 和全局注册 ,局部注册使用的更多;
1)注册局部组件:
vm 实例中,使用 components:{}
选项来注册局部组件,写在 vm 实例的配置对象中跟 data 平级;
components: {
school: school,
student: student,
}
可以简写成:组件名和组件实例名字一样的时候;
components: {
school,
student,
}
2)注册全局组件:
注册全局组件后,该组件可以跳出嵌套在全局使用;
语法是 Vue.component('组件名',组件实例名)
Vue.component('school',school)
第二步:使用组件
使用组件名标签形式,在写在引用的位置;
注意:本例中,引用了两次 <student></student> 组件;
看下效果:
1)根组件下可以看到 三个组件 ;一个 school 和 两个 student 组件;
2)复用了 student 组件,单独修改组件中的数据:年龄,不影响复用的组件数据,这就是使用 函数式 定义数据属性的原因;
3)如果在 student 组件上,修改了功能,如添加了按钮点击事件,那么复用的组件上也会有这个功能;
使用“非单文件组件”的方式,在开发中不会使用的,在本例中,仅作为过渡讲解组件使用方法;
了解了“非单文件组件”的写法后,单文件组件的写法就一目了然了;
关注几个问题
Vue中使用组件的三大步骤:
1)定义组件(创建组件);
2)注册组件;
3)使用组件(写组件标签);
如何定义组件?
使用 Vue.extend(options)
创建,其中 options 和 new Vue(options)
时传入的 options 几乎一样,但也有点区别:
1) el 不要写,因为最终所有的组件都要经过 vm 管理,由 vm 中的 el 决定服务哪个容器;
2) data 必须写成函数,可以避免组件被复用时,数据存在的引用关系,
备注:使用 template 可以配置组件结构,但 结构中只能有一个根元素,通过会做一个容器在最外层;
如何注册组件?
1)局部注册:用 new Vue 的时候传入 components:{}
选项来配置;
2)全局注册:用 Vue.component(‘组件名’,组件实例名)
来注册;
组件命名:
组件名和组件实例名一般使用一个全部小写的单词,如: school ,student;
多个单词组成的组件名或组件实例名:
官方推荐使用 kebab-case 方式来命名组件名,如:my-school-info;
也可以使用 PascalCase (或叫大驼峰)方式来命名,如:MySchool(仅在脚手架环境中使用);
使用"-"短线方式命名,在注册组件时,要用 “” 引号引起来;
局部注册:
components: {
'my-school-info': school,
'school-student-info': student,
},
局部注册时简写:当组件名和组件实例名相同时,可以简写;
如果 组件名和组件实例名都是 : school 或 都是 student 时,那么在注册局部组件时,可以简定;
components: {
school,
student
},
全局注册:
Vue.component('my-school-info',school)
标签引用时:
<my-school-info></my-school-info>
【总结】:
关于组件名:
1)一个单词组成:
第一种写法是首字母小写: school ;
第二种写法是首字母大写: School ;
2)多个单词组成:
第一种写法是(kebab-case): my-school
第二种写法是(CamelCase): MySchool (需要 Vue 脚手架支架)
备注:
1)组件名尽可能回避HTML中已有的元素名称,例如:h2,H2都不行;
2)可以使用name配置项指定组件在开发者工具中呈现的名字(组件中使用个 name 属性中写一个);
const student = Vue.extend({
name:'mystudent'
})
这样写,不会影响组件引用,但是在 Vue DevTools 中会显示 mystudent;
关于组件标签:
第一种写法: <school></school>
第二种写法:<school/>
备注:不使用脚手架时,<school/> 会导致后续组件不能渲染;
一个简写方式:
const school = Vue.extend(options) 或以简写成: const school = options
const student = Vue.extend({
template: `
<div>
<h2>学员姓名:{{studentName}}</h2>
<h2>学员年龄:{{age}}</h2>
</div>
`,
data() {
return {
studentName: '小明',
age: 18
}
}
})
//可以简写成如下:
const student = {
template: `
<div>
<h2>学员姓名:{{studentName}}</h2>
<h2>学员年龄:{{age}}</h2>
</div>
`,
data() {
return {
studentName: '小明',
age: 18
}
}
}