组件的生命周期

首先,我们一起了解一下,钩子是什么?

钩子函数,就是options里面的key, 它的值是函数
钩子函数写在其他配置项的后面

组件有那几个阶段?
初始化阶段
运行中阶段
销毁阶段

1.1 初始化阶段

分为两个大阶段, 每一个大阶段包含两个生命周期钩子函数 ---- 生命周期 --》人的一生
钩子函数 --》 (人在某个阶段做的一些事情, 这些事情是自动触发)

有那四个钩子函数呢?每个钩子函数有什么功能嗯?项目中有什么用呢?

  1. beforeCreate —表示组件创建之前的准备工作(初始化事件和生命周期)
  • 表示组件创建前的准备工作, 为事件的发布订阅 和 生命周期的开始做初始化
  • 这个钩子函数中
    • 数据拿不到, 真实DOM也拿不到
  • 这个钩子在项目中我们没有什么实际用途
  1. created
  • 表示组件创建结束
  • 这个钩子函数中
    • 数据拿到了, 但是真实DOM没有拿到
  • 这个钩子函数在项目
    • 数据请求, 然后可以进行一次默认数据的修改
  1. beforeMount
  • 表示组件装载前的准备工作
    • 判断 el选项有没有, 判断 template选项有没有 , 如果没有, 那么需要手动装载
    • 如果有,那么通过render函数进行模板的渲染(没有做的,正要进行, VDOM)
  • 这个钩子函数中
    • 数据拿到了, 真实DOM没有拿到
  • 这个钩子函数在项目中,
    • 数据请求, 它也可以进行一次数据修改
  1. mounted
  • 表示组件装载结束, 就是我们可以在视图中看到了
  • 这个钩子函数中
    • 数据拿到了, 真实DOM也拿到了
  • 这个钩子函数在项目:
    • DOM操作就可以进行了, 第三方库的实例化
      总结 : 由上对比,我们可以知道, 数据请求越提前越好一些, created常用于数据的请求和数据的修改, 第三方库的实例化常在mounted中进行书写
html:
<div id="app">
   <life-circle></life-circle>
</div>
<template id="life-circle">
   <div>
   	<h3> 组件生命周期的 初始化阶段 </h3>
   	<p> {{ msg }} </p>
   </div>
</template>
Js:
Vue.component('LifeCircle',{
   template: '#life-circle',
   data () {
     return {
       msg: 'hello vue.js'
     }
   },
   // 初始化阶段钩子函数
   beforeCreate () { //表示组件创建前的准备工作( 初始化事件和生命周期 )     ----  小孩降生前的准备工作
     /* 
       组件未创建, 所以没有this , 数据拿不到 , DOM也拿不到
     */
     console.log('01-beforeCreate');
     console.log( 'data',this.msg )
     console.log( 'DOM',document.querySelector('p'))
     /* axios({
             url: './data.json'
           })
             .then( res => {
               this.msg = res 
             })
             .catch( error => console.log(error))
     */
   },
   created () { // 组件创建结束
     console.log('02-created')
     console.log( 'data',this.msg )
     console.log( 'DOM',document.querySelector('p'))
 	 /* axios({
       url: './data.json'
     })
       .then( res => {
         this.msg = res 
       })
       .catch( error => console.log(error)) */
     
   },
   beforeMount () { 
     console.log( '03-beforeMounte' )
     console.log( 'data',this.msg )
     console.log( 'DOM',document.querySelector('p'))
   	/*axios({
       url: './data.json'
     })
       .then( res => {
         this.msg = res 
       })
       .catch( error => console.log(error)) */
   },
   mounted () {
     console.log('04-mounted')
     console.log('data',this.msg)
     console.log('Real DOM',document.querySelector('p'))
     axios({
       url: './data.json'
     })
       .then( res => {
         this.msg = res 
       })
       .catch( error => console.log(error))
   }
 })
 new Vue({
  
 }).$mount('#app')
