前言
十載的柳州網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營(yíng)銷網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整柳州建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“柳州網(wǎng)站設(shè)計(jì)”,“柳州網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。Vue.js 是開(kāi)源的一個(gè)前端開(kāi)發(fā)庫(kù),通過(guò)簡(jiǎn)潔的 API 提供高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng)。在前端紛繁復(fù)雜的生態(tài)中,Vue.js在近年來(lái)受到一定程度的關(guān)注,目前在 GitHub上已經(jīng)有5000+。
本文是筆者在開(kāi)發(fā)實(shí)踐中踩過(guò)的坑,總結(jié)和分享出來(lái),希望對(duì)大家學(xué)習(xí)Vue有所幫助。下面來(lái)看看詳細(xì)的介紹:
【問(wèn)題描述】
v-for遍歷數(shù)組中存在空值導(dǎo)致頁(yè)面報(bào)錯(cuò),情況如下:
開(kāi)發(fā)框架是以Vue為模型綁定的核心,根據(jù)錯(cuò)誤可以進(jìn)行一個(gè)簡(jiǎn)單的判斷:
▪ removeChild操作既然不是發(fā)生在開(kāi)發(fā)者顯示書寫的代碼中,就應(yīng)該是模型銷毀后Vue引擎移除dom節(jié)點(diǎn)導(dǎo)致的。
▪ 錯(cuò)誤棧信息都在框架的代碼之內(nèi),此操作不可能是有用戶代碼觸發(fā)導(dǎo)致的。
開(kāi)發(fā)者某一流程的操作,會(huì)100%穩(wěn)定地觸發(fā)出這一錯(cuò)誤,此錯(cuò)誤導(dǎo)致js執(zhí)行終端,整個(gè)程序陷入癱瘓無(wú)法工作,開(kāi)發(fā)者的操作流程可以簡(jiǎn)化為如下的步驟:
1. 訪問(wèn)視圖A。
2. 訪問(wèn)視圖B。
3. 回退歷史記錄到A。(錯(cuò)誤發(fā)生在這里)
以上的跳轉(zhuǎn)關(guān)系都是視圖跳轉(zhuǎn),也就是發(fā)生在路由系統(tǒng)之內(nèi)的路由跳轉(zhuǎn),按照路由邏輯,第三步的時(shí)候會(huì)依次執(zhí)行視圖的聲明周期函數(shù),包括:
▪ B視圖的unRender邏輯,包括beforeUnRender和afterUnRender。
▪ A視圖的Render,包括beforeRender和afterRender。
開(kāi)發(fā)者只在beforeRender的階段進(jìn)行了模型重置的操作,幾乎可以確定無(wú)疑,報(bào)錯(cuò)就是由這幾行模型重置和賦值的操作引起的。層層排除可以尋找到使用簡(jiǎn)單代碼重新此問(wèn)題的方式。
【重現(xiàn)方式】
準(zhǔn)備一個(gè)簡(jiǎn)單的空工程,新建視圖test,一下的代碼分別為js/view/test.js和html/view/test.html,js/view/test.js中視圖對(duì)模型的操作可以完整反映重現(xiàn)此問(wèn)題的流程。其中,setTimeout模擬的是ajax操作以讓數(shù)據(jù)在多個(gè)tick之后設(shè)置到模型以觀察Vue對(duì)dom節(jié)點(diǎn)的創(chuàng)建和銷毀。
$nextTick
之后,將test_arr置空的操作是為了使vue將此數(shù)據(jù)對(duì)應(yīng)的dom節(jié)點(diǎn)銷毀,對(duì)應(yīng)代碼如下:
以上的代碼可以穩(wěn)定重新問(wèn)題,下面是解題思路。
【解決方案】
在不求甚解的狀態(tài)下,這個(gè)問(wèn)題是比較容易解決的,這里有幾個(gè)臨時(shí)的解決方案。
▲方案一
從報(bào)錯(cuò)信息Uncaught TypeError: Cannot read property 'removeChild' of null
可知,之所以發(fā)生這個(gè)問(wèn)題是因?yàn)樵趎ull的對(duì)象上執(zhí)行了removeChild。
修改Vue框架代碼,將這里的代碼:
修改為:
▲方案二
深入地分析,為什么el.parentNode
會(huì)是null,通過(guò)上面重現(xiàn)的步驟發(fā)現(xiàn),當(dāng)that.model.test_arr = ["","4","","5","6",""]
這段代碼設(shè)置發(fā)生后,v-for產(chǎn)生的dom節(jié)點(diǎn)之后3個(gè),而不是5個(gè),這種情況下el.parentNode
就是不存在的,所以產(chǎn)生了第二種解決方案,強(qiáng)制不給空數(shù)據(jù)的元素生成dom節(jié)點(diǎn)。
▲方案三
問(wèn)題并不算是圓滿解決,正常的情況下框架應(yīng)該具有魯棒性,適應(yīng)不同的使用場(chǎng)景,不應(yīng)該出現(xiàn)js報(bào)錯(cuò)的問(wèn)題,所以還有深入研究下去的必要。
在Vue中針對(duì)v-for指令有一個(gè)track-by的可選配置:
▪無(wú)track-by情況:數(shù)據(jù)修改時(shí),無(wú)論值是否被修改,dom都被重新渲染。
▪有track-by情況:數(shù)據(jù)修改時(shí),不變數(shù)據(jù)所在的dom不被重新渲染,已改變的數(shù)據(jù)所在dom才被重新渲染。
因?yàn)?v-for 默認(rèn)通過(guò)數(shù)據(jù)對(duì)象的特征來(lái)決定對(duì)已有作用域和 DOM 元素的復(fù)用程度,這可能導(dǎo)致重新渲染整個(gè)列表。但是,如果每個(gè)對(duì)象都有一個(gè)唯一 ID 的屬性,便可以使用 track-by 特性給 Vue 一個(gè)提示,Vue因而能盡可能地復(fù)用已有實(shí)例。所以就有了第三種解決方案。
【原因分析】
v-for遍歷數(shù)組中存在空值導(dǎo)致頁(yè)面報(bào)錯(cuò),主要是遍歷條件里對(duì)值的判斷有問(wèn)題。Vue為了保證對(duì)dom節(jié)點(diǎn)的復(fù)用,內(nèi)置了一份按照id存取的dom緩存,通過(guò)對(duì)數(shù)據(jù)分析出dom_id,然后根據(jù)此id從緩存中獲取dom節(jié)點(diǎn)。由于不同的數(shù)據(jù)取到了相同的dom_id,所以沒(méi)有創(chuàng)建dom節(jié)點(diǎn)出來(lái)。但是,在最終數(shù)組置空,模型變更之后dom節(jié)點(diǎn)移除的時(shí)候卻為這些dom節(jié)點(diǎn)觸發(fā)了remove操作,也就是方案一中兼容的那些代碼:
所以問(wèn)題必定出現(xiàn)在getTrackByKey這個(gè)函數(shù)的執(zhí)行上,以下是getTrackByKey的代碼:
Vue中對(duì)數(shù)據(jù)綁定的操作大大地提高了開(kāi)發(fā)者應(yīng)用開(kāi)發(fā)的效率,但與此同時(shí)也伴隨著一些不易察覺(jué)的問(wèn)題,尤其如本文中問(wèn)題的重現(xiàn)條件比較復(fù)雜的情況下,測(cè)試不一定可以覆蓋到問(wèn)題的觸發(fā)條件,這個(gè)時(shí)候就需要開(kāi)發(fā)人員多一分警惕。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)建站的支持。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站www.cdcxhl.com,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、建站服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。