activex for chrome扩展程序 下载”_Chrome扩展程序一键生成网页骨架屏
對于依賴接口渲染的頁面,在拿到數據之前頁面往往是空白的,為了提示用戶當前正在加載中,往往會使用進度條、loading圖標或骨架屏的方式。對于前兩種方案而言,實現比較簡單;本文主要研究骨架屏的應用及實現,并給出一種使用Chrome擴展工具快速生成骨架屏的方案。
首先看看效果 先放一個動圖展示
掘金首頁
百度首頁
知乎首頁
安裝插件后訪問任意網頁,基本上均可以一鍵生成骨架屏(由于時間關系,部分節點并沒有完全實現,不過目前展示Demo應該是夠了
本文所有代碼均放在https://github.com/tangxiangmin/web-skeleton-extension上面了,時間關系代碼寫的比較潦草~
(寫完準備提交Chrome應用商店的時候才發現,居然有一個類似的應用:skeleton extention~囧,就當瞎折騰一番了
骨架屏方案
目前有幾種比較常見的骨架屏方案
在最開始調研骨架屏方案的時候也注意到了page-skeleton-webpack-plugin,體驗了一下發現并不能完全滿足我的需求,對于骨架屏方案,我的期望是
- 使用方便,能夠根據給定頁面,自動生成對應的骨架屏,不需要安裝額外的工具(不用安裝puppeteer)
- 能夠靈活地處理骨架屏生成的HTML文件,支持首屏或者部分區域使用骨架屏(不需要webapck自動注入模板文件,反之,需要實現為項目單個或多個頁面配置對應骨架屏)
- 能夠自定義骨架屏各個區塊的樣式,能夠指定包含或者忽略某些節點,生成的代碼體積要足夠小(骨架屏并不需要完全還原原本頁面)
恰好調研骨架屏方案的那段時間正在處理Chrome擴展程序的工單,發現page-skeleton-webpack-plugin借助puppeteer執行頁面腳本的方案,完全可以通過擴展程序的content.js實現,這樣,不需要借助本地開發環境也可以渲染骨架屏了
骨架屏實現原理
何為骨架?
首先需要保留節點的布局信息,這樣就可以復用節點原有的樣式,不會破壞整體布局,最后生成的骨架屏樣式就可以與原本的頁面保持一致。
然后為了保證生成樣式的統一,需要覆蓋節點原本的UI信息,包括背景色、圖片、邊框等。
由于骨架屏僅僅作為數據返回之前的占位,并不需要完全復原原本的頁面,因此為了使整個骨架屏看起來比較簡潔,可以忽略不必要的節點。
那么要處理哪些節點、忽略哪些節點呢?因此針對不同節點,我們需要進行判斷并分別處理。
區分不同節點
這部分大量參考了一種自動化生成骨架屏的方案:https://github.com/Jocs/jocs.github.io/issues/22 這篇文章的思路,不妨移步閱讀,下面簡單整理一下各種不同節點的處理方案,并增加了一些額外的節點處理策略。
由于涉及大量的節點操作,因此使用了jQuery。
文字
把文字占據的空間看做上行高、內容、下行高,
- 行高部分用透明色,
- 內容部分用灰色
這樣就可以展示原本的文字區域了,對于多行文字而言,顯示的就是斑馬狀條紋形式的骨架屏結構
.line?{????background-image:?linear-gradient(red?25%,blue?25%,?blue?75%,?red?75%);
????/*background-image:?linear-gradient(red?25%,blue?0,?blue?75%,?red?0);?//?與上面等價*/
}
復制代碼
這里需要計算元素的行高、字體大小等信息
renderText($dom)?{????let?fontSize?=?parseFloat($dom.css("font-size"));
????let?lineHeight?=?$dom.css("line-height");
????//?todo?處理瀏覽器默認行高、包含繼承、自定義等屬性
????if?(lineHeight?===?"normal")?{
????????lineHeight?=?fontSize?*?1.4;
????}?else?{
????????lineHeight?=?parseFloat(lineHeight);
????}
????const?textHeightRatio?=?fontSize?/?lineHeight;
????const?firstColorPoint?=?(((1?-?textHeightRatio)?/?2)?*?100).toFixed(2);
????const?secondColorPoint?=?(((1?-?textHeightRatio)?/?2?+?textHeightRatio)?*?100).toFixed(2);
????const?style?=?`--fp:${firstColorPoint}%;--sp:${secondColorPoint}%;--lh:${lineHeight}px;`;
????$dom.addClass('sk-text');
????$dom.attr("style",?style);
}
復制代碼
因為每個文本節點的字體大小和行高可能不一樣,如果全在style標簽上添加樣式,則生成的HTML文件可能比較大,因此這里使用了CSS Var,然后統一在sk-text的樣式類中處理背景色
.sk-text?{????--c:?#eee;
????--fp:?0%;
????--sp:?0%;
????--lh:?0;
????display:?inline-block;
????background-origin:?content-box?!important;
????background-clip:?content-box?!important;
????background-color:?transparent?!important;
????background-repeat:?repeat-y?!important;
????background-image:?linear-gradient(transparent?var(--fp),?var(--c)?0,?var(--c)?var(--sp),?transparent?0);
????background-size:?100%?var(--lh);
????color:?transparent?!important;
}
復制代碼
圖片
獲取原始圖片節點的寬高,然后使用1像素的base64灰色圖片替換原始節點的src屬性
renderImg($img)?{????let?width?=?$img.width()
????let?height?=?$img.height()
????//?一像素灰色圖片
????let?emptyImage?=?"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
????$img.attr("src",?emptyImage);
????$img.css({
????????background:?"#eee",
????????width:?width?+?"px",
????????height:?height?+?"px"
????})
}
復制代碼
對于包含背景圖片的區塊而言,只需要將其背景覆蓋成灰色即可。
按鈕、input
使用灰色背景的塊占據
邊框
替換對應邊框的顏色為骨架屏灰色
列表
列表元素是骨架屏中一個比較常見的區塊,列表元素可以由上面這些區塊組成,但是為了保證生成規整的骨架屏,采取的策略是使用移除多余的元素,使用第一個元素克隆占位
function?renderList($dom)?{????$dom.addClass("sk-list")
????let?$children?=?$dom.children()
????let?$child?=?$children.first()
????let?len?=?$children.length
????//?列表元素子節點統一,保證頁面骨架整齊
????for?(let?i?=?1;?i?????????$children.eq(i).remove()
????}
????for?(let?i?=?1;?i?????????let?tmp?=?$child.clone(true)
????????$dom.append(tmp)
????}
}
復制代碼
遍歷DOM樹
當確定了不同類型節點的處理策略之后,就可以從入口節點遍歷整個DOM樹執行處理方法了
function?preorder($dom)?{????//?...獲取節點類型,執行相關策略放啊
????
????//?遍歷子節點
????$dom.children().each(function?()?{
????????const?$this?=?$(this)
????????preorder($this)
????});
}
復制代碼
在遍歷期間還需要處理一些特殊情況
- 不可見的元素及其子節點應該停止遍歷
- 對于某些節點而言,可能存在一些定制操作
- 由用戶指定節點類型,而不是默認根據節點nodeType推斷
- 忽略某些節點的處理,如一個ul標簽我們可能并不希望將其轉換成列表
- 直接隱藏節點,如某些小圖標等,為了保證骨架屏簡潔,可能需要直接隱藏節點
基于這些場景,引入了skeleton-type的概念,對應上面章節提到的節點類型,在遍歷時會優先讀取節點上的該屬性值,只有當屬性值不存在時,才會根據nodeType自行推斷相關的類型;
- 對于需要隱藏的節點,直接指定skeleton-type為ignore
- 對于忽略節點類型而言,則使用skeleton-exclude-type
let?excludeType?=?$dom.attr(KEY_EXCLUDE)
if?(!excludeType?||?type?!==?excludeType)?{
????let?handlers?=?{
????????[TEXT]:?renderText,
????????[IMAGE]:?renderImg,
????????[BLOCK]:?renderBlock,
????????[BORDER]:?renderBorder,
????????[BUTTON]:?renderButton,
????????[LIST]:?renderList,
????????[BACKGROUND_IMAGE]:?renderBackgroundImage,
????????[INPUT]:?renderInput,
????????[IGNORE]:?renderIgnore
????}
????let?handler?=?handlers[type]
????handler?&&?handler($dom)
}
復制代碼
這樣相當于暴露了skeleton-type與skeleton-exclude-type兩個HTML屬性,在開發頁面的時候就可以直接指定骨架屏區塊類型,方便定制業務需要的骨架屏。
當然逐個去配置skeleton-type也會顯得比較繁瑣,在getNodeSkeletonType中會盡可能地推斷并生成比較符合要求的骨架屏效果;此外,基于Chrome擴展程序的工具還暴露了一個配置參數
?renderSkeleton("body",?{????ignore:?'',
????selector:?{
????????[key]:?{include:?'',?exclude:?''}
????},
})
復制代碼
用掘金首頁試一下
原本的效果
如果不過濾的話,因為頂部導航欄使用的是ul,會默認識別成list,導致展示出現問題
自定義配置后的效果
{????ignore:?['.banner?.label'].join(','),?//?隱藏右側廣告欄的提示按鈕
????selector:?{
????????block:?{
????????????//?將表單轉換成一個BLOCK
????????????include:?['.add-group?.more',?'.search-form'].join(',')
????????},
????????list:?{
????????????//?排除導航欄的ul標簽
????????????exclude:?['.nav-list'].join(',')
????????},
????},
}
復制代碼
此外,我們也可以只傳入某個節點而非body的選擇器,這樣就只會生成對應節點的HTML
將骨架屏嵌入應用
骨架屏有兩種比較常見的應用場景
- 用于首屏或某個頁面打開時等待數據返回時的占位
- 用于滾動加載等列表頁面占位
接下來研究在這兩種場景下如何嵌入骨架屏
獲取骨架屏代碼
在前面遍歷入口節點DOM樹渲染骨架屏之后,我們只需要獲取對應節點的HTML代碼即可。由于沒有修改原本布局信息,因此這段HTML代碼再同一個頁面是完全可以展示的。我們要做的就是拿到對應的骨架屏HTML代碼。
由于整個操作都是在當前頁面上執行的,拿到當前頁面上某個節點的的html內容就變得十分簡單了
- 通過控制臺,找到節點然后訪問innerHTML
- 通過調試工具Elements面板,然后Copy HTML
上面的方式需要手動去操作,我們可以使用擴展程序在骨架屏渲染結束之后自動保存對應的HTML代碼
//?chromeMsg是自己封裝的一個`chrome.runtime.onMessage`工具chromeMsg.on("createSkeleton",?(params)?=>?{
????const?{config}?=?params
????//?默認頁面根節點,可以導出某個dom容器的骨架屏結構
????let?content?=?renderSkeleton(".page",?config)
????//?處理對應的骨架屏HTML代碼,這里只是簡單打印,也可以直接保存文件到本地,或者通過HTTP接口調用某些鉤子服務完成自動注入等功能
????console.log(content)
})
復制代碼
整頁應用
對于整頁骨架屏,我們需要先使用測試數據生成對應的骨架屏,然后將得到的HTML放入頁面中即可。
以Vue等單頁項目而言,在整個應用初始化之前,頁面上只存在根節點,用戶看見的是一片空白,對于這種首屏應用,我們可以將得到的骨架屏代碼直接嵌入到根節點中,這樣當頁面加載至應用初始化之前,用戶都能看見完整的骨架屏效果。
對于其他單頁應用其他頁面而言,也可以采用類似的原理,等待接口返回前展示骨架屏
<SkeletonFrame?:frame="html"?:loading="isLoading">????<RealPage>RealPage>
SkeletonFrame>
復制代碼
比如我們可以封裝一個SkeletonFrame組件,其接口包括
- frame和loading兩個props,表示骨架屏HTML和是否正在加載,當loading為true時展示骨架屏
- default slot需要真實渲染的頁面組件,當loading為false時展示真正頁面組件
局部骨架屏
對于一些需要持續加載的數據,如滾動加載等,可以先獲取對應區塊的骨架屏HTML代碼(不需要整個頁面的骨架屏代碼),然后將其封裝成待展示組件,與上面SkeletonFrame邏輯比較類似
小結
本文整理了骨架屏的實現原理,然后提供了一種通過Chrome擴展程序生成任意網頁的骨架屏方案,主要包括
- 將頁面按節點類型拆分成不同區塊
- 支持自定義節點類型、忽略或隱藏節點
- 導出并使用骨架屏HTML代碼
當然,上面只是介紹了大概的實現思路,并給出了一個簡單的Demo,距離實際應用還有一些距離,等后面有時間再進一步完善吧。本文所有代碼均放在github上面了,歡迎提PR和issue。
近期程序員都喜歡用的架構圖工具vue+ts打造一個酷炫的星空聊天室
若此文有用,何不素質三連?? 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的activex for chrome扩展程序 下载”_Chrome扩展程序一键生成网页骨架屏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ll微信2下载安装_【兰苑文学】:陈振
- 下一篇: 2021年宝鸡中学高考成绩查询,宝鸡中学