1.2 运行中阶段
  • 运行中阶段一共有两个钩子函数
    • beforeUpdate
      • 表示数据更新前的准备工作
      • 这个钩子不主动执行,当数据修改了, 才会执行
      • 这个钩子函数中
        • 数据拿到了, 并且拿到的是修改后的数据
        • DOM也输出了
      • 这个钩子函数更多的工作内容为:生成新的 VDOM , 然后通过diff算法(Patch )进行两次VDOM 对比
      • 这个钩子在项目中
        • 因为他主要做的事情是内部进行的, 所以对我们而言没有太多的操作意义
    • updated
    • 表示数据更新结束, 通过render函数渲染真实DOM
      • 这个钩子函数的执行也是, 当数据修改的时候才执行
      • 这个钩子函数中
        • 数据拿到了, DOM也拿到了
      • 这个钩子在项目中
        • 也是进行第三方库的实例化( DOM是改变的 )
  • 总结: 数据更新, 也要进行DOM操作那么, 我们使用update这个钩子
html:
<div id="app">
	<life-circle></life-circle>
</div>
<template id="life-circle">
	<div>
		<h3> 运行中阶段 </h3>
		<p> {{ msg }} </p>
	</div>
</template>
Js:
Vue.component('LifeCircle',{
	template: '#life-circle',
	data () {
		return {
			msg: 'hello'
		}
	},
	beforeUpdate () { 
		console.log( 'beforeUpdate' )
		console.log( 'data', this.msg)
		console.log( 'DOM', document.querySelector('p') )
	},
	updated () {
		console.log( 'updated' )
		console.log( 'data', this.msg )
		console.log( 'DOM' , document.querySelector('p') )
		// document.querySelector('p').style.background = 'red'
	}
})
new Vue({
	el: '#app'
})
1.3 销毁阶段

通过过开关销毁
这个组件真实DOM也会被删除掉(v-if)
通过调用vm.$destroy()
这个vue的组件的被删除了, 但是它的真实DOM的html结构还在
包含两个钩子函数
beforeDestroy
destroyed
这两个钩子无差别
这两个钩子在项目中
做善后工作 , 手动清除一些计时器, 和一些方法, 还有第三方实例化出来的对象
我们建议大家使用开关的形式来操作组件的销毁和创建

Html:
<div id="app">
	<button @click = 'flag = !flag'> 销毁 </button>
	<life-circle v-if = "flag"></life-circle>
</div>
<template id="life-circle">
	<div>
		<h3> 销毁阶段 </h3>
		<button @click = 'destroy'> 销毁 </button>
	</div>
</template>
Js:
Vue.component('LifeCircle',{
	template: '#life-circle',
	methods: {
		destroy(){
		this.$destroy()
	}
	},
	created () {
		this.timer = setInterval( () => {
			console.log('1')
		},1000)
	},
	beforeDestroy () {
		console.log('beforeDestory')
	},
	destroyed () {
		console.log('destroyed')
		clearInterval( this.timer )
		// 如果是用$destroy这个方法来清除组件, 那么我们必须手动清除这个组件的外壳
		document.querySelector('#app div').remove()
	}
})
new Vue({
	el: '#app',
	data: {
		flag: true
	}
})

案例 : 第三方库的实例化(swiper4)

真实DOM存在了, 才能实例化

数据直接写死 Mounted()
DOM就没有渲染
数据直接有了

Css:
.swiper-container {
	width: 600px;
	height: 300px;
}
Html:
<div id="app">
	<my-swiper></my-swiper>
</div>
<template id="my-swiper">
	<div>
		<input type="text" v-model = 'count'>
		<!-- swiper--start -->
			<div class="swiper-container">
				<div class="swiper-wrapper">
				<div class="swiper-slide"
				v-for = " item in swiperLists"
				:key = "item.id"
				>
				<img :src="item.src" alt="">
			</div>
			</div>
				<!-- 如果需要分页器 -->
				<div class="swiper-pagination"></div>
				<!-- 如果需要导航按钮 -->
				<div class="swiper-button-prev"></div>
				<div class="swiper-button-next"></div>
				<!-- 如果需要滚动条 -->
				<div class="swiper-scrollbar"></div>
			</div>
		<!-- swiper--end -->
	</div>
