2.VUE组件化编程
组件的定义:实现应用中局部功能代码和资源的集合
传统方式:
问题:
(1)依赖关系混乱。
(3)代码复用率不高。
组件方式
2.1 模块与组件
2.1.1模块
(1)概念:向外提供特定功能的js程序,一般是一个js文件。
(2)使用原因:js文件很多很复杂。
(3)作用:复用js,简化js的编写,提高js运行效率。
2.1.2 组件
(1)概念:用来实现局部(特定)功能效果的代码集合(html/css/js/image...)。
(2)使用原因:一个界面功能很复杂。
(3)作用:复用代码,简化项目编码,提高运行效率。
2.1.3 模块化
应用中的js都已模块来编写,这个应用就是一个模块化应用。
2.1.4 组件化
当应用中的功能都是多组件的方式来编写,那么这个应用就是组件化应用
2.2 非单文件组件
定义:一个文件中有多个组件。
2.2.1 非单文件组件使用
(1)Vue组件使用三大步骤:
(1.1)定义组件(创建组件)
(1.2)注册组件(全局注册/局部注册)
(1.3)使用组件(写组件标签)
(2)如何定义一个组件
(2.1)使用VUe.extend(options)创建,其中options和new Vue(options)传入的options
几乎一样,但也有点区别:
(2.1.1)不写el:组中所有组件都由vm管理,有vm指定el服务的容器。
(2.1.2)data必须写函数式:避免组件复用时,数据引用造成的数据修改错误。
(2.2)备注:template可以配置组件结构。
(3)如何注册组件:
(3.1)局部注册:new Vue()时,传入入参conponents:{}参数。
(3.2)全局注册:Vue.component('组件名',组件)。
(4)使用组件:使用引入组件时指定的组件名===><组件名><组件名/>
<div id="root">
root1star
<!-- 3.编写组件标签 -->
<school>
</school>
<hr>
<student>
</student>
<hr>
<hello>
</hello>
<hr>
root1end
</div>
<div id="root2">
root2
<hello>
</hello>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//全局注册
//1.创建组件school
const schoolConst = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>学校名称:{{school.name}}</h2>
<h2>学校地址:{{school.address}}</h2>
<button @click="alertSchoolName">弹出学校名</button>
</div>`,
//组件变量,必须用函数式
data() {
return {
school: {
name: "schoolName",
address: "schoolAddress"
}
}
},methods: {
alertSchoolName(){
alert(this.school.name)
}
},
})
//1.创建组件student
const student = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>学生姓名:{{student.name}}</h2>
<h2>学生年龄:{{student.age}}</h2>
</div>`,
data() {
return {
student: {
name: "studentName",
age: "studentAge"
}
}
},
})
//1.创建组件student
const hello = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>hello{{hello}}</h2>
</div>`,
data() {
return {
hello:"你好"
}
},
})
Vue.component('hello',hello)
//创建vm
new Vue({
el: '#root',
//2.注册组件(局部注册)
components: {
//key为注册后的真实key,value为创建的const组件变量名,若两个一样可以简写为一个单词
school: schoolConst,
// student:student,
student
},
})
new Vue({
el:"#root2",
})
</script>
2.2.2 ★注意点★
(1)关于组件名:
(1.1)一个单词组成:
(1.1.1)首字母小写(school)。
(1.1.2)首字母小写(School)。
(1.2)多个单词组成:
(1.2.1)kebab-case命名方式:my-school。
(1.2.2)CsmelCase命名方式:MySchool(需要脚手架支持)。
(1.3)备注:
(1.3.1)组件名尽可能回避HTML已存在的元素名,例如:h1,H1等等。
(1.3.2)可以使用name配置指定组件在开发者工具中的名字(不影响调用)。
(2)关于组建标签:
(2.1)单标签<school/>。
(2.2)双标签<school></school>。
(2.3)不适用脚手架单标签<school/>多个连续使用会导致后面的无法渲染。
(3)简写方式:
const school={},当变量等于一个对象不调用Vue.compent()方法时,在vm引入 组件时会做判断,如果没有调用,或自动去调用Vue.compent()。
(3.1)简写:
const schoolConst = { template: `<div> <h2>学校名称:{{school.name}}</h2> <h2>学校地址:{{school.address}}</h2> <button @click="alertSchoolName">弹出学校名</button> </div>`, data() { return { school: { name: "schoolName", address: "schoolAddress" } } }, methods: { alertSchoolName() { alert(this.school.name) } }, }
(3.2)Vue自检:
function extend(to, _from) { for (var key in _from) { to[key] = _from[key]; } return to; }
2.2.3组件嵌套
<div id="root">
root1star
<!-- 3.编写组件标签 -->
<!-- <app/> -->
<hr>
root1end
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
//全局注册
//1.创建组件hello
const hello = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>hello{{hello}}</h2>
</div>`,
data() {
return {
hello:"你好"
}
},
})
//1.创建组件student
const student = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>学生姓名:{{student.name}}</h2>
<h2>学生年龄:{{student.age}}</h2>
</div>`,
data() {
return {
student: {
name: "studentName",
age: "studentAge"
}
}
},components:{
hello
}
})
//1.创建组件school
const schoolConst = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>学校名称:{{school.name}}</h2>
<h2>学校地址:{{school.address}}</h2>
<student></student>
<button @click="alertSchoolName">弹出学校名</button>
</div>`,
//组件变量,必须用函数式
data() {
return {
school: {
name: "schoolName",
address: "schoolAddress"
}
}
},components:{
student
},methods: {
alertSchoolName(){
alert(this.school.name)
}
},
})
const app={
template: `<div>
<hello></hello>
<school></scholl>
</div>`,
components:{
school:schoolConst,
hello
}
}
//创建vm
new Vue({
el: '#root',
//2.注册组件(局部注册)
template:" <app/> ",
components: {
//key为注册后的真实key,value为创建的const组件变量名,若两个一样可以简写为一个单词
app: app,
},
})
</script>
2.2.4 VueConponent
关于 VueConponent:
(1)shcool组件本质是一个名为VueConponent的构造函数,且不是程序员地赢的,是 Vue.extent生成的。
(2)我们只需要写<school></school>或者<school/>,Vue解析时会帮我们创建school组件的 实例对象。
(3)特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent。
(4)关于this指向:
(4.1)组件配置中:data函数,methods中的函数,watch中的函数,computed中的函
数,他们的this指向的是【VueComponent实例对象】
(4.2)new Vue配置中:data函数,methods中的函数,watch中的函数,computed中
的函数,他们的this指向的是【Vue实例对象】
(5)一般情况下:
(5.1)VueComponent实例对象简称==》vc(组件实例对象)
(5.2)Vue对象简称==》vm
2.2.5 ★内置关系★
2.2.5.1 原型对象
function demo(){
this.a=1
this.b=2
}
const d=new demo();
console.log(demo.prototype);//显示原型属性
console.log(d.__proto__);//隐式原型属性
console.log(d.__proto__===demo.prototype,"demo.prototype===d.__proto__");//true 他们都是原型对象
//对原型对象添加一个属性99
demo.prototype.x=99
2.2.5.2 Vue和VueComponent
(1)一个重要的内置关系:Vue.prototype===schoolConst.prototype.__proto__(true)。
(2)为什么要有这个关系:让组件实例对象vc可以访问到Vue原型上的属性,方法。
//1.创建组件school
const schoolConst = Vue.extend({
//el: '#root', 组件定义时一定不要写el,因为最终都要被一个vm管理,vm决定服务于谁
//组件模板
template: `<div>
<h2>学校名称:{{school.name}}</h2>
<h2>学校地址:{{school.address}}</h2>
</div>`,
//组件变量,必须用函数式
data() {
return {
school: {
name: "schoolName",
address: "schoolAddress"
}
}
}
})
//创建vm
new Vue({
el: '#root',
//2.注册组件(局部注册)
template:" <school/> ",
components: {
//key为注册后的真实key,value为创建的const组件变量名,若两个一样可以简写为一个单词
school: schoolConst,
},
})
console.log("Vue.prototype===schoolConst.prototype.__proto__:",Vue.prototype===schoolConst.prototype.__proto__)//true
2.3. 单文件组件
定义:一个文件只有一个组件。
2.3.1 Vue文件
<template>
<!-- 组件的结构 -->
<div class="demo">
<h2>学校名称:{{ school.name }}</h2>
<h2>学校地址:{{ school.address }}</h2>
</div>
</template>
<script>
//组件交互相关代码(数据,方法)
export default {
name: "School",
//组件变量,必须用函数式
data() {
return {
school: {
name: "schoolName",
address: "schoolAddress",
},
};
},
methods: {
alertSchoolName() {
alert(this.school.name);
},
},
};
</script>
<style>
/* 组件样式 */
.demo {
background: beige;
}
</style>
<template>
<!-- 组件的结构 -->
<div>
<h2>学生姓名:{{ student.name }}</h2>
<h2>学生年龄:{{ student.age }}</h2>
</div>
</template>
<script>
//组件交互相关代码(数据,方法)
export default {
name:'student',
data() {
return {
student: {
name: "studentName",
age: "studentAge",
},
};
},
};
</script>
<style>
/* 组件样式 */
</style>
2.3.2App.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>
2.3.3main.js
import Vue from 'vue'
import App from './App'
new Vue({
el:"#root",
template:`<App></App>`,
components:{App}
})
2.3.4 index.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>
</head>
<body>
<div id="root">
</div>
<script src="../../js/vue.js"></script>
<script src="./main.js"></script>
</body>
</html>