国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Vue.js中輕松解決v-for執(zhí)行出錯的三個方案

2019-11-19 16:23:03
字體:
供稿:網(wǎng)友

前言

Vue.js 是開源的一個前端開發(fā)庫,通過簡潔的 API 提供高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng)。在前端紛繁復(fù)雜的生態(tài)中,Vue.js在近年來受到一定程度的關(guān)注,目前在 GitHub上已經(jīng)有5000+。

本文是筆者在開發(fā)實踐中踩過的坑,總結(jié)和分享出來,希望對大家學(xué)習(xí)Vue有所幫助。下面來看看詳細(xì)的介紹:

【問題描述】

v-for遍歷數(shù)組中存在空值導(dǎo)致頁面報錯,情況如下:

開發(fā)框架是以Vue為模型綁定的核心,根據(jù)錯誤可以進行一個簡單的判斷:

      ▪ removeChild操作既然不是發(fā)生在開發(fā)者顯示書寫的代碼中,就應(yīng)該是模型銷毀后Vue引擎移除dom節(jié)點導(dǎo)致的。

      ▪ 錯誤棧信息都在框架的代碼之內(nèi),此操作不可能是有用戶代碼觸發(fā)導(dǎo)致的。

開發(fā)者某一流程的操作,會100%穩(wěn)定地觸發(fā)出這一錯誤,此錯誤導(dǎo)致js執(zhí)行終端,整個程序陷入癱瘓無法工作,開發(fā)者的操作流程可以簡化為如下的步驟:

      1. 訪問視圖A。

      2. 訪問視圖B。

      3. 回退歷史記錄到A。(錯誤發(fā)生在這里)

以上的跳轉(zhuǎn)關(guān)系都是視圖跳轉(zhuǎn),也就是發(fā)生在路由系統(tǒng)之內(nèi)的路由跳轉(zhuǎn),按照路由邏輯,第三步的時候會依次執(zhí)行視圖的聲明周期函數(shù),包括:

      ▪ B視圖的unRender邏輯,包括beforeUnRender和afterUnRender。

      ▪ A視圖的Render,包括beforeRender和afterRender。

開發(fā)者只在beforeRender的階段進行了模型重置的操作,幾乎可以確定無疑,報錯就是由這幾行模型重置和賦值的操作引起的。層層排除可以尋找到使用簡單代碼重新此問題的方式。

【重現(xiàn)方式】

準(zhǔn)備一個簡單的空工程,新建視圖test,一下的代碼分別為js/view/test.js和html/view/test.html,js/view/test.js中視圖對模型的操作可以完整反映重現(xiàn)此問題的流程。其中,setTimeout模擬的是ajax操作以讓數(shù)據(jù)在多個tick之后設(shè)置到模型以觀察Vue對dom節(jié)點的創(chuàng)建和銷毀。

$nextTick之后,將test_arr置空的操作是為了使vue將此數(shù)據(jù)對應(yīng)的dom節(jié)點銷毀,對應(yīng)代碼如下:

以上的代碼可以穩(wěn)定重新問題,下面是解題思路。

【解決方案】

在不求甚解的狀態(tài)下,這個問題是比較容易解決的,這里有幾個臨時的解決方案。

▲方案一

從報錯信息Uncaught TypeError: Cannot read property 'removeChild' of null可知,之所以發(fā)生這個問題是因為在null的對象上執(zhí)行了removeChild。

修改Vue框架代碼,將這里的代碼:

修改為:


▲方案二

深入地分析,為什么el.parentNode會是null,通過上面重現(xiàn)的步驟發(fā)現(xiàn),當(dāng)that.model.test_arr = ["","4","","5","6",""]這段代碼設(shè)置發(fā)生后,v-for產(chǎn)生的dom節(jié)點之后3個,而不是5個,這種情況下el.parentNode就是不存在的,所以產(chǎn)生了第二種解決方案,強制不給空數(shù)據(jù)的元素生成dom節(jié)點。


▲方案三

問題并不算是圓滿解決,正常的情況下框架應(yīng)該具有魯棒性,適應(yīng)不同的使用場景,不應(yīng)該出現(xiàn)js報錯的問題,所以還有深入研究下去的必要。

在Vue中針對v-for指令有一個track-by的可選配置:

       ▪無track-by情況:數(shù)據(jù)修改時,無論值是否被修改,dom都被重新渲染。

       ▪有track-by情況:數(shù)據(jù)修改時,不變數(shù)據(jù)所在的dom不被重新渲染,已改變的數(shù)據(jù)所在dom才被重新渲染。

因為 v-for 默認(rèn)通過數(shù)據(jù)對象的特征來決定對已有作用域和 DOM 元素的復(fù)用程度,這可能導(dǎo)致重新渲染整個列表。但是,如果每個對象都有一個唯一 ID 的屬性,便可以使用 track-by 特性給 Vue 一個提示,Vue因而能盡可能地復(fù)用已有實例。所以就有了第三種解決方案。


【原因分析】

v-for遍歷數(shù)組中存在空值導(dǎo)致頁面報錯,主要是遍歷條件里對值的判斷有問題。Vue為了保證對dom節(jié)點的復(fù)用,內(nèi)置了一份按照id存取的dom緩存,通過對數(shù)據(jù)分析出dom_id,然后根據(jù)此id從緩存中獲取dom節(jié)點。由于不同的數(shù)據(jù)取到了相同的dom_id,所以沒有創(chuàng)建dom節(jié)點出來。但是,在最終數(shù)組置空,模型變更之后dom節(jié)點移除的時候卻為這些dom節(jié)點觸發(fā)了remove操作,也就是方案一中兼容的那些代碼:


所以問題必定出現(xiàn)在getTrackByKey這個函數(shù)的執(zhí)行上,以下是getTrackByKey的代碼:


Vue中對數(shù)據(jù)綁定的操作大大地提高了開發(fā)者應(yīng)用開發(fā)的效率,但與此同時也伴隨著一些不易察覺的問題,尤其如本文中問題的重現(xiàn)條件比較復(fù)雜的情況下,測試不一定可以覆蓋到問題的觸發(fā)條件,這個時候就需要開發(fā)人員多一分警惕。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對武林網(wǎng)的支持。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 汶上县| 连江县| 阿尔山市| 怀远县| 东光县| 城步| 土默特左旗| 泰顺县| 乌拉特后旗| 泰州市| 筠连县| 田东县| 潞西市| 海兴县| 昌都县| 道真| 崇文区| 淳安县| 图们市| 方山县| 彩票| 绵竹市| 嘉定区| 百色市| 杭锦后旗| 阿瓦提县| 红安县| 舟曲县| 文水县| 哈巴河县| 抚州市| 青岛市| 荣成市| 通河县| 土默特右旗| 洪泽县| 鄯善县| 南平市| 方山县| 赞皇县| 额济纳旗|