前言
之前写移动项目时,我使用了骨架屏来解决渲染首屏时空白太短的问题。我已经掌握了Eleme方法page-skeleton-webpack-plugin
但是page-skeleton-webpack-plugin
需要一个依赖puppeteer
,这会导致整个项目在开发中很笨重
并且并不是所有页面都需要使用屏幕骨架。后来我找到了解决办法,决定用谷歌插件
代替puppeteer
Chrome扩展生成网站骨架
下载谷歌插件
最新版本下载地址未经谷歌官方核实。 PS:如何安装谷歌插件?自己Google一下吧
渲染
使用方法
插件模块参数
与饿了么骨架文档保持一致,如下图
骨架屏原理
饿了么骷髅屏的原理,可以看这篇文章详细了解
其实想法很简单。我们可以根据已有的dom结构
重写指定的颜色,大致就达到了。不过这套方案有两个难点
- 如何识别
容器和块
- 多余的CSS样式和房屋结构的多余处理
容器和方块
由于并非所有 DOM 节点都覆盖指定的背景颜色,有些 DOM 是 作为容器
,让我们看看 饿了么
是如何处理的
// 将所有拥有 textChildNode 子元素的元素的文字颜色设置成背景色,这样就不会在显示文字了。
if (ele.childNodes && Array.from(ele.childNodes).some((n) => n.nodeType === Node.TEXT_NODE)) {
transparent(ele)
}
if (checkHasTextDecoration(styles)) {
ele.style.textDecorationColor = TRANSPARENT
}
// 隐藏所有 svg 元素
if (ele.tagName === 'svg') {
return svgs.push(ele)
}
// ! 针对于容器中如果有background或者img的 如果有需要当做块处理 否则就以容器为处理
if (EXT_REG.test(styles.background) || EXT_REG.test(styles.backgroundImage)) {
return hasImageBackEles.push(ele)
}
// export const GRADIENT_REG = /gradient/
// CSS linear-gradient() 函数用于创建一个表示两种或多种颜色线性渐变的图片
if (GRADIENT_REG.test(styles.background) || GRADIENT_REG.test(styles.backgroundImage)) {
return gradientBackEles.push(ele)
}
if (ele.tagName === 'IMG' || isBase64Img(ele)) {
return imgs.push(ele)
}
if (
ele.nodeType === Node.ELEMENT_NODE &&
(ele.tagName === 'BUTTON' || (ele.tagName === 'A' && ele.getAttribute('role') === 'button'))
) {
return buttons.push(ele)
}
if (
ele.childNodes &&
ele.childNodes.length === 1 &&
ele.childNodes[0].nodeType === Node.TEXT_NODE &&
/\S/.test(ele.childNodes[0].textContent)
) {
return texts.push(ele)
}
})(rootElement)
// ! dom节点 引用类型 这里统一收集对应类型的dom 然后集中用对应的handler处理
console.log('button数组', buttons)
console.log('hasImageBackEles', hasImageBackEles)
console.log(pseudos, gradientBackEles, grayBlocks)
svgs.forEach((e) => handler.svg(e, svg, cssUnit, decimal))
texts.forEach((e) => handler.text(e, text, cssUnit, decimal))
buttons.forEach((e) => handler.button(e, button))
console.log('imgs数组', imgs)
hasImageBackEles.forEach((e) => handler.background(e, image))
imgs.forEach((e) => handler.image(e, image))
pseudos.forEach((e) => handler.pseudos(e, pseudo))
gradientBackEles.forEach((e) => handler.background(e, image))
grayBlocks.forEach((e) => handler.grayBlock(e, button))
解决的办法很简单,就看房子有没有background、backgroundImage、linear-gradient
,或者有没有容器
多余的CSS样式和房屋结构的多余处理
饿了么
这个方案处理了多余的节点和样式,但是效果不是很明显。让我们换个角度思考一下。其实我们已经知道节点是一个容器,节点是块
,那么就需要剔除容器
这样的节点,因为页面上实际显示的是对应的骨架屏块
,而对于特定位置,您可以通过 getBoundingClientRect
API 使用绝对位置来获取 整理到语雀上
我的入门学习笔记?
最近写了笔记整理到语雀上
,方便童鞋们阅读
- 我的入门学习笔记?
总结
- 文章如有错误,欢迎在评论区指正。如果这篇文章对您有帮助,请点赞关注吗?
- 本文由掘金首发。未经许可禁止转载?
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。