阅读:8287回复:3
对vue生命周期/钩子函数的理解对于实现页面逻辑交互等效果,我们必须知晓vue的生命周期,才能愉快的玩耍,知道我们写的东西应该挂载到哪里,vue官方给出的api讲解的那叫一个简单啊,如下: 所有的生命周期钩子自动绑定this上下文到实例中,因此你可以访问数据,对属性和方法进行运算。这意味着你不能使用箭头函数来定义一个生命周期方法(例如created: () => this.fetchTodos())。这是因为箭头函数绑定了父上下文,因此this与你期待的 Vue 实例不同,this.fetchTodos的行为未定义。 下面附加一张生命周期图示 生命周期
|
|
沙发#
发布于:2020-03-11 21:24
详解:
select2 图中的select的option都是通过异步请求得到的,然后通过v-for渲染进去,到此一切看起来很正常。还有一个需求是当页面刷新后要保留上次一查询的条件。我通过vue-router来给select指定一个默认选项; <template v-for='(item, index) in agentList.name' > <option v-if='item == name' :key='index' selected :value="item">pw_item</option> <option v-else :key='index' :value="item">pw_item</option> </template> 那么问题就来了,option的获得是一个异步请求,那这个请求完成的时刻和mounted的顺序是什么?如果mounted在请求成功之前执行,那将很遗憾——默认选项会设置失败 option有默认效果的是130,select中的值还是保持全部 什么时候执行$('select').select2(),是解决这个问题的关键。大家肯定猜到了,mounted的确是在请求成功之前执行的,所以这时的办法就是将$('select').select2()的执行放到请求成功的回调里执行: $.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => { const a = this.agentList, d = res.data; a.id = d.orgIds; a.name = d.orgNames; a.city = d.cityMap; $('select').select2(); }); 本以为这样就完美解决了,但是发现还是会出现和上图一样的效果;如何是好?这时轮到vm.$nextTick登场了: 说明: 将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。 官方示例代码: new Vue({ // ... methods: { // ... example: function () { // 修改数据 this.message = 'changed' // DOM 还没有更新 this.$nextTick(function () { // DOM 现在更新了 // `this` 绑定到当前实例 this.doSomethingElse() }) } } }) 所以我的解决办法如下: $.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => { const a = this.agentList, d = res.data; a.id = d.orgIds; a.name = d.orgNames; a.city = d.cityMap; this.$nextTick(() => { $('select').select2(); }); }); 至此这个问题才算比较满意的解决 |
|
板凳#
发布于:2020-03-11 21:24
|
|
地板#
发布于:2020-03-11 21:29
Vue 实例中的生命周期钩子 Vue 框架的入口就是 Vue 实例,其实就是框架中的 view model ,它包含页面中的业务 处理逻辑、数据模型等,它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的 过程时更容易形成好的逻辑。 Vue 实例 在文档中经常会使用 vm 这个变量名表示 Vue 实例,在实例化 Vue 时,需要传入一个选 项对象,它可以包含数据(data)、模板(template)、挂载元素(el)、方法(methods)、生 命周期钩子(lifecyclehook)等选项。 Vue 实例化的选项 需要注意的是含 this 的函数大多不要使用箭头函数,因为我们期望 this 指向 Vue 实例。 data Vue 实例的数据都保存在 data 对象中,Vue 将会递归将 data 的属性转换为 getter/setter, 从而让 data 的属性能够响应数据变化。 var data = { a: 1 } // 直接创建一个实例 var vm = new Vue({ data: data }) vm.a // -> 1 vm.$data === data // -> true 这样数据就绑定在 HTML 中,Vue 框架监视 data 的数据变化,自动更新 HTML 内容。 computed 计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue var vm = new Vue({ data: { a: 1 }, computed: { // 仅读取,值只须为函数 aDouble: function () { return this.a * 2 }, // 读取和设置 aPlus: { get: function () { return this.a + 1 }, set: function (v) { this.a = v - 1 } } } }) vm.aPlus // -> 2 vm.aPlus = 3 vm.a // -> 2 vm.aDouble // -> 4 这里可以省略setter,如果省略了setter,那么值就可以是普通函数,但是必须有返回值。 methods methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达 var vm = new Vue({ data: { a: 1 }, methods: { plus: function () { this.a++ } } }) vm.plus() vm.a // 2 看下面这个例子,methods 和 computed 看起来可以做同样的事情,单纯看结果两种方式确实是相同的。 然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变 时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会 立即返回之前的计算结果,而不必再次执行函数。相比而言,只要发生重新渲染,method 调用总会执行 该函数。 var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // a computed getter reversedMessage: function () { // `this` points to the vm instance return this.message.split('').reverse().join('') } } }) watch 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue var vm = new Vue({ data: { a: 1, b: 2, c: 3 }, watch: { // 监控a变量变化的时候,自动执行此函数 a: function (val, oldVal) { console.log('new: %s, old: %s', val, oldVal) }, // 深度 watcher c: { handler: function (val, oldVal) { /* ... */ }, deep: true } } }) vm.a = 2 // -> new: 2, old: 1 Vue 实例的生命周期 Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列 过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。 在Vue的整个生命周期中,它提供了一些生命周期钩子,给了我们执行自定义逻辑的机会。 接下来我们用几个例子来看看生命周期钩子是怎么用的: 完整的代码托管在 codepen HTML结构: pw_ number 我们对 input 和 p 绑定了data 对象的 number 数据,Vue 实例构建如下: var app = new Vue({ el: '#app', data: { number: 1 } }) 在实例中分别在每个生命周期钩子中 console.log('钩子名称',this.number) 我们发现,第一次页面加载时 触发了 beforeCreate, created, beforeMount, mounted 这几个钩子,data 数据在 created 中可获取到。 再去 console.log('mounted: ', document.getElementsByTagName('p')[0]) ,DOM 渲染在 mounted 中已经 完成。 我们再试着去更改 input 输入框中的内容,可以看到输入框上方的数据同步发生改变,这就是数据绑定的效果,在更 新数据时触发 beforeUpdate 和 updated 钩子,且在 beforeUpdate 触发时,数据已更新完毕。 而 destroy 仅在调用app.$destroy();时触发,对 vue 实例进行销毁。销毁完成后,我们再重新改变 number 的值,vue 不再对此动作 进行响应了。但是原先生成的dom元素还存在,可以这么理解,执行了destroy操作,后续就不再受vue控制了。 Vue.nextTick 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。官方API Vue.nextTick(function () { // DOM 更新了 }) 官方还提供了一种写法,vm.$nextTick,用 this 自动绑定到调用它的实例上 created() { setTimeout(() => { this.number = 100 this.$nextTick(() => { console.log('nextTick', document.getElementsByTagName('p')[0]) }) },100) } 什么时候需要用到Vue.nextTick() 生命周期小结 生命周期钩子的一些使用方法: beforecreate : 可以在这加个loading事件,在加载实例时触发 created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数 beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom |
|