7.1 vue对象的生命周期
生命周期:
又名:生命周期回调函数、生命周期函数、生命周期钩子。
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
生命周期函数中的this指向是vm
或组件实例对象
。
-
初始化显示
beforeCreate()
created()
-
初始化后,挂载
beforeMount()
mounted()
-
更新状态
beforeUpdate()
updated()
-
销毁 vue 实例: vm.$destory()
beforeDestory()
destoryed()
7.2 生命周期图解
图解说明
尚硅谷的生命周期解说视频https://www.bilibili.com/video/BV1Zy4y1K7SH?p=48
引出生命周期的例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2 v-if="a">你好啊</h2>
<h2 :style="{opacity}">欢迎学习Vue</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
a:false,
opacity:1
},
methods: {
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
mounted(){
console.log('mounted',this)
setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
})
//通过外部的定时器实现(不推荐)
/* setInterval(() => {
vm.opacity -= 0.01
if(vm.opacity <= 0) vm.opacity = 1
},16) */
</script>
</html>
效果
7.3 常用的生命周期方法(生命周期钩子)
mounted
: 发送ajax
请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。beforeDestroy
: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
7.4 关于销毁Vue实例
- 销毁后借助
Vue
开发者工具看不到任何信息。 - 销毁后自定义事件会失效,但原生
DOM
事件依然有效。 - 一般不会在
beforeDestroy
操作数据,因为即便操作数据,也不会再触发更新流程了。
7.5 组件的概念
7.5.1 传统方式编写应用
存在问题:
- 依赖关系混乱,不好维护
- 代码复用率不高
7.5.2 使用组件方式编写应用
7.5.3 组件的定义——实现应用中局部功能代码
和资源
的集合
7.5.4 模块
- 理解: 向外提供特定功能的
js
程序, 一般就是一个js
文件 - 为什么:
js
文件很多很复杂 - 作用: 复用
js
, 简化js
的编写, 提高js
运行效率
7.5.5 组件
- 理解: 用来实现局部(特定)功能效果的代码集合(
html/css/js/image
……) - 为什么: 一个界面的功能很复杂
- 作用: 复用编码, 简化项目编码, 提高运行效率
7.5.6 模块化
当应用中的
js
都以模块来编写的, 那这个应用就是一个模块化的应用。
7.5.7 组件化
当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用,。
7.6 非单文件组件
非单文件组件
一个文件中包含有n个组件
单文件组件
一个文件中只包含1个组件
7.6.1 使用组件的三大步骤
- 定义组件(创建组件)
- 注册组件
- 使用组件(写组件标签)
7.6.2 如何定义一个组件
使用Vue.extend(options)
创建,其中options
和new Vue(options)
时传入的那个options
几乎一样,但有以下区别
不要写el
——因为最终所有的组件都要经过一个vm
的管理,由vm
中的el
决定服务哪个容器
data
必须写成函数——避免组件被复用时,数据存在引用关系
备注:使用template
可以配置组件结构。
7.6.3 如何注册组件?
- 局部注册:靠
new Vue
的时候传入components
选项 - 全局注册:靠
Vue.component('组件名',组件)
7.6.4 编写组件标签:
<school></school>
案例如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<hello></hello>
<hr>
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<school></school>
<hr>
<!-- 第三步:编写组件标签 -->
<student></student>
</div>
<div id="root2">
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//第一步:创建school组件
const school = Vue.extend({
template:`
<div class="demo">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'尚硅谷',
address:'北京昌平'
}
},
methods: {
showName(){
alert(this.schoolName)
}
},
})
//第一步:创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
age:18
}
}
})
//第一步:创建hello组件
const hello = Vue.extend({
template:`
<div>
<h2>你好啊!{{name}}</h2>
</div>
`,
data(){
return {
name:'Tom'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
new Vue({
el:'#root2',
})
</script>
</html>
7.6.5 几个注意点:
-
关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
(推荐使用)
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool
(推荐使用)(需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。 -
关于组件标签:
第一种写法:<school></school>
第二种写法:<school/>
第二种写法备注:不使用脚手架时,<school/>
会导致后续组件不能渲染。(这种写法最好在脚手架中使用) -
一个简写方式:
const school = Vue.extend(options)
可简写为:const school = options
案例如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>几个注意点</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h1>{{msg}}</h1>
<school></school>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义组件
// const s = Vue.extend({
// name:'atguigu',
// template:`
// <div>
// <h2>学校名称:{{name}}</h2>
// <h2>学校地址:{{address}}</h2>
// </div>
// `,
// data(){
// return {
// name:'尚硅谷',
// address:'北京'
// }
// }
// })
//定义组件 简写形式,无需写Vue.extend()
const s = {
name:'atguigu',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
}
}
new Vue({
el:'#root',
data:{
msg:'欢迎学习Vue!'
},
components:{
school:s
}
})
</script>
</html>
7.6.6 组件的嵌套
案例如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件的嵌套</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//定义student组件
const student = Vue.extend({
name:'student',
template:`
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
name:'尚硅谷',
age:18
}
}
})
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
//注册组件(局部)
components:{
student
}
})
//定义hello组件
const hello = Vue.extend({
template:`<h1>{{msg}}</h1>`,
data(){
return {
msg:'欢迎来到尚硅谷学习!'
}
}
})
//定义app组件
const app = Vue.extend({
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
template:'<app></app>',
el:'#root',
//注册组件(局部)
components:{app}
})
</script>
</html>
7.7 关于VueComponent:
school
组件本质是一个名为VueComponent
的构造函数,且不是程序员定义的,是Vue.extend
生成的。- 我们只需要写
<school/>
或<school></school>
,Vue
解析时会帮我们创建school组件
的实例对象,
即Vue
帮我们执行的:new VueComponent(options)
。 - 特别注意:每次调用
Vue.extend
,返回的都是一个全新的VueComponent
!!!! - 关于
this
指向:
(1).组件配置中:
data函数
、methods中的函数
、watch中的函数
、computed中的函数
它们的this
均是【VueComponent实例对象】
。
(2).new Vue(options)
配置中:
data函数
、methods中的函数
、watch中的函数
、computed中的函数
它们的this
均是【Vue实例对象】
。 VueComponent
的实例对象,以后简称vc
(也可称之为:组件实例对象)。
Vue
的实例对象,以后简称vm
。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>VueComponent</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<school></school>
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showName(){
console.log('showName',this)
}
},
})
const test = Vue.extend({
template:`<span>atguigu</span>`
})
//定义hello组件
const hello = Vue.extend({
template:`
<div>
<h2>{{msg}}</h2>
<test></test>
</div>
`,
data(){
return {
msg:'你好啊!'
}
},
components:{test}
})
console.log('@',school)
console.log('#',hello)
//创建vm
const vm = new Vue({
el:'#root',
components:{school,hello}
})
</script>
</html>
7.8 一个重要的内置关系:
VueComponent.prototype.proto === Vue.prototype
- 为什么要有这个关系:让
组件实例对象(vc)
可以访问到Vue
原型上的属性、方法。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>一个重要的内置关系</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
-->
<!-- 准备好一个容器-->
<div id="root">
<school></school>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.prototype.x = 99
//定义school组件
const school = Vue.extend({
name:'school',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showX">点我输出x</button>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showX(){
console.log(this.x)
}
},
})
//创建一个vm
const vm = new Vue({
el:'#root',
data:{
msg:'你好'
},
components:{school}
})
//定义一个构造函数
/* function Demo(){
this.a = 1
this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype) //显示原型属性
console.log(d.__proto__) //隐式原型属性
console.log(Demo.prototype === d.__proto__)
//程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
console.log('@',d) */
</script>
</html>
7.9 单文件组件(重点)
编写xxx.vue
,让其有高亮效果,安装Vetur插件
三种暴露方式
-
分别暴露
-
统一暴露
-
默认暴露**(推荐使用)**
7.10 使用 Vue 脚手架
说明
Vue 脚手架
是Vue
官方提供的标准化开发工具(开发平台)。- 文档: https://cli.vuejs.org/zh/
脚手架安装具体步骤
先安装node.js
第一步(仅第一次执行):全局安装@vue/cli
。
npm install -g @vue/cli@4.5.13
@4.5.13是指定版本号
第二步:切换到你要创建项目的目录,然后使用命令创建项目
vue create xxxx
第三步:启动项目
npm run serve
备注:
- 如出现下载缓慢请配置
npm
淘宝镜像:
建议先配置npm淘宝镜像
npm config set registry https://registry.npm.taobao.org
Vue
脚手架隐藏了所有webpack
相关的配置,若想查看具体的webpack
配置, 请执行:
vue inspect > output.js
7.10.1 脚手架文件结构
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
7.10.2 index.html
7.10.3 noscript 标签说明
<!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>Document</title>
</head>
<body>
<h1>你好</h1>
<noscript>
不好意思,你的浏览器不支持js,有点旧了,下载一个新的吧
</noscript>
</body>
</html>
7.10.4关于不同版本的Vue以及为什么要使用render
方式一:引用完整版Vue
成功
方式二:使用render函数
成功
vue.js
与vue.runtime.xxx.js
的区别:
vue.js
是完整版的Vue,包含:核心功能 + 模板解析器。
vue.runtime.xxx.js
是运行版的Vue
,只包含:核心功能;没有模板解析器。
因为vue.runtime.xxx.js
没有模板解析器,所以不能使用template
这个配置项,需要使用render
函数接收到的createElement
函数去指定具体内容。
7.10.5 vue.config.js配置文件
使用vue inspect > output.js
可以查看到Vue脚手架的默认配置。
使用vue.config.js
可以对脚手架进行个性化定制,详情见:https://cli.vuejs.org/zh
案例地址
https://github.com/RanGuMo/vue_test.git