日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

异步加载在Vue生命周期哪个阶段更合理

發布時間:2024/9/21 vue 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步加载在Vue生命周期哪个阶段更合理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

react高階面試題中有這么一道:為什么異步請求數據在didMount階段更合適?同為MVVM中的翹楚,Vue是否也有類似問題呢?另外,我在平時也無開發過程中也會發現,每個人選擇的那個生命周期階段去異步請求數據總會不一樣,因此引發思考,到底哪個階段更適合異步請求數據呢?在產品設計和用戶體驗方面又會有哪些影響?本篇記錄就是為了解決這兩個問題。

一、Vue生命周期

首先再老話重提過一下Vue生命周期,以及每個階段都做了什么事。

1. beforeCreated:生成$options選項,并給實例添加生命周期相關屬性。在實例初始化之后,在 數據觀測(data observer) 和event/watcher 事件配置之前被調用,也就是說,data,watcher,methods都不存在這個階段。但是有一個對象存在,那就是$route,因此此階段就可以根據路由信息進行重定向等操作。

2. created:初始化與依賴注入相關的操作,會遍歷傳入methods的選項,初始化選項數據,從$options獲取數據選項(vm.$options.data),給數據添加‘觀察器’對象并創建觀察器,定義getter、setter存儲器屬性。在實例創建之后被調用,該階段可以訪問data,使用watcher、events、methods,也就是說 數據觀測(data observer) 和event/watcher 事件配置 已完成。但是此時dom還沒有被掛載。該階段允許執行http請求操作。

3. beforeMount:將HTML解析生成AST節點,再根據AST節點動態生成渲染函數。相關render函數首次被調用(劃重點)。

4. mounted:在掛載完成之后被調用,執行render函數生成虛擬dom,創建真實dom替換虛擬dom,并掛載到實例。可以操作dom,比如事件監聽

5. beforeUpdate:$vm.data更新之后,虛擬dom重新渲染之前被調用。在這個鉤子可以修改$vm.data,并不會觸發附加的沖渲染過程。

6. updated:虛擬dom重新渲染后調用,若再次修改$vm.data,會再次觸發beforeUpdate、updated,進入死循環。

7. beforeDestroy:實例被銷毀前調用,也就是說在這個階段還是可以調用實例的。

8. destroyed:實例被銷毀后調用,所有的事件監聽器已被移除,子實例被銷毀。

總結來說,虛擬dom開始渲染是在beforeMount時,dom實例掛載完成在mounted階段顯示。

那么接下來了解就是render函數。

