文章目录
为什么使用组件化开发
传统的编写模式
组件化的编写模式
每个组件拥有自己的html片段(不是完整的html),css和js
。
- 所有组件都有vm进行指挥
- 组件也可以嵌套
几个定义
模块
模块定义:模块即向外提供特定功能的js程序,一般一个模块就是一个js文件
模块作用: 复用js,简化js的编写,提高js运行效率
模块化
当应用中的js
都以模块
来编写的,那这个应用就是一个模块化的应用。
将一个大的js拆分成多个小的js以实现模块化
组件的定义
组件是实现应用中局部
功能代码
和资源
的集合
代码
:html、css、js
资源
:mp3 mp4 ttf .zip
局部
:将所有功能写在一个组件中是没有意义的所以要分开写。
组件的作用:复用编码,简化项目编码,提高运行效率
组件化
当应用中的功能都是多组件
的方式来编写的,那这个应用就是一个组件化的应用。
将应用按功能点拆分,一个功能就是一个组件。
组件中的js也可以拆分成多个js,实现js的模块化。
组件的编写
非单文件组件
一个文件中包含有n个组件。
一个html文件中可以包含多个组件
组建的编写需要分成3步:创建组件、注册组件
创建组件
使用Vue.extend({配置对象})
创建,其中配置对象和new Vue(options)时传入的那个options几乎一样,但也有点区别。
区别如下:
el不要写
。最终所有的组件都要经过一个vm的管理
,由vm中的el决定服务哪个容器。
组件就是一块砖,哪里需要哪里搬- data必须写成
函数
。避免组件被复用时,数据存在引用关系。
即如果data是一个配置对象,那么如果该组件被多个html引用,那么多个html的该组件的data是指向同一个对象的,则只要一个html改变data值,其他所有的html页面的该data值也改变,这样不好。
定义组件时,要把组件中html对应的内容写在template
中。使用template配置组件结构。
eg:
// 创建school组件
const school = Vue.extend({
// el: "#root",不要写el配置项,由vm决定该组件给谁用
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
注册组件
注册局部组件
在vue实例中注册组件,靠new Vue的时候传入components选项
new Vue({
components:{
组件名:定义的组件
}
});
eg:
const vm = new Vue({
el: "#root",
components:{
school:school
}
});
注册全局组件
局部注册是说,只有在vue实例中注册该组件,才能使用该组件,不注册就不能使用。
那如何不在vue实例中注册就可以使用组件呢?——全局注册
全局注册靠Vue.component('组件名',组件位置)
eg:
Vue.component("school", school);
使用组件
在html中编写组件标签<school></school>
<div id="root">
<school></school>
</div>
例子
局部注册:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
<hr />
<student></student>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建school组件
const school = Vue.extend({
// el: "#root",不要写el配置项,由vm决定该组件给谁用
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
const student = Vue.extend({
// el: "#root",不要写el配置项,由vm决定该组件给谁用
data() {
return {
studentName: "🐏",
age: 18,
};
},
template: `
<div>
<h2>名字:{{studentName}}</h2>
<h2>年龄:{{age}}</h2>
</div>`,
});
const vm = new Vue({
el: "#root",
// 第二步,注册组件
components:{
school:school,
student:student,
}
});
</script>
</body>
</html>
全局注册:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<h2>实例1:</h2>
<div id="root">
<school></school>
<hr />
<student></student>
</div>
<h2>实例2:</h2>
<div id="root2">
<school></school>
<hr />
<student></student>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建school组件
const school = Vue.extend({
// el: "#root",不要写el配置项,由vm决定该组件给谁用
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
const student = Vue.extend({
// el: "#root",不要写el配置项,由vm决定该组件给谁用
data() {
return {
studentName: "🐏",
age: 18,
};
},
template: `
<div>
<h2>名字:{{studentName}}</h2>
<h2>年龄:{{age}}</h2>
</div>`,
});
// 第二步,注册组件(全局注册)
Vue.component("school", school);
Vue.component("student", student);
const vm = new Vue({
el: "#root",
// 第二步,注册组件
// components:{
// school:school,
// student:student,
// }
});
new Vue({
el: "#root2",
});
</script>
</body>
</html>
vue开发者工具
组件的名称在vue开发者工具中首字母自动变成大写
单文件组件
一个文件中只包含有1个组件。
- 该文件名的后缀就是
.vue
.vue
文件格式
<template>
<!-- 组件的结构 -->
</template>
<script>
// 组件交互的代码(数据、方法)
</script>
<style>
/* 组建的样式 */
</style>
- 组件一般需要暴露出去
- 可以将
Vue.extend()省略
,直接将组件的配置对象暴露出去
eg:
// 组件交互的代码(数据、方法),相当于非单文件中的除了template的配置
<script>
// export default Vue.extend(
// {
// name:'School',
// data() {
// },
// })
export default {
name:'School',
data() {
},
}
</script>
单文件组件的编写
- 先编写一个组件School组件
School.vue
<template>
<!-- 组件的结构,相当于非单文件中的 template配置-->
<div class="demo">
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{ address }}</h2>
</div>
</template>
<script>
// 组件交互的代码(数据、方法),相当于非单文件中的除了template的配置
export default {
name:'School',
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
}
</script>
<style>
/* 组建的样式 */
.demo{
background: orangered;
}
</style>
- 定义app.vue汇总所有的组件
app.vue的作用:
app.vue:
<template>
<div>
<School></School>
<Student></Student>
</div>
</template>
<script>
//引入组件
import School from './School'
import Student from './Student'
export default {
name: 'App',
components: {
School,
Student
}
}
</script>
<style>
</style>
- 创建vm
在main.js中创建 vue实例对象
main.js
import App from './App.vue'
new Vue({
el: "#root",
// template:`<App></App>`,
components:{App}
})
- 创建容器
创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="#root">
<App></App>
</div>
<!-- 引入vue -->
<script type='text/javascript' src='../../js/vue.js'></script>
<!-- 引入main.js -->
<script type='text/javascript' src='./main.js'></script>
</body>
</html>
这样就完成了一个单文件组件的编写。
单文件组件的目录结构:
脚手架概念引入
.vue文件在浏览器是不能直接解析的,需要编译加工成.js文件。编译的方法有两种:一种是通过webpack等工具我们手动编译,另一种方式是利用vue提供给我们的脚手架进行编译(对webpack等工具的封装),我们一般采取脚手架方式。
组件的注意点
组件名
- 一个单词的组件名:都小写,或者首字母大写。
eg:school,School - 多个单词组成:都小写(当成一个单词处理),或者使用
'单词-单词'
的格式
eg:
components:{
'my-school':school,
}
vue开发者工具:
也可以使用大驼峰式直接为组件命名,但是有一个前提是使用脚手架。
- 组件名尽可能回避HTML 中已有的元素名称,例如: h2、H2都不行。
- 可以使用
name配置项
在组件定义时指定组件在开发者工具中
呈现的名字
eg:
const school = Vue.extend({
name: "xuexiao",
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
组件标签
第一种写法:<school></school>
第二种写法: <school/>
备注:不用使用脚手架时,<school/>
会导致后续组件不能渲染。
组件定义的简写
一个简写方式:
const school = Vue.extend(options)
可简写为:const school = options
组件的嵌套
基本嵌套
组件中还可以定义组件以实现组件的嵌套。
如在school中嵌套student只需在school中定义components配置项
,里面配置student组件,
同时student组件的使用也需要在school的 template中使用。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>欢迎</h2>
<school></school>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建student组件
const student = Vue.extend({
data() {
return {
studentName: "yang",
age: "18",
};
},
template: `
<div>
<h2>学校名字:{{studentName}}</h2>
<h2>地址:{{age}}</h2>
</div>`,
});
// 创建school组件
const school = Vue.extend({
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
<student></student>
</div>`,
components:{
student: student,
}
});
const vm = new Vue({
el: "#root",
data: {
msg: "欢迎!",
},
// 第二步,注册组件
components: {
school: school,
},
});
new Vue({
el: "#root2",
});
</script>
</body>
</html>
app组件
app组件用于管理所有组件,app组件和vm的关系
VM只需管理app一个组件,由app管理所有组件。
app组件:一人之下万人之上。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<app></app>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建student组件
const student = Vue.extend({
data() {
return {
studentName: "yang",
age: "18",
};
},
template: `
<div>
<h2>学校名字:{{studentName}}</h2>
<h2>地址:{{age}}</h2>
</div>`,
});
// 创建school组件
const school = Vue.extend({
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
<student></student>
</div>`,
components:{
student: student,
}
});
// 创建hello组件
const hello = Vue.extend({
data() {
return {
hello:"hello,你好"
};
},
template: `
<div>
<h2>{{hello}}</h2>
</div>`,
components:{
student: student,
}
});
// 创建app组件
const app = Vue.extend({
template: `
<div>
<hello></hello>
<school></school>
</div>
`,
components: {
school:school,
hello:hello,
},
})
const vm = new Vue({
el: "#root",
data: {
msg: "欢迎!",
},
// 第二步,注册组件
components: {
// 简写
app
},
});
new Vue({
el: "#root2",
});
</script>
</body>
</html>
VueComponent
组件是什么数据类型的呢?是一个名为VueComponent的构造函数。
const school = Vue.extend({
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
console.log(school);
- 组件本质是一个
名为VueComponent的构造函数
,且不是程序员定义的,是Vue .extend生成的。 - 我们只需要写
<school/>
或<school></school>
,Vue解析时会帮我们创建school组件的实例对象,即vue帮我们执行的:new VueComponent(options)
。options就是我们在组件中写的配置对象。 - 特别注意:每次调用
Vue.extend
,返回的都是一个全新的VueComponent
!!!
验证:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
<hello></hello>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 创建school组件
const school = Vue.extend({
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
</div>`,
});
// 创建school组件
const hello = Vue.extend({
data() {
return {
hello:"你好呀"
};
},
template: `
<div>
<h2>{{hello}}</h2>
</div>`,
});
console.log(school===hello);
const vm = new Vue({
el: "#root",
// 第二步,注册组件
components: {
school: school,
hello:hello,
},
});
</script>
</body>
</html>
console.log(school===hello);
输出:
组件中this指向
(1)组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【VueComponent实例对象】
。
(2)new Vue(options)配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue实例对象】
。
VueComponent实例对象(vc
)的功能和Vue实例(vm
)很像,也有数据代理、生命周期,数据监测,参数的配置项也很相似。
但是二者是不同的:1. vm可以指定el
,而vc不可以; 2. data定义的区别。
vm得功能>=
vc
VueComponent的实例对象,简称vc(也可称之为:组件实例对象)。.
Vue的实例对象,简称vm.
vm管理着一个个vc。
一个重要的内置关系
一个重要的内置关系:VueComponent.prototype._proto_ === Vue.prototype
.
-
根据原型链的知识,可以理解vue和VueComponent的如下原型关系
-
但是VueComponent将原型链做如下修改
VueComponent.prototype._proto_ === Vue.prototype
.,即:
这样做的目的是:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法
。 -
这样在Vue的原型对象上定义一个属性,vueComponent实例对象可以通过原型链访问到。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<school></school>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
Vue.prototype.x = 10
const school = Vue.extend({
data() {
return {
schoolName: "nefu",
address: "哈尔滨",
};
},
template: `
<div>
<h2>学校名字:{{schoolName}}</h2>
<h2>地址:{{address}}</h2>
<h2>Vue.prototype上的x:{{x}}</h2>
</div>`,
});
const vm = new Vue({
el: "#root",
components: {
school: school,
},
});
</script>
</body>
</html>