Vue_2 --- 组件化编程
1. 模块与组件
1.1 模块化编写应用
向外提供特定功能的js程序,一般就是一个js文件,也就是一个模块

存在的问题
- 依赖关系混乱,不好维护
- 代码复用率不高
1.2 组件化编写引用
组件 --- 实现应用中局部功能代码和资源的集合


优点
- 好维护
- 代码复用率高
2. 非单文件组件
一个文件中包含多个组件
1. 创建组件(局部注册)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<!-- 4. 使用 school 组件 -->
<School></School>
<hr>
<!-- 4. 使用 student 组件,两个单词组成的需要用 - 连接 -->
<student-msg></student-msg>
<!-- 可以用自闭合标签,但是要再vue脚手架中使用 -->
<student-msg/>
</div>
</body>
<script>
Vue.config.productionTip = false
// 1. 创建组件
// 创建 school 组件,组件名首字母大写
const School = Vue.extend({
// el:"#root", // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
// 定义组件内的模板
name:"School", // 可以定义组件在开发者工具中的名字
template: `
<div>
<h1>学校名称: {{ schoolName }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
`,
data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
return {
schoolName: "实验中学",
address: "北京",
}
}
})
// 创建 student 组件,组件名首字母大写
const StudentMsg = Vue.extend({
// el:"#root", // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
// 定义组件内的模板
template: `
<div>
<h1>学生名称: {{ studentName }}</h1>
<h1>学生年龄: {{ age }}</h1>
</div>
`,
data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
return {
studentName: "张三",
age: 18
}
}
})
// 2. 创建Vue对象
new Vue({
el: '#app',
data: {
msg: "Vue实例"
},
// 3. 注册组件(局部注册)
components: {
School,
StudentMsg
}
})
</script>
</html>
定义组件的简写方式
<script>
// 内部会有判断,如果是对象,会自动调用 Vue.extend()
const StudentMsg = {
// el:"#root", // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
// 定义组件内的模板
template: `
<div>
<h1>学生名称: {{ studentName }}</h1>
<h1>学生年龄: {{ age }}</h1>
</div>
`,
data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
return {
studentName: "张三",
age: 18
}
}
}
</script>
2. 创建组件(全局注册)
<script>
Vue.config.productionTip = false
// 创建 School组件
const School = Vue.extend({
template: `
<div>
<h1>学校名称: {{ schoolName }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
`,
data() {
return {
schoolName: "实验中学",
address: "北京",
}
}
})
// 注册组件(全局注册)
Vue.component("School",school)
new Vue({
el: '#app',
})
</script>
3. 组件嵌套
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<!-- 4. 使用 school 组件 -->
<School></School>
<hr>
<!-- 4. 使用 student 组件 -->
</div>
</body>
<script>
Vue.config.productionTip = false
// 1. 创建组件
// 创建 student 组件
const StudentMsg = Vue.extend({
template: `
<div>
<h1>学生名称: {{ studentName }}</h1>
<h1>学生年龄: {{ age }}</h1>
</div>
`,
data() {
return {
studentName: "张三",
age: 18
}
}
})
// 创建 school 组件,并在其中嵌套 student 组件
const School = Vue.extend({
template: `
<div>
<h1>学校名称: {{ schoolName }}</h1>
<h1>学校地址: {{ address }}</h1>
<student-msg></student-msg> <!-- school 组件中 写 student 组件的标签 -->
</div>
`,
data() {
return {
schoolName: "实验中学",
address: "北京",
}
},
// 在 school 组件中注册 student 组件
components: {
StudentMsg
}
})
// 2. 创建Vue对象
new Vue({
el: '#app',
// 3. 注册组件(局部注册)
components: {
School,
}
})
</script>
</html>
4. 组件标准化开发
以后标准化开发过程中,会由 vm 只管理 一个 app 这个顶层组件, app中再管理着多个子组件和子嵌套组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<!-- 空容器,由vm将app组件放到容器 -->
<div id="app">
</div>
</body>
<script>
Vue.config.productionTip = false
// 1. 创建组件
// 创建 student 组件
const StudentMsg = Vue.extend({
template: `
<div>
<h1>学生名称: {{ studentName }}</h1>
<h1>学生年龄: {{ age }}</h1>
</div>
`,
data() {
return {
studentName: "张三",
age: 18
}
}
})
// 创建 school 组件,并在其中嵌套 student 组件
const School = Vue.extend({
template: `
<div>
<h1>学校名称: {{ schoolName }}</h1>
<h1>学校地址: {{ address }}</h1>
<student-msg></student-msg> <!-- school 组件中 写 student 组件的标签 -->
</div>
`,
data() {
return {
schoolName: "实验中学",
address: "北京",
}
},
// 在 school 组件中注册 student 组件
components: {
StudentMsg
}
})
// 创建app组件
const app = Vue.extend({
template: `<school></school>`,
components: {
School,
}
})
// 2. 创建Vue对象
new Vue({
el: '#app',
template: `<app></app>`,
// 3. 注册 app 组件(局部注册)
components: {
app,
}
})
</script>
</html>
5. VueComponent --- 组件实例对象
- 组件的本质是一个名为
VueComponent的构造函数,且不是程序员定义的,是Vue.extend()生成的 - 我们只需要写
<school/>或<school></school>,Vue解析模板时会帮我们创建组件的实例对象,即Vue执行的:new VueComponent(options) - 特别注意: 每次调用
Vue.extend(),返回的都是一个全新的VueComponent实例对象 - 关于this指向:
- 组件的
{}对象配置中:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this均是VueComponent 实例对象 new Vue(options)中的options配置中的:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this均是Vue 实例对象
- 组件的
VueComponent的实例对象,简称vc,Vue的实例对象,简称vm,vc 和vm 的功能差不多,也有数据监视和数据代理,vm实例中的$children是个数组,存储着一个一个的vc,每个vc的$children也是个数组,存储着一个一个的嵌套组件vc,但是vc不能写el配置项,data必须写成函数形式return一个对象
6. 内置关系
1. 原型对象的概述(类继承)
// 定义一个构造函数
function Demo(){
this.a = 1
this.b = 2
}
// 创建一个实例
const d = new Demo()
console.log(Demo.prototype) // 显式原型属性
console.log(d.__proto__) // 隐式原型属性
// 它们两个所指向的都是同一个对象: 原型对象
// 程序员通过显式原型属性操作原型对象,设置一个属性x,值是99
Demo.prototype.x = 99
// 调用d.x时,d身上没有x这个属性,自动顺着隐式原型属性找原型对象身上有没有x属性
console.log(d.x) // 其本质是 d.__proto__.x 通过隐式原型属性调用x,可以省略
2. 对象的指向关系

