者:卡頌
轉發(fā)鏈接:https://mp.weixin.qq.com/s/ICjOlJL-fUGRb2S_xqBT7Q
是個無聊的問題嗎當提出這個問題時,我的第一反應是——我還真是無聊 ?♂?
轉念一想,em~,好像事情沒有這么簡單如果直接選擇所有div再遍歷刪除的話,div的子孫節(jié)點也被刪除了。有什么辦法能在保留整棵DOM樹層級關系的前提下,只刪除div節(jié)點呢?我陷入了沉思。。。。。
知乎是React寫的,React用JSX來表示頁面層次結構,JSX在編譯時會被babel轉換為React.createElement。在代碼運行時,React獲取的其實是React.createElement()的返回值。辦法來了!
我們只需要覆寫一下React.createElement方法,當遇到type==='div',我們將type修改為React.Fragment,即我們把所有div節(jié)點都變成Fragment,那不就能在保持樹的層級關系的同時去掉div了?讓我們開始吧??!如何拿到React對象這時候遇到了第一個問題:知乎沒把React暴露到全局(廢話,當然不會 ),怎么獲取React對象呢?
好在當我們使用React Dev Tools時,Dev Tools會向頁面注入全局變量__REACT_DEVTOOLS_GLOBAL_HOOK__,這個變量會成為鏈接React與Dev Tools的橋梁。
其中的renderers屬性指頁面使用的渲染器,在網(wǎng)頁端就是我們熟悉的React-DOM(在客戶端當然就是React-Native啦)我們發(fā)現(xiàn)一個方法findFiberByHostInstance
方法名居然出現(xiàn)了Fiber字樣??!
我們知道,F(xiàn)iber是React的最小可調(diào)度單元(別問為什么,問就是安利我寫的React源碼揭秘系列)那findFiberByHostInstance方法所在文件一定有React相關定義。我們右鍵跳轉到定義函數(shù)的文件,
在文件內(nèi)搜.createElement
果然讓我們找到了。打上斷點,刷新頁面試試~
果然進來了,事情越發(fā)有趣了看看o.a是什么,em~~一個對象,內(nèi)部有Children、createElement。。。。。。看來這就是React對象了
趕忙把來之不易的React對象保存在全局,順便把React.createElement也保存一份。
現(xiàn)在放開斷點,window.React已經(jīng)指向知乎首頁內(nèi)部使用的React啦。
修改React.createElement方法我們知道,React.createElement方法第一個參數(shù)為type(別問為什么,問又是一波安利React源碼揭秘系列),我們再到React文檔中找來React.Fragment的定義。
if (typeof Symbol==='function' && Symbol.for) {
const symbolFor=Symbol.for;
REACT_ELEMENT_TYPE=symbolFor('react.element');
REACT_PORTAL_TYPE=symbolFor('react.portal');
REACT_FRAGMENT_TYPE=symbolFor('react.fragment');
REACT_STRICT_MODE_TYPE=symbolFor('react.strict_mode');
REACT_PROFILER_TYPE=symbolFor('react.profiler');
REACT_PROVIDER_TYPE=symbolFor('react.provider');
// ...
}
接下來,修改全局變量
React.createElement=(type, ...args)=> {
if (type==='div') {
type=Symbol.for('react.fragment');
}
// originCreateElement才是正經(jīng)的React.createElement
return originCreateElement(type, ...args);
}
讓我們康康此時的頁面結構
ok~~~ 滿屏的div套div(嫌棄臉),接著我們輕輕的點一下關注按鈕,觸發(fā)隨便啥組件的setState。接下來,就是見證奇跡的時刻。。。
除了根節(jié)點,其他div都消失了,終于恢復了往日的清爽界面(大誤)
總結通過這篇無聊的文章,我們認識到:
PS:如果你用Chrome將被壓縮后的代碼formatted后打上斷點,刷新頁面進入斷點后瀏覽器卡死,不要懷疑,這是Chrome的bug,截止版本 81.0.4044.138(正式版本) (64 位)還未修復,建議使用chrome開發(fā)者版本 Chrome Canary
作者姓名:卡頌
轉發(fā)鏈接:https://juejin.im/post/5ecb2af0
首先我們通過一張圖來解釋下元素浮動是什么樣的狀態(tài)。
元素浮動情況
上圖的html部分代碼為:
html代碼
css部分代碼為:
css代碼
通過上面的圖片可以看出,當內(nèi)部的div設置float后,外部的元素的就會受到以下影響:
背景不能顯示
邊框不能被撐開
margin和padding設置的值不能正確顯示
如果不清除元素浮動的話,浮動層后面的非浮動層內(nèi)容就有可能被覆蓋,造成頁面的排版混亂。
例如在上面的例子中再加一個非浮動的div,就會發(fā)現(xiàn)該div被前面的三個浮動div覆蓋住。
因為浮動,后面的div被覆蓋
既然會出現(xiàn)這種情況,我們就應該設法清除掉元素的浮動。
我們可以給父級元素.outer設置為定高,這樣就可以不影響后面的非浮動元素。.outer的樣式為:
設置定高
達到的效果為
清楚浮動之后
雖然這種方法可以清楚浮動,但是對父元素設置定高會有很多的限制,如果內(nèi)層div的高度變化,則需要手動修改外層div的高度,相對來說有點麻煩,因此這種方法并不推薦。
在父元素內(nèi)部的末尾處添加一個新的div,并設置其clear: both;屬性。
添加一個新的div
該新增div的css屬性為:
新增div的css屬性
利用該方法同樣可以達到清楚浮動的效果,但是由于會新增DOM元素,這種方法也不推薦。
在父級元素上使用overflow:hidden屬性,準確來說只要不給overflow屬性設置為visible都可以清除元素浮動。
設置overflow: hidden
使用這種方法可以少寫很多css樣式代碼,同時不會新增DOM元素,因此推薦使用這種方式。
通過對父元素使用:after偽元素,同樣可以達到清除浮動的效果。
偽元素清楚浮動
以上方法在偽元素中,通過設置clear與overflow屬性來實現(xiàn)。方法4在實際的項目中使用的頻率最高,因此極大的推薦使用方法4來清除元素浮動。
看到網(wǎng)上有的資料介紹,通過設置父元素為浮動,或者設置父元素為absolute定位,這兩種方法只是能顯示父元素而已,但父元素同樣會覆蓋到后面的非浮動元素,因此這兩種方法嚴格意義來說并不算清除浮動的方法。
今天這篇文章主要介紹了幾種通過CSS來清除元素浮動的方法,你掌握了嗎?
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。