render示例:export default {data () {return {menu_items: [] // 請求返回如:[{fullname: '頁面一'},{fullname: '頁面二'},{fullname: '頁面三'},{fullname: '頁面四'}]}},   render (createElement){    return createElement(// 1. 第一個參數,要渲染的標簽名稱(必填)'ul',// 2. 第二個參數,1中要渲染的標簽的屬性,或者文本元素(可選)      { class: {'uk-nav': true}, }, // 3. 第三個參數,1中標簽的子元素,詳情看官方文檔(可選)this.menu_items.map(item=>createElement('li',item.fullname))))  }}復制代碼

render函數最終返回的是createNodeDescription(節點描述),即俗稱virtual node(虛擬節點)。用template寫的話,就是下面這樣:

<template><ul>  <li v-for="item in menu_items">     {{ item.fullname }}     </li>  </ul></template>復制代碼

這個過程在mounted被調用前完成。詳細參考可移步 這里

二、異步加載

setTimeout等異步函數

異步函數跟同步函數的不同之處,最大的應該就是異步函數會等到所有同步函數執行完成之后再執行。具體的可以看 事件循環 。

//data字段有個num created: function () {console.group('created 創建完畢狀態===============》')console.log('%c%s', 'color:red', 'el : ' + this.$el) // undefinedconsole.log('%c%s', 'color:red', 'data : ' + this.$data) // 已被初始化console.log('%c%s', 'color:red', 'message: ' + this.message) // 已被初始化//新增代碼片段setTimeout(() => { //這里只是為了偷懶用了ES6的箭頭函數,如果是普通函數請注意this指針修改,vue中請不要濫用箭頭函數,出了問題找都找不到this.num ++this.num += 2}, 0) //注意這里的延時都是0setTimeout(() => {this.num -= 5}, 0)}復制代碼

控制臺答應結果:


(略失真。。。截圖太大稍微壓縮了下!!--)

vue在執行代碼的時候,并沒有去管定時器里發生了什么事情,甚至已經設置了0延時,他依舊會去順序執行其他生命周期,看起來就像跳過了這些異步加載。因此可以確定一點,生命周期中的異步操作不會按照順序執行,而是會等到非異步操作結束后執行。因此書寫這部分代碼的時候請注意里面的邏輯不要和順序掛鉤,要確保任何異步操作即使最后執行,之前的程序也不會發生異常從而阻塞整個進程。

ajax異步請求

ajax請求是異步操作,回調函數的執行時間是不確定的。也就是說,即使在created鉤子發送請求,dom被掛載之后請求仍沒有返回結果,就很有可能導致運行出錯,諸如:


因為此時上述render事例中的menu_items還是空置。

解決方案

針對ajax異步請求,這樣的錯誤原因其實就是因為返回結果沒趕上dom節點的渲染。所以可以從兩方面做修改:一是返回結果的賦值變量上,另一個就是dom節點的渲染層面。

1. 給予賦值變量初始值,即定義時menu_items:[ {fullname: ''} ]。

這么做的好處就是頁面節點的渲染不受限于返回結果,靜態文案照樣會被渲染,動態數據則會在數據更新時被填充。給用戶的感覺就是,頁面渲染速度不錯。

但是這種方式也有缺陷,后臺返回數據字段不盡相同,要是都這么寫那就真是麻煩了。

當然如果你使用typescript就沒有這種煩惱,menu_items: { [propName: string]: any } = {}就搞定了。

2. v-if,控制dom節點的掛載,當且僅當menu_items被賦予返回值時,才開始渲染節點。

這么做的好處就是靜態和動態文案同步展現在用戶面前,不會有文案跳動,數據從無到有的過程。但是,副作用就是頁面渲染時間、用戶等待時間變長。

那如果dom掛載前請求數據已經返回了,又會是怎樣的結果呢?

我們可以用setTimeout來模擬一下這個過程

<span>{{person.name.firstName}}</span> data: function () {return {message: 'hello world',add: 1,person: {name: {}}}}, created: function () {console.group('created 創建完畢狀態===============》')console.log('%c%s', 'color:red', 'el : ' + this.$el) // undefinedconsole.log('%c%s', 'color:red', 'data : ' + this.$data) // 已被初始化console.log('%c%s', 'color:red', 'message: ' + this.message) // 已被初始化//假裝接口返回了一些信息給你,如一個人,然后你把這些信息賦值給了this實力setTimeout(() => {this.person = {name: {lastName: 'carry',firstName: 'dong'},sex: '男'}}, 0)復制代碼

請求夠早了吧,但還是報錯了,this.person.name.firstName 是 undefined,不過程序報完錯后還是再繼續執行了。

三、結論

既然異步函數并不會阻塞vue生命周期整個進程,那么在哪個階段請求都可以。如果考慮到用戶體驗方面的影響,希望用戶今早感知頁面已加載,減少空白頁面時間,建議就放在created階段了,然后再處理會出現null、undefined這種情況就好。畢竟越早獲取數據,在mounted實例掛載的時候渲染也就越及時。

當然即使是這種情況下,也不排除會觸發updated生命鉤子(data有默認值且已渲染,之后數據被更新),從而導致虛擬dom的重新渲染。



與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的异步加载在Vue生命周期哪个阶段更合理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。