</template>
Js:
Vue.component('MySwiper',{
   template: '#my-swiper',
   data () {
   	return {
   		swiper:[{
   		"id": 1,
   		"src": "https://m.360buyimg.com/babel/jfs/t1/38920/7/978/98861/5cbb35f6E9289f045/9372bac08d061fdc.jpg"
   		},
   		{
   		"id": 2,
   		"src": "https://img1.360buyimg.com/da/jfs/t1/36709/25/3628/65612/5cb9417bE5b30fdff/5cf6415bc396c9d0.jpg"
   		},
   		{
   		"id": 3,
   		"src": "https://m.360buyimg.com/babel/jfs/t1/38920/7/978/98861/5cbb35f6E9289f045/9372bac08d061fdc.jpg"
   		}]
   	}
   },
   mounted () {
   	this.swiper = new Swiper ('.swiper-container', {
   		loop: true, // 循环模式选项
   		navigation: {
   			nextEl: '.swiper-button-next',
   			prevEl: '.swiper-button-prev',
   		}
   	})
   }
})
new Vue({
   el: '#app'
})

数据请求 updated
我们常规是往 updated 钩子里面写, 但是遇到问题了?
问题是: 当我们有其他数据更新时,updated钩子就会重复触发, 也就是说第三方库要重复实例化
解决:
在updated钩子中添加判断条件, if(!this.swiper){}
在数据请求里面写, 但是发现无法获得真实DOM
将实例化代码发到异步队列
setTimeout(function(){},0) 将实例化代码发到这里面 [不推荐]
Vue.nextTick() /this.$nextTick 优先使用
概念: nextTick表示DOM渲染之后执行的业务

Css:
.swiper-container {
width: 600px;
height: 300px;
}
Html:
 <div id="app">
   <my-swiper></my-swiper>
 </div>
 <template id="my-swiper">
   <div>
     <input type="text" v-model = 'count'>
     <!-- swiper--start -->
       <div class="swiper-container">
           <div class="swiper-wrapper">
               <div class="swiper-slide"
                 v-for = " item in swiperLists"
                 :key = "item.id"
               >
                 <img :src="item.src" alt="">
               </div>
           </div>
           <!-- 如果需要分页器 -->
           <div class="swiper-pagination"></div>
           
           <!-- 如果需要导航按钮 -->
           <div class="swiper-button-prev"></div>
           <div class="swiper-button-next"></div>
           
           <!-- 如果需要滚动条 -->
           <div class="swiper-scrollbar"></div>
       </div>
     <!-- swiper--end -->
   </div>
 </template>
Js:
Vue.component('MySwiper',{
   template: '#my-swiper',
   data () {
     return {
       swiperLists: null,
       count: 0
     }
   },
   created () {
     axios({
       url: './swiper.json'
     })
       .then( res => {
         this.swiperLists = res.data 
   /*       setTimeout( ()=> {
           this.swiper = new Swiper ('.swiper-container', {
             loop: true, // 循环模式选项
             navigation: {
               nextEl: '.swiper-button-next',
               prevEl: '.swiper-button-prev',
             }
           }) 

         },0) */

         Vue.nextTick(()=>{
           this.swiper = new Swiper ('.swiper-container', {
             loop: true, // 循环模式选项
             navigation: {
               nextEl: '.swiper-button-next',
               prevEl: '.swiper-button-prev',
             }
           }) 
         })

       })
       .catch( error => {
         if( error ){
           throw error
         }
       })
   },
   updated () {
     // if( !this.swiper ){
     //   this.swiper = new Swiper ('.swiper-container', {
     //       loop: true, // 循环模式选项
     //       navigation: {
     //         nextEl: '.swiper-button-next',
     //         prevEl: '.swiper-button-prev',
     //       }
     //     })  
     // }
   }
 })
 new Vue({
   el: '#app'
 })
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值