初学Vue
文章目录
组件
1、模块与组件、模块化与组件化
-
什么是模块
向外界提供特定功能的js程序,一般就是一个js文件,起到了复用js、简化js编写、提高js运行效率的作用。 -
什么是组件
用来实现局部特定功能效果的代码集合(html/css/js/image等),起到复用编码、简化项目编码、提高运行效率的作用。 -
什么是模块化
当应用中的js都以模块来编写,那这个应用就是一个模块化应用 -
什么是组件化
当应用中的功能都是多组件的方式来编写的,那这个应用就是一个组件化的应用
2、非单文件组件与单文件组件
- 非单文件组件
一个文件中包含n个组件 - 单文件组件
一个文件中只包含一个组件
2.1 非单文件组件
步骤:
1、创建组件
2、注册组件
3、使用组件(组件标签)
- 局部注册组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../JS/vue.js"></script>
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="root">
<!-- 3、编写组件标签,使用定义好的组件 -->
<school></school>
<hr>
<student></student>
</div>
<script>
Vue.config.productionTip = false;
// 1、创建组件
// 创建一个school组件
const school = Vue.extend({
// 组件的基本结构用template配置项决定(注意用div包裹)
template: `
<div>
<h2>学校名称:{
{schoolName}}</h2>
<h2>学校地址:{
{address}}</h2>
</div>
`,
// 注意组件里面不需要写el配置项,因为最终所有组件都会被一个vm管理,由vm决定服务对象
// data配置项必须写成函数形式
data() {
return {
schoolName: "清华大学",
address: "北京",
}
}
})
// 创建一个student组件
const student = Vue.extend({
template: `
<div>
<h2>学生姓名:{
{studentName}}</h2>
<h2>学生年龄:{
{age}}</h2>
</div>
`,
data() {
return {
studentName: "李明",
age: 23,
}
}
})
// 2、局部注册组件
const vm = new Vue({
el: "#root",
// 组件相关的配置项
components: {
school: school,
student: student
}
})
</script>
</body>
</html>
开发者工具查看
- 全局注册组件
<body>
<!-- 3、使用组件标签 -->
<div id="root1">
<hello></hello>
</div>
<!-- 在不同的vm对象中也能使用全局注册的标签 -->
<div id="root2">
<hello></hello>
</div>
<script>
// 1、创建组件
const hello = Vue.extend({
template: `
<div>
<div>你好呀!!{
{name}}</div>
</div>
`,
data(){
return {
name:"李明"
}
}
})
// 2、全局注册组件
Vue.component("hello",hello);
new Vue({
el: "#root1",
})
new Vue({
el: "#root2",
})
</script>
</body>
问题1:为什么data配置项必须写成函数的形式而不可以写成对象形式?
当data写成单独一个对象时,如果有多个用户对data进行修改,那么改的就是同一个data对象。例如:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="../../JS/vue.js"></script> <title>Document</title> </head> <body> <script> // 这是一个对象 const data = { a:1, b:2 } // 有两个对象同时想使用data中的数据 const x1 = data; const x2 = data; </script> </body> </html>
因为这个x1和x2都指向data,而data最内存中的地址是固定的,也就是说改变了x1中的值,就是改变了data的值,同时x2因为也指向data,那么x2也改变。
写成函数时可以通过return返回一个新对象,如下:
<script> // 这是一个函数 function data() { return { a: 1, b: 2 } } // 有两个对象同时想使用data中的数据 const x1 = data(); const x2 = data(); </script> </body>
分析:写成函数形式时,每次调用函数,都会返回一个新的对象,每一个对象都是单独存在的,各自占一片内存,互不影响。
问题2:注册组件的components配置项中,key值和value值的意义?
key值是使用组件时的名字,也就是组件标签,value值时创建组件时起的临时名字。
问题3:证明组件可以重复使用?<!-- 准备一个容器 --> <div id="root"> <!-- 3、编写组件标签,使用定义好的组件 -- <school></school> <hr> <student></student> <student></student> <student></student> </div>
使用组件的几个注意点:
1、组件标签的命名
(1)单个单词时,首字母大写或则和小写都行,例如:school或者School
(2)多个单词组成时
第一种方式:单词用横杠隔开,单词全部小写,并且用引号包裹起来,例如:“my-school”
第二种方式:每个单词首字母大写,例如:MySchool,这种方式必须在使用脚手架的前提下。
(3)组件尽量避免与html中保留的标签同名。
2、使用组件标签时有两种方式,一种时双标签,例如:< school></ school>,另一种时自闭合标签,例如< school/>,这种方式的使用前提是使用脚手架
组件嵌套
- 平级定义多个组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../JS/vue.js"></script>
<title>组件嵌套</title>
</head>
<body>
<!-- 3、使用组件 -->
<div id="root">
<school></school>
<student></student>
<teacher></teacher>
</div>
<script>
// 1、创建组件
// school组件
const school = Vue.extend({
name:"school",
template: `
<div>
<div>学校名字:{
{name}}</div>
<div>学校地址{
{address}}</div>
</div>
`,
data() {
return {
name: "清华大学",
address: "北京"
}
}
})
// 学生组件
const student = Vue.extend({
name:"student",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "小明",
age: 21
}
}
})
// 老师组件
const teacher = Vue.extend({
name:"teacher",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "张老师",
age: 31
}
}
})
// 创建vm对象
new Vue({
el: "#root",
// 2、注册组件
components:{
school,
student,
teacher
}
})
</script>
</body>
</html>
- 在一个组件中嵌套其他组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../JS/vue.js"></script>
<title>组件嵌套</title>
</head>
<body>
<!-- 3、使用组件 -->
<div id="root">
<school></school>
</div>
<script>
// 1、创建组件
// 嵌套时需要先定义子组件,创建了子组件后,父组件才能将其注册
// 学生组件(子组件)
const student = Vue.extend({
name:"student",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "小明",
age: 21
}
}
})
// 老师组件(子组件)
const teacher = Vue.extend({
name:"teacher",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "张老师",
age: 31
}
}
})
// school组件(父组件)
const school = Vue.extend({
name:"school",
template: `
<div>
<div>学校名字:{
{name}}</div>
<div>学校地址{
{address}}</div>
<student></student>
<teacher></teacher>
</div>
`,
data() {
return {
name: "清华大学",
address: "北京"
}
},
// 注册子组件
components:{
student,
teacher
}
})
// 创建vm对象
new Vue({
el: "#root",
// 2、注册组件
components:{
school,
}
})
</script>
</body>
</html>
打开开发工具同样也可以看到嵌套关系
注意点:
(1)使用嵌套时,子组件的创建需要在父组件创建之前,这样才能让子组件成功注册到父组件中形成嵌套关系
(2)在子组件注册到父组件后,一定记得要在父组件的template配置项中使用组件
(3)注册关系图如下:
- 在vm下定义一个app组件,用来管理vm中的所有组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="../../JS/vue.js"></script>
<title>组件嵌套</title>
</head>
<body>
<!-- 使用组件 -->
<div id="root">
<app></app>
</div>
<script>
// 创建组件
// 嵌套时需要先定义子组件,创建了子组件后,父组件才能将其注册
// 学生组件(子组件)
const student = Vue.extend({
name:"student",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "小明",
age: 21
}
}
})
// 老师组件(子组件)
const teacher = Vue.extend({
name:"teacher",
template: `
<div>
<div>学生姓名:{
{name}}</div>
<div>学生年龄:{
{age}}</div>
</div>
`,
data() {
return {
name: "张老师",
age: 31
}
}
})
// school组件(父组件)
const school = Vue.extend({
name:"school",
template: `
<div>
<div>学校名字:{
{name}}</div>
<div>学校地址{
{address}}</div>
<student></student>
<teacher></teacher>
</div>
`,
data() {
return {
name: "清华大学",
address: "北京"
}
},
// 注册子组件
components:{
student,
teacher
}
})
// 定义一个与school同级的组件
const hello = Vue.extend({
template:`
<div>
<div>自强不息,厚德载物</div>
</div>
`,
})
// 定义一个app组件,用来管理所有组件
const app = Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
hello,
school,
}
})
// 创建vm对象
new Vue({
el: "#root",
// 在vm中注册app组件
components:{
app
}
})
</script>
</body>
</html>
2.2 单文件组件
通常单文件组件不会单独出现,通常还会用到如下类型文件
- 页面html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件组件测试</title>
</head>
<body>
<!--准备一个容器 -->
<div id="root">
<App></App>
</div>
<!-- 先让页面模板加载完再引入js文件 -->
<!-- 先引入vue.js文件 -->
<script src="../../../JS/vue.js"></script>
<!-- 再引入入口文件 -->
<script src="./main.js"></script>
</body>
</html>
- main.js入口文件
// 引入vue
import vue from "vue"
// 引入App组件,这是所有组件的父组件
import App from "./app.vue"
// 创建vue实例
new Vue({
el:"#root",
// 注册App组件
components:{
App
}
})
- App.vue文件,管理所有组件
<template>
<div>
<Student></Student>
<Teacher></Teacher>
</div>
</template>
<script>
// 引入组件
import Student from "./Student";
import Teacher from "./Teacher";
// 暴露
export default {
name: "app",
// 注册组件
components: {
Student,
Teacher,
},
};
</script>
<style>
</style>
- 其他单个单文件组件
Student.vue组件
<template>
<!-- html代码,组件结构 -->
<div>
<div>学生姓名:{
{ name }}</div>
<div>学生年龄:{
{ age }}</div>
</div>
</template>
<script>
// 不做任何省略时
//#region
/*
export default student = Vue.extend({
name: "student",
data() {
return {
name: "小明",
age: "21",
};
},
})
*/
//#endregion
// js代码,控制组件交互
export default {
name: "student",
data() {
return {
name: "小明",
age: "21",
};
},
};
</script>
<style lang="">
/* css代码,组件样式渲染 */
</style>
Teacher.vue组件
<template>
<div>
<div>老师名字{
{ name }}</div>
<div>老师年龄:{
{ age }}</div>
</div>
</template>
<script>
export default {
name: "teacher",
data() {
return {
name: "张老师",
age: 31,
};
},
};
</script>
<style>
</style>
注意点:
(1)在给单文件组件命名时,同样有如下规则,单个单词时,首字母可大可小,当多个单词时,要么单词全部小写,单词间用横杆‘-’隔开,要么单词首字母全部大写
(2)通常会定义一个App.vue组件来管理所有组件
(3)组件中也是可以通过template配置项来添加模板
(4)通过脚手架就可以一步将上面的文件全部创建好。
3、VueComponet构造函数
关于VueComponet:
- 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
- 当使用组件标签时,例如< school>< /school>,Vue解析时会帮我们创建school组件的示例对象,即Vue帮我们执行的:new VueComponent(options)
- 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent
- 组件中this的指向:
(1)组件配置中:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this指向都是【VueComponent】
(2)new Vue()配置中:
data函数、methods中的函数,watch中的函数,computed中的函数,他们的this指向都是【vue实例】- VueComponent的实例对象,可以简称vc(或者组件实例对象),vue中的实例对象简称vm。
- 组件实例对象和vue实例对象的区别
虽然vm和vc对象很相似,vc中的配置vm中都有,但vm中有vc没有的,所以不能划上等号,有如下区别:
(1)vm中可以使用el配置项来指定为那个容器服务,而vc中不能使用。
(2)vm中的data配置项可以写成对象式,也可以写成函数式,而vc中的data只能写成函数式
4、Vue与VueComponent的内置关系
- 一个重要的内置关系:
VueComponent.prototype._proto_===Vue.prototype
上面的等式说明:vc实例对象通过属性__proto__指向Vue这个原型对象。 - 原因:
使得组件实例对象(vc)可以访问到Vue原型上的属性、方法。
如图: