国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue.js 渲染簡寫樣式存在的問題

CoderStudy / 534人閱讀

摘要:首先將不存在于中的的樣式設置為然后再設置與中樣式值不相等的的樣式看起來沒什么問題,一切都很符合邏輯,那么是什么造成了上面的現象呢一切的罪魁禍首都在這個樣式的簡寫屬性上。

引出問題

首先我們來這么一個問題, 這里是完整的 jsfiddle demo or codepen demo

給一個元素綁定兩個邊框樣式, 右側和底部都為1px的紅色邊框

        styleA: {
          borderBottom: "1px solid red",
          borderRight: "1px solid red"
        };

然后用一個按鈕(或者任何方式)將樣式換成下面的樣式, 一個1px的綠色邊框,和1px的紅色右側邊框。

        styleB: {
          border: "1px solid green",
          borderRight: "1px solid red"
        };

我們期望的結果應該是右側邊框是紅色的,其余三邊的邊框是綠色的,但實際結果卻是所有邊都是綠色的, 這里已經出現了問題, 然后再點擊按鈕,將樣式切換回去, 此時期望的結果應該是跟一開始一樣: 右側和底部都為1px的紅色邊框, 但實際結果卻是只剩下底部的邊框是紅色的,右側的邊框就像消失了一樣。

那么, 右側的邊框樣式是不是真的消失了呢? 是不是從第一次切換就消失了呢?(這好像也能符合第一次全都是綠色邊框的表現),是CSS的bug嗎?

這個style的替換過程是在Vue里幫我們實現的,是跟虛擬節點vNode的渲染有關,接下來讓我們去Vue的源碼看一下這個問題到底是怎么樣造成的。

Vue更新視圖機制

首先,vue視圖的更新通過updateComponent進行, updateComponent會執行一個update的方法進行更新視圖,update會從根節點進行patch操作, patch操作會依次遍歷虛擬節點樹的所有vnode節點,深度優先的遍歷方式。

通常patch操作會update以下幾個部分

     0: ? updateAttrs(oldVnode, vnode)  
     1: ? updateClass(oldVnode, vnode)
     2: ? updateDOMListeners(oldVnode, vnode)
     3: ? updateDOMProps(oldVnode, vnode)
     4: ? updateStyle(oldVnode, vnode)
     5: ? update(oldVnode, vnode)
     6: ? updateDirectives(oldVnode, vnode)

這里我們只需要關注第5個方法:updateStyle, 那么這個方法里做了什么呢?
看一下核心邏輯:

可以看到這段代碼的主要邏輯是用新的樣式覆蓋舊的樣式,這里的setProp是對element.style進行修改,也就是原生CSSStyleDeclaration對象的實例。

首先將不存在于newStyle中的oldStyle的樣式設置為"",

然后再設置與oldStyle中樣式值不相等的newStyle的樣式,

看起來沒什么問題,一切都很符合邏輯,那么是什么造成了上面的現象呢?

一切的罪魁禍首都在這個border樣式的簡寫屬性(shorthand property)上。

簡寫屬性有什么特殊的地方呢?
最直接的就是當對一個簡寫屬性賦值,例如:

border: 1px solid green;

這個賦值會被轉換為:

    borderWidth: "1px"
    borderStyle: "solid"
    borderColor: "green"
    
    borderTop: "1px solid green"
    borderTopColor: "green"
    borderTopStyle: "solid"
    borderTopWidth: "1px"
    
    borderRight: "1px solid green"
    borderRightColor: "green"
    borderRightStyle: "solid"
    borderRightWidth: "1px"
    
    borderLeft: "1px solid green"
    borderLeftColor: "green"
    borderLeftStyle: "solid"
    borderLeftWidth: "1px"
    
    borderBottom: "1px solid green"
    borderBottomColor: "green"
    borderBottomStyle: "solid"
    borderBottomWidth: "1px"

也就是說borderTop, borderLeft, borderRight, borderBottom也都被賦值了.

原因分析

所以,回到上面的那個切換過程,根據updateStyle源碼進行分析:

styleA切換為styleB時,

第一個for循環, borderBottom不在 oldStyle 中,被清空,borderRight在 oldStyle 中,保留了下來。

第二個for循環, border不在 oldStyle 中,設置border的值,注意此時borderTop, borderLeft, borderRight, borderBottom也都被賦值了,然后borderRight與 oldStyle 中保留下來的值相等, 跳過這次賦值。

最后的結果就是 borderTop, borderLeft, borderRight, borderBottom都顯示 border的值。

styleB切換回為styleA時,

第一個for循環, border不在 oldStyle 中,border的值被清空,此時borderTop, borderLeft, borderRight, borderBottom也都被清空,然后borderRight在 oldStyle 中, 跳過這次賦值。

第二個for循環, borderBottom不在 oldStyle 中,borderBottom被賦值,borderRight與 oldStyle 中保留下來的值相等, 跳過這次賦值

最后的結果也就是只剩下了borderBottom的值。

解決方案

那么,原理搞清楚了,有什么好的解決方案呢? 這個問題在Vue的github上已經被提過issue了,看下尤雨溪的官方回復

這個問題被定性為了一個wontfix,但也給出了有效的解決方案:

給這個元素一個用樣式生成的hash值作為key, 當樣式有任何變化的時候,key就會變化,在Vue的更新渲染邏輯中,如果元素的key發生變化,那么oldstyle就是空對象,就不會出現上面的問題了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/114134.html

相關文章

  • Vue.js 渲染簡寫樣式存在問題

    摘要:首先將不存在于中的的樣式設置為然后再設置與中樣式值不相等的的樣式看起來沒什么問題,一切都很符合邏輯,那么是什么造成了上面的現象呢一切的罪魁禍首都在這個樣式的簡寫屬性上。 引出問題 首先我們來這么一個問題, 這里是完整的 jsfiddle demo or codepen demo 給一個元素綁定兩個邊框樣式, 右側和底部都為1px的紅色邊框 styleA: { ...

    dadong 評論0 收藏0
  • 學習Vue.js-Day1

    摘要:學習內容,基本語法和概念,打包工具,實戰操作參考文獻官網官方資料庫全家桶全家桶文檔概念前端框架借助可以實現手機開發前端框架是一套構造用戶界面的框架,只關于視圖層前端的主要工作室跟用戶界面打交道,中的,實現界面效果框架是為了提高開發 學習內容 1,Vue基本語法和概念 2, 打包工具 Webpack , Gulp3,實戰操作 參考文獻:官網: https://cn.vuejs.org...

    Cheriselalala 評論0 收藏0
  • 學習Vue.js-Day1

    摘要:學習內容,基本語法和概念,打包工具,實戰操作參考文獻官網官方資料庫全家桶全家桶文檔概念前端框架借助可以實現手機開發前端框架是一套構造用戶界面的框架,只關于視圖層前端的主要工作室跟用戶界面打交道,中的,實現界面效果框架是為了提高開發 學習內容 1,Vue基本語法和概念 2, 打包工具 Webpack , Gulp3,實戰操作 參考文獻:官網: https://cn.vuejs.org...

    Cristic 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<