生命周期
生命周期是指一个组件从创建->运行->销毁的整个阶段,强调的是一个时间段。
生命周期函数
生命周期函数(比如beforeCreate)是由vue提供的内置函数,会伴随着组件的生命周期,自动按次序执行。强调的是一个时间点。
它有三个阶段,分别包含以下生命周期函数。
创建阶段
- beforeCreate
- created
- beforeMount
- mounted
运行阶段
- beforeUpdate
- updated
销毁阶段
- beforeDestroy
- destroyed
声明周期图
下图是vue官方给的生命周期参考图。
methods:{ show(){ console.log('调用了life组件') } }, created(){ //在created生命周期函数阶段下,methods都已经创建好,且是可用状态,故可以进行调用。 this.show() } }
created生命周期函数经常用在ajax中请求数据,即当执行到created阶段,立马去调用请求数据的方法,并且把请求到的数据,转存到data中,供template模版渲染的时候使用。
当数据发生变化之后,未来能够操作到最新的dom结构,必须把操作代码写到updated生命周期函数中,因为这个生命周期函数下的dom结构是同步于最新的数据。相反beforeUpdate就不是,它只是有了最新数据,并没有同步到dom结构中。
数据共享
父向子传值
父组件向子组件共享数据需要使用自定义属性。即子组件通过自定义属性props来接收父组件传过来的数据。
简单类型数据是复制一份值再传过去;复杂数据类型是把它的引用给传过去。
父组件
<left :mes:"message"></left> ... export default{ data(){ return{ message:'zzl' } } components:{ 'left': left,//键值相同,可以省略 right, life } }
子组件
<p>mes={{mes}}</p> export default{ props:['mes'] }
子向父传值
子组件向父组件共享数据使用自定义事件,也就是@click的写法与理解。
子组件
export default{ data(){ return {count:0} }, methods:{ add(){ this.count+=1 //修改数据时,通过调用$emit()触发自定义事件numchange this.$emit('numchange',this.count) } } }
父组件
<biaoqian @numchange="getNewCount"> <!--如果指定的方法不带有小括号,则它默认自带事件对象numchange传过来的值, 如果带有小括号,即里面是该方法自己接收除事件对象传过来的值,即覆盖了默认值。 但是此时方法里面传入$event的话, 一样还是会拿到事件对象传过来的值,即方法有了两个值。 也可根据前面写的Vue初始文章的事件对象来理解上面的内容。--> </biaoqian> export default{ data(){ return{ countFromLeft:0 } }, methods:{ //自定义getNewCount事件处理函数,接收子组件传过来的值 getNewCount(val){ console.log('dd') this.countFromLeft=val } } }
兄弟组件之间的数据共享
在vue2中,兄弟组件之间的数据共享用EventBus。
- 创建eventBus.js模块,并向外共享一个Vue的实例对象
- 在数据发送方,调用bus.$emit(‘事件名称’,要发送的数据)方法触发自定义事件
- 在数据接收方,调用bus.$on(‘事件名称’,事件处理函数)方法注册一个自定义事件
兄弟组件A(数据发送方)
<button @click="send">发送</button> ... <script> import bus from './eventBus.js' export default{ data(){ return { str:'zzl' } }, methods:{ send(){ bus.$emit('fenxiang',this.str) } } } </script>
eventBus.js
import Vue from 'vue' //向外共享Vue的实例对象 export default new Vue()
兄弟组件C(数据接收方)
<script> import bus from './eventBus.js' export default{ data(){ return{ msgFromLeft:'' } }, //在这个created生命周期函数 created(){ bus.$on('fenxiang',valstr=>{ this.msgFromLeft=valstr //console.log(this.msgFromLeft) }) } } </script>
on是用来声明事件的,emit是用来触发事件的。
ref引用
引用dom
ref可以在不依赖于jQuery的情况下,获取和操作dom元素或组件的引用。
<template> <div class="rootbox"> <h1 ref="myh1">App根组件</h1> <button @click="showThis">打印</button> </div> </template> <script> export default{ methods:{ showThis(){ // console.log(this.$refs.myh1) this.$refs.myh1.style.color="red" } } } </script>
引用组件
ref也可以引用页面上的组件实例。
<button @click="onrel">重置left</button> comLeft是组件的实例 <left ref="comLeft"></left> ... export default{ methods:{ onrel(){ //直接操作子组件的属性值 // this.$refs.comLeft.count=0 //直接操作子组件的方法 this.$refs.comLeft.rel() } }, components:{ 'left': left,//键值相同,可以省略 right, life } }
this.$nextTick(callback)方法
当dom根据渲染好的数据重新更新好了dom,才会调用这个回调函数,相当于延迟了。
也可以这样理解,即等组件的dom元素更新完之后,再去执行回调函数。
<input type="text" v-if="inputflag" @blur="showbutton" ref="iptRef"/> methods:{ showinput(){ //切换布尔值,展示输入框 this.inputflag=true//将要把文本框展示出来,但是此时只是把布尔值改为true而已,页面还没来得及更新,所以页面上还是按钮,并没有文本框,所以拿不到文本框的引用,又所以下面的iptRef拿不到, //this.$refs.iptRef.focus()此时这样会报错,因为此时的iptRef拿不到, //此时会根据上面的布尔值重新渲染完页面(有了文本框)之后再去执行这个回调函数。 this.$nextTick(()=>{ this.$refs.iptRef.focus()//自动获得焦点 }) } }