基于DOM的骨架屏自动生成方案

后来仔细想想,骨架屏这幅样子不是和一堆颜色块拼起来的页面一样吗?对比现有的骨架屏方案,这个想法有点“走捷径”的感觉。再进一步思考,这些色块基于当前页面去分析节点来生成,不如来段 JS 分析页面节点,一顿 DOM 操作生成颜色块拼成骨架屏。那么问题来了,该怎么样精确的分析页面节点,不同节点又该生成什么样的色块呢?

既然骨架屏代表了页面的大致结构,那么需要先用 js 对页面的结构进行分析。分析之前,我们需要制定一种规则,以确定需要排除哪些节点?哪些种类的节点需要生成颜色块?生成的颜色块如何定位等等。我们初步定下的规则如下:

1. 只遍历可见区域可见的 DOM 节点,包括:

非隐藏元素、宽高大于 0 的元素、非透明元素、内容不是空格的元素、位于浏览窗口可见区域内的元素等;

2. 针对(背景)图片、文字、表单项、音频视频、Canvas、自定义特征的块等区域来生成颜色块;

3. 页面节点使用的样式不可控,所以不可取 style 的尺寸相关的值,可通过 getBoundingClientRect 获取节点宽、高、距离视口距离的绝对值,计算出与当前设备的宽高对应的百分比作为颜色块的单位,来适配不同设备;

基于这套规则,我们开始生成骨架屏:

首先,确定一个 rootNode 作为入口节点,比如 document.body,同时方便以后扩展到生成页面内局部的骨架屏,由此入口进行递归遍历和筛选,初步排除不可见节点。

function isHideStyle(node) {

return getStyle(node, ‘display’) === ‘none’ ||

getStyle(node, ‘visibility’) === ‘hidden’ ||

getStyle(node, ‘opacity’) == 0 ||

node.hidden;

}

接下来判断元素特征,确定是否符合生成条件,对于符合条件的区域,”一视同仁”生成相应区域的颜色块。”一视同仁”即对于符合条件的区域不区分具体元素、不考虑结构层级、不考虑样式,统一根据该区域与视口的绝对距离值生成 div 的颜色块。之所以这样是因为生成的节点是扁平的,体积比较小,同时避免额外的读取样式表、通过抽离样式维持骨架屏的外观,这种统一生成的方式使得骨架屏的节点更可控。基于那上述“走捷径”的想法,该方法生成的骨架屏是由纯 DOM 颜色块拼成的。

生成颜色块的方法:

const blocks = [];

// width,height,top,left 都是算好的百分比

function drawBlock({width, height, top, left, zIndex = 9999999, background, radius} = {}) {

const styles = [

‘position: fixed’,

'z-index: '+ zIndex,

‘top: ‘+ top +’%’,

‘left: ‘+ left +’%’,

‘width: ‘+ width +’%’,

‘height: ‘+ height +’%’,

'background: '+ background

];

radius && radius != ‘0px’ && styles.push('border-radius: ’ + radius);

// animation && styles.push('animation: ’ + animation);

blocks.push(<div style="${ styles.join(';') }"></div>);

}

绘制颜色块并不难,绘制之前的分析确认才是这个方案真正的核心和难点。比如,对于页面结构比较复杂或者大图片比较多的页面,由图片拼接的区域没有边界,生成的颜色块就会紧挨着,出现不尽如人意的地方。再比如,一个包含很多符合生成条件的小块的 card 块区域,是以 card 块为准还是以里面的小块为准来生成颜色块呢?如果以小块为准,绘制结果可能给人的感觉压根就不是一个 card 块,再加上布局方式和样式的可能性太多,大大增加了不确定因素。而如果以 card 块为准生成颜色块的话还要对 card 块做专门的规则。

目前来说,对于页面结构不是特别复杂,不是满屏图片的,不是布局方式特别“飘逸“的场景,该方式已经可以生成比较理想的骨架屏了。而对于那些与预期相差较远的情况,我们提供了两个钩子函数可供微调:

1. init 函数,在开始遍历节点之前执行,适合删除干扰节点等操作。

2. includeElement(node, draw) 函数,可在遍历到指定节点时,调 用 draw 方法进行自定义绘制。

通过以上步骤就能够直接在浏览器中生成骨架屏代码了。

在浏览器里运行

由于我们的方案出发点是通过单纯的 DOM 操作,遍历页面上的节点,根据制定的规则生成相应区域的颜色块,最终形成页面的骨架屏,所以核心代码完全可以直接跑在浏览器端;

const createSkeletonHTML = require(‘draw-page-structure/evalDOM’)

createSkeletonHTML({

// …

background: ‘red’,

animation: ‘opacity 1s linear infinite;’

}).then(skeletonHTML => {

console.log(skeletonHTML)

}).catch(e => {

console.error(e)

})

结合 Puppeteer 自动生成骨架屏

虽然该方式已经可以生成骨架屏代码了,但是还是不够自动化,为了让生成的骨架屏代码自动加载进指定页面。于是,我们开发了一个配套的 CLI 工具。这个工具通过 Puppeteer 运行页面,并把 evalDOM.js 脚本注入页面自动执行,执行的结果是生成的骨架屏代码被插入到应用页面。

我们的方案大概思路如下:

接下来看看如何使用 CLI 工具生成骨架屏,最多只需如下四步:

1. 全局安装,npm i draw-page-structure – g

2. dps init 生成配置文件 dps.config.js

3. 修改 dps.config.js 进行相关配置

4. dps start 开始生成骨架屏

只需简单几步,然而并没有繁琐的配置:

一般来说,你需要按自己的项目情况来配置 dps.config.js ,常见的配置项有:

  • url: 待生成骨架屏的页面地址

  • output.filepath: 生成的骨架屏节点写入的文件

  • output.injectSelector: 骨架屏节点插入的位置,默认 #app

  • background: 骨架屏主题色

  • animation: css3 动画属性

  • rootNode: 真对某个模块生成骨架屏

  • device: 设备类型,默认 mobile

  • extraHTTPHeaders: 添加请求头

  • init: 开始生成之前的操作

  • includeElement(node, draw): 定制某个节点如何生成

  • writePageStructure(html, filepath): 回调的骨架屏节点

详细代码及工具的使用请移步 [Github]( famanoder/dps);

初步实现的效果:

* 京东 PLUS 会员正式中首页:

* 京东 PLUS 会员正式中首页,通过该方案生成的骨架屏效果:

* 移动端百度首页,通过该方案生成的骨架屏效果:

总结
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

本人分享一下这次字节跳动、美团、头条等大厂的面试真题涉及到的知识点,以及我个人的学习方法、学习路线等,当然也整理了一些学习文档资料出来是附赠给大家的。知识点涉及比较全面,包括但不限于前端基础,HTML,CSS,JavaScript,Vue,ES6,HTTP,浏览器,算法等等

详细大厂面试题答案、学习笔记、学习视频等资料领取,点击资料领取直通车

前端视频资料:
CoPEF.jpg" />

最后

本人分享一下这次字节跳动、美团、头条等大厂的面试真题涉及到的知识点,以及我个人的学习方法、学习路线等,当然也整理了一些学习文档资料出来是附赠给大家的。知识点涉及比较全面,包括但不限于前端基础,HTML,CSS,JavaScript,Vue,ES6,HTTP,浏览器,算法等等

详细大厂面试题答案、学习笔记、学习视频等资料领取,点击资料领取直通车

[外链图片转存中…(img-x5Gt5Nyi-1713234262833)]

前端视频资料:

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值