一.生命周期
1.了解生命周期
- 生命周期又名生命周期回调函数,生命周期函数,生命周期钩子。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据要求编写的。
- 生命周期函数中的this指向vm或组件实例对象。
要求:实现在页面中显示“欢迎学习Vue”,并使其达到透明度有小变大的效果,(要求打开页面就开始变化。)
<div id="root">
<!-- 1.完整写法:<h2:style="{opacity:opacity}">欢迎学习Vue</h2>,用对象解构可以简写为下一行代码-->
<h2 :style="{opacity}">欢迎学习Vue</h2> <!--因为透明度需要不断变化,所以需要用动态绑定样式 -->
</div>
<script>
new Vue({
el:"#root",
data:{
opacity:1
},
//3.Vue完成模板的解析并把初始值(最开始的值,以后数据再改变都不会调用mounted函数)的真实DOM元素放入页面后(挂载完毕),调用mounted函数
mounted(){ //2.特殊,是一个函数,和methods平级
this.timer=setInterval(()=>{
this.opacity-=0.01 //3.每16ms透明度减小0.01
if(this.opacity<=0) //4.使用判断语句做一个限制。当透明度减小为0,是透明度再变为1,但由于js对小数不敏感(0.1+0.2!=0.3),他可能会跳过0,所以最好设置为小于等于0
this.opacity=1
},16)
}
})
</script>
这样就会实现一个透明度动态变化的效果。
2.分析生命周期
vm的生命周期:
将要创建==>调用beforeCreate函数。
创建完毕=–>调用created函数。
将要挂载=->调用beforeMount函数。
(重要)挂载完毕==>调用mounted函数。 =>【重要的钩子】
将要更新=–>调用beforeUpdate函数。
更新完毕==>调用updated函数。
(重要)将要销毁=->调用beforeDestroy函数。=>【重要的钩子】
销毁完毕=-=>调用destroyed函数。
常用的生命周期钩子
1.mounted:发送ajax请求,启动定时器、绑定自定义事件、订阅消息等初始化操作。
2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作。
不常用的钩子(beforeUpdate和updated)
beforeUpdated:数据是新的,页面是旧的,数据和页面未保持同步。(控制台已输出更新后的数据,单页面并未更新)
updated:数据和页面都是新的,保持同步。
关于销毁vue实例
- 销毁后借助vue开发者工具看不到任何信息。
- 销毁后自定义事件会失效,但原生DOM事件依然有效。
- 一般不会在beforeDestroy操作数据,即便操作,也无法触发更新流程。
3.案例练习
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
<button @click="stop">点我停止变化</button>
<button @click="opacity=1">点我透明度为1</button>
</div>
<script>
new Vue({
el:"#root",
data:{
opacity:1
},
methods:{
stop(){
this.$destroy() //1.销毁vm
}
},
mounted(){
//3.由于beforeDestroy函数需要关闭定时器,要用到定时器,所以需要给定时器命一个名字,若直接用const或let会产生块级作用域,只在mounted()这个函数体内部起作用,所以要么在外部定义“let timer”,这里用timer接;要么就用this.timer(this指向vm)
this.timer=setInterval(()=>{
this.opacity-=0.01
if(this.opacity<=0)
this.opacity=1
},16)
},
beforeDestroy(){ //2.发现vm被销毁时,就会执行beforeDestroy函数,在本题中,需要其执行关闭定时器的操作
clearInterval(this.timer)
}
})
</script>
当点击“点我停止变化”的按钮时,效果如下:
二.组件
1.组件的定义
组件的定义:实现应用中局部功能代码和资源的集合。
作用:复用编码、简化项目编码,提高运行效率。
模块的定义:向外提供特定功能的js程序,一般就是一个js文件。
作用:复用js,简化js的编写,提高js的运行效率。
模块化:当应用中的js都以模块来编写的,那这个应用就是一个模块化的应用。
组件化:当应用中的功能都是多组件的方式编写的,那这个应用就是一个组件化的应用。
2.创建组件(非单文件组件)
在创建组件时,不用添加el,不用指定服务于谁,vm会指定。
第一步:创建学校组件
// 第一步:创建学校组件
const school=Vue.extend({
//必须在模板上加上一个根标签
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我显示学校名字</button>
</div>
`,
data(){ //data必须用函数,防止组件被复用时,数据存在引用关系。注意:有返回值
return{
schoolName:"尚硅谷",
address:"北京"
}
},
methods:{
showName(){
alert(this.schoolName)
}
}
})
第一步:创建学生组件
// 第一步:创建学生组件
const student=Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:"张三",
age:"18"
}
},
})
第二步:注册组件
// 第二步:注册组件
new Vue({
el:"#root", //指定组件服务于哪个容器
components:{
school, //完整写法:school:school
student
}
})
第三步:使用组件
<div id="root">
<!-- 第三步:使用组件 -->
<school></school>
<hr>
<student></student>
</div>
效果图:
3.全局注册组件
先创建hello组件
//创建hello组件
const hello=Vue.extend({
template:`
<div>
<h2>你好,{{name}}</h2>
</div>
`,
data(){
return{
name:"yoyo"
}
}
})
注册hello组件(全局注册)
//注册hello组件(全局注册)
Vue.component("hello",hello) //注意:第一个hello表示组件名,要用引号。第二个hello表示组件
4.tips
关于组件名
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)
补充:组件注册的时候是什么名字,用的时候标签里也是什么名字。
通过name配置项在定义组件时起一个名字,这个名字会在开发者工具呈现,而不会用注册时的名字。
组件标签
第一种写法:<school></school>
第二种写法:<school/>
备注:不使用脚架时,会导致后续组件不能渲染。
创建组件简写
const school=Vue.extend({ })
可简写为
const school={ }
//创建组件的简写:
const student={
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:"张三",
age:"18"
}
}
}
5.组件嵌套
案例1
要求实现student作为school的子标签
//创建学生组件
const student=Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:"张三",
age:"18"
}
},
})
//创建学校组件
const school=Vue.extend({
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student> //把student组建的标签写在template里面
</div>
`,
data(){
return{
schoolName:"尚硅谷",
address:"北京"
}
},
components:{
student //注意:这里需要先创建student组件,否则会出错
}
})
//注册组件
new Vue({
el:"#root",
components:{
school //student标签已经在school里了,所以这里只需要写school
}
})
</script>
效果:
案例2
要求实现student作为school的子标签,并创建一个hello组件,使其和school标签同级
<div id="root">
<hello></hello>
<school></school>
</div>
<script>
//创建学生组件
const student=Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:"张三",
age:"18"
}
},
})
//创建学校组件
const school=Vue.extend({
//必须在模板上加上一个根标签
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return{
schoolName:"尚硅谷",
address:"北京"
}
},
components:{
student
}
})
//创建hello组件
const hello=Vue.extend({
template:`
<div>
<h2>你好,{{name}}</h2>
</div>
`,
data(){
return {
name:"yoyo"
}
}
})
//注册组件
new Vue({
el:"#root",
components:{
school,
hello
}
})
</script>
效果:
案例3
**要求实现student作为school的子标签,并创建一个hello组件,使其和school标签同级。在此基础上,再创建一个app组件,使其管理这三个组件 **
<div id="root">
<!-- <app></app> -->
</div>
<script>
//创建学生组件
const student=Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:"张三",
age:"18"
}
},
})
//创建学校组件
const school=Vue.extend({
//必须在模板上加上一个根标签
template:`
<div>
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return{
schoolName:"尚硅谷",
address:"北京"
}
},
components:{
student
}
})
//创建hello组件
const hello=Vue.extend({
template:`
<div>
<h2>你好,{{name}}</h2>
</div>
`,
data(){
return {
name:"yoyo"
}
}
})
//创建app组件
const app=Vue.extend({
template:`
<div>
<h2>欢迎学习Vue</h2>
<hello></hello>
<school></school>
</div>
`,
components:{
school,
hello
}
})
//注册组件
new Vue({
el:"#root",
template:`
<div>
<app></app>
</div>
`, //可以将app标签放在template中,也可以将其放在容器里。
components:{
app
}
})
</script>
效果: