VUE2 学习笔记9 生命周期
vue2内置了很多生命周期函数,也叫生命周期钩子、生命周期回调函数等。
每个函数会在vue运行的特定时机触发。在生命周期函数内部,this指向vm实例或组件。生命周期函数的名称是不可以修改的。
vue提供了beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestory、destoryed四对函数。除这四对八个钩子之外,vue还有其他三个生命周期钩子,这三个钩子涉及路由,会在学路由的时候介绍。
整个生命周期图示如下:
先分析整个生命周期,当创建vue实例,也就是new Vue()之后,vue的生命周期就开始了。
一开始进入Init 初始化事件和生命周期阶段,在这个时候,会指定一些规则,涉及生命周期函数(有哪几个、命名、何时调用等),事件(规定一些vue内置的事件处理机制,比如定义修饰符等),但在这个阶段,还未开始数据代理,也就是说在new Vue时传入的data,vm还没有收到,vm上也就没有_data,不能够获取配置的data数据。
然后会调用beforeCreate函数。
在beforeCreate函数中,由于数据代理还没有完成,所以无法访问data中的数据,也无法使用methods中定义的方法。而且this中的很多value值还是null或者undefined。
然后进入init 数据监测 数据代理 初始化,在这个阶段,初始化数据监测(vue对data中的对象、数组等添加监测,给属性赋予get、set、给数组方法进行包装,在数组修改的方法中添加模板解析更新的逻辑等)、数据代理(给vm添加_data等)。
调用created函数,在created中,由于已经完成了数据代理和数据监测,在created中可以获得data和methods。
然后vue会分析new Vue时是否传递了el配置项,如果没有el,则会去找vm.$mount的配置,然后会继续判断是否配置了template配置项(vue容器中可以什么内容都不写,容器中的内容可以通过template配置,在template中,只能有一个根节点,且根节点不能是template标签,且配置template时,el绑定的选择器所在的标签也会被template替换),如果配置了template,会编译template的内容替换vue模板,如果没有配置template,会编译el配置的outerHTML作为template(此时整个el对应的容器都是模板,也包括el对应的选择器所在的标签本身)。在这个过程中,vue开始解析模板,也就是说,会对vue模板中的vue指令进行解析,生成虚拟DOM,把虚拟DOM存在内存中,但虚拟DOM还没转换为真实DOM,页面也还不能显示解析好的内容。
调用beforeMount函数,在beforeMount中,页面呈现的是未经编译的DOM结构。在这个时间点,虽然vue已经完成了对模板的解析,但是由于解析好的内容还没有挂载到页面上,因此页面上显示的是未经编译的内容。所有对DOM的操作,最终都是不生效的。也就是说,虽然对DOM的操作,可以奏效一瞬间,但最后对DOM的修改会失效。因为在beforeMount函数执行之后,页面上的内容会被切换为真实DOM,刚刚对DOM进行的操作都会被覆盖。
然后会创建vm.$el(vue把刚才生成的虚拟DOM转换为真实DOM,把真实DOM往vm.$el存了一份),并且替换掉整个el容器。也就是说,在这个阶段,vue将内存中的虚拟DOM转换为真实DOM并且插入页面。
挂载:vue解析模版,把初始的模版转换为虚拟DOM,把虚拟DOM再转换成真实DOM,而vue把真实DOM放入页面的过程,就叫做挂载。
调用mounted函数,mounted在vue完成模板的初次解析并且完成挂载后调用。在mounted函数中,页面已经完成挂载,页面上呈现的是经过编译的DOM。在mounted中,对DOM的操作都会生效,但一般不推荐在vue中通过操作DOM的方式实现功能。因为vue的逻辑是声明式的。在mounted函数被执行时,代表vue的初始化过程结束了,一般在mounted函数中开启定时器、发送网络请求、进行消息订阅,绑定自定义事件等。
mounted在整个生命周期中只调用一次。如果是页面初次加载完成后,页面中的数据发生变化,引起模版再次解析,mounted也不会被调用,之后页面数据变化引起的再次解析属于更新。
在页面运行过程中,如果页面内容需要发生更新,就会涉及beforeUpdate和update。当vue发现数据更新时,就会立刻调用beforeUpdate。在beforeUpdate中,后台的数据是新的,但页面的数据未来得及更新,还是旧值。
然后会进行虚拟DOM的重新渲染和新旧虚拟DOM的对比。在这个阶段,vue会根据新数据,生成新的虚拟DOM,和旧的虚拟DOM进行比较,最终完成页面数据从数据到视图的更新。
调用updated。在updated中,由于已经完成了真实DOM的更新,因此此时后台数据的是新的,页面上的数据也是新的。在updated中,页面数据和后台数据是保持同步的。
当vm上的$destroy方法被调用时(这个方法可以主动调用,也可以被其他组件调用,当调用这个方法时,会完全销毁实例,并且清理他和其他组件实例的连接,解绑全部指令及自定义事件监听器(但对于通过Dom绑定的事件,是无法撤销的,在实例销毁后,事件也可以触发,但页面无法维护)。虽然vm销毁了,但vm运行时留存的页面内容并不会被删除,只不过页面内容无法进行任何维护了,销毁只是销毁vue和容器的绑定),进入销毁阶段,$destroy会触发beforeDestroy。
beforeDestroy函数。在beforeDestroy函数中,实例还未销毁,此时vm中所有data、methods、指令等都还是可用状态,是马上要执行销毁之前(但这种可用,是可以对数据、方法等进行访问和调用,但是即使调用了数据和方法,页面上的数据并不会进行相应的改变,这是由于在进入销毁阶段后,就无法调用beforeUpdate和update,也就是说,在销毁阶段进行的修改都无法触发更新,也就都无法在页面上生效,只能在后台生效),一般在这个阶段不进行数据的修改和方法的调用,一般是进行关闭定时器、取消订阅消息、解绑自定义事件等操作。
然后会移除所有的监视事件、子组件、以及自定义事件监听器。
实例销毁完毕后,会调用destroyed。