3. 结论
- 内置关系:
VueComponent.prototype.__proto__ === Vue.prototype - 为什么要有这个关系: 让组件实例对象(vc)可以访问到Vue原型上的属性、方法
3. 单文件组件(常用)
一个文件中只包含一个组件,以.vue结尾的文件
1. 文件结构
<template> <!-- template 标签是不参与编译的,即最终呈现在浏览器中的结构不会出现template这个标签 -->
<!-- 组件的标签结构 -->
</template>
<script>
// 组件交互相关的代码(数据,方法)
</script>
<style>
/* 组件的样式 */
</style>
2. 对外暴露方式
1. 分别暴露
<template>
<div class="demo">
<h1>学校名称: {{ name }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
</template>
<script>
// 对外暴露组件的方式一: 分别暴露
export const school = {
name: "School",
data() {
return {
name: "实验中学",
address: "北京",
}
}
}
</script>
<style>
.demo {
}
</style>
外部的引用方式
import {school} from "文件路径"
2. 统一暴露
<template>
<div class="demo">
<h1>学校名称: {{ name }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
</template>
<script>
const school = {
name: "School",
data() {
return {
name: "实验中学",
address: "北京",
}
}
}
// 对外暴露组件的方式一: 统一暴露
export {school}
</script>
<style>
.demo {
}
</style>
外部的引用方式
import {school} from "文件路径"
3. 默认暴露(常用)
<template>
<div class="demo">
<h1>学校名称: {{ name }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
name: "实验中学",
address: "北京",
}
}
}
// 对外暴露组件的方式三: 默认暴露
</script>
<style>
/* 组件的样式 */
.demo {
}
</style>
外部的引用方式
import school from "文件路径"
3. 目录结构
1. School 组件
<template>
<div class="demo">
<h1>学校名称: {{ name }}</h1>
<h1>学校地址: {{ address }}</h1>
</div>
</template>
<script>
export default {
name: "School",
data() {
return {
name: "实验中学",
address: "北京",
}
}
}
// 对外暴露组件的方式三: 默认暴露
</script>
<style>
/* 组件的样式 */
.demo {
}
</style>
2. App.vue
<template>
<!-- 2. 使用组件 -->
<div>
<School/>
</div>
</template>
<script>
// 1. 引入组件
import School from "./School.vue";
export default {
name: "App",
components: {School},
data() {
return {}
}
}
</script>
<style>
</style>
3. main.js
import App from "./App.vue";
new Vue({
el: "#root",
template: `<App/>`, // 将 App 组件放入root 的模板中
components: {App}
})
4. index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单文件组件</title>
</head>
<body>
<!-- 1. 创建容器 -->
<div id="root"></div>
<!-- 2. 引入 vue.js -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<!-- 3. 引入 main.js -->
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
python防脱发技巧

浙公网安备 33010602011771号