前端专业学习记录第2弹

去年,23年10月中旬写了"我最近3个月的前端专业学习记录",今天我掐指一算,完蛋,超时了,说好一季度一总结的,结果都4个月了,赶快补上。

时间范围是23年10月16日-24年2月18日,以周为单位。

2023.10.16-10.22

1. React加key

无论是Vue还是React,只要是列表,都需要加key,这个我是知道的。

然后今天又学到了一招,在某些情况下,非列表元素也可以加key。

就是下图所示的这个场景:

此多数据共用,一开始是没有设置key的,结果数据切换的时候,输入框里面的值是不会变化的。

然后我就设置了value={...},结果没法输入内容了,然后又在onChange里面同步数据,实现输入,但是发现不对,数据同步要请求完成才能执行,不能实时更新。

后来询问同事,才知道,这里设置个key就可以解决此问题了。

原来如此简单,学习了!

2. 视频导出Windows异常问题

收到反馈,有运营同事在使用最近开发****的时候,导出到99%就停止了,跟踪了下,发现Windows系统下才有。

我找了台Windows台式机测试,还真是......奇怪的是,也不报错,如果视频短,或者尺寸小,都是可以成功合成视频的。

研究了一番,发现可能是Windows的缓冲区体积小,导出时候缓存溢出,然后失败。

去W3C官方github上查找有没有人遇到类似问题,结果并不多,只是有一个地方提到,如果视频帧创建的时候如果没有及时释放(frame.close()),可能会出问题。

我一看自己的代码,frame.close()是有书写的,咋回事呢?

问题的解决似乎陷入了死胡同,还是说Chrome浏览器的bug?但应该不至于,如果是浏览器的bug,网上反馈的信息应该很多,所以,应该还是自己使用上的问题。

之前为了让合并时候的进度条可以正常显示(for循环canvas绘制会造成浏览器假死),每120帧加了个定时器。

我就在想,会不会是因为canvas的绘制开销太大,导致frame.close()没执行呢?

于是,我就把每一帧的绘制从原来的for循环(0延时)改成了定时器不停地递归,就像下面代码这样:

嘿,神了奇了,可以成功导出了!

顿时豁然开朗,frame.close()可能是个异步的过程,如果绘制使用for循环,可能导致释放不及时,然后缓存区溢出,最终导致视频合成失败。

但每一帧加了定时器,虽然看上去整个过程时间长了,但是由于缓存得到及时释放,因此,最终的时间其实还好。

想起了一句古话,欲速则不达,这个例子就是最好的体现,想要最快的编译绘制,反而导致最终的失败,但是加个定时器一帧一帧慢慢来,反而最终成功了,速度也没降低。

呵呵,豁然开朗个屁啊!以上判断是当时的判断,以我现在的视角看,相关解释多少有些胡说八道的成分在里面了,执行失败与frame.close()无关,而是因为videoEncoder的序列排队拥挤导致,加了定时器可以缓解此拥挤,但是,如果用户设备性能差,4ms的延时并不顶用,依然会失败。

正确做法是判断videoEncoder.encodeQueueSize的数量,如果大于2(其他值也可以),就停止继续编码,等待之前的编码完成,再继续进行。

3. JSPDF使用经验

参加公司举办的某比赛,做的东西需要用到pdf.js,第一次正式使用,踩了点坑,这里记录下。

首先,光导入jsLib还不够,还需要导入worker,我是这么处理的:

javascript 复制代码
// import 需要的组件,例如 JSpdf
import * aspdfjsLib from "pdfjs-dist";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";

然后,pdfjsLib.getDocument是个长任务,需要先执行下primise然后再then。

javascript 复制代码
pdfjsLib.getDocument({data:pdfData,}).promise.then(function (pdf) {});

2023.10.23-10.29

1. rel=modulepreload

最近才知道,对于JS模块文件,还有个专门的预加载类型,叫做rel=modulepreload

比如页面上有个main.js,会import其他两个JS,不妨叫做a.js, b.js,其目录结构如下:

其中a.js和b.js是必然要加载的,那我们就可以提前预加载这两个JS文件,这样,整个main.js脚本所需要的资源加载速度就会明显提升。

ini 复制代码
<link rel="modulepreload" href="main.js" />
<link rel="modulepreload" href="modules/a.js" />
<link rel="modulepreload" href="modules/b.js" />
<script type="module" src="main.js"></script>

2. 网络请求的优先级

这是自己以前没关注的概念。

在Chrome浏览器中,网络请求的优先级分成了5个等级:

  • Highest 最高,如页面HTML资源和CSS文件;

  • High 高,如正文图片请求资源;

  • Medium 中等,如页面的业务JavaScript文件请求;

  • Low 低,如内联的Base64资源,异步加载的JavaScript文件请求;

  • Lowest 最低,如发送的统计请求;

我们可以Chrome浏览器的开发者工具,在Network面板中可以看到每一个请求的优先级,如下图所示。

然后,这种优先级是可以修改的。

一种方法是使用preload预加载,此特性可以提高JS文件和字体文件的加载优先级。

另外一种方法就是使用fetchPriority属性,可以提高和降低某些资源的加载优先级,例如页面中某个不重要的图片就可以使用下面的代码降低加载优先级。

ini 复制代码
<img src="example.png" fetchPriority="low" />

更多内容可以参见我整理的这篇文章:"聊聊Web网页中资源加载的优先级"

2023.10.30-11.5

1. 滤镜应用与pixijs学习

部分视频特性用的是frag滤镜实现的,因此,我就去研究了下如何使用p5.js和pixi.js希望可以跑通这些滤镜,发现都是以失败告终,而官网提供的frag都没问题。

于是就去请教在这块更有经验的其他同事,果然不一样,一针见血就指出了问题,部分配置参数缺失。

以及部分参数可以使用pixijs默认的关键字代替,例如inputImageTexture可以替换成uSampler。

u_ScreenParams可以使用固定值,就像这样:

一番调整后成功跑通了对frag的解析,demo地址访问这里,使用pixijs实现。

2. script type="importmap"

原来import外部JS组件的时候,还可以通过设置Imports Map对导入地址进行映射,从而简化导入的业务逻辑。

语法是script元素设置type属性值为importmap,里面的内容是个JSON格式的数据。

例如使用别名:

还支持scopes关键字设置额外的路径匹配映射,这对于加载组件不同版本,或者本地加载相对地址线上加载绝对地址的场景非常受用。

本周回乡了,两个娃彻底释放了天性,挖起了红薯。

2023.11.6-11.12

1. React调用子组件方法

使用forwardRef包裹子组件实例,useImperativeHandle暴露方法,外部主组件使用ref引用,然后调用暴露的方法,具体可参考官网提供的案例。

2. 为何<small>元素保留了而<big>元素废弃了?

HTML里面有一众表象元素,就是这些元素没有任何语义,就是用来实现样式功能的,例如<i><b><center>以及这里的主角<small><big>元素。

由于CSS2.1的到来,推荐样式与行为分离,这些表象元素就不推荐使用了,在规范中被废弃了。

随着HTML5时代的到来,这些表象元素有些迎来第二春,有些没能起死回生,为什么呢?

其实原因很简单,规范制定人员没有找到可以复活这些HTML元素的语义场景。

<small><big>元素就是典型的代码。

<small>元素找到了合适的语义,那就是文档中的标记,页眉页脚的小字体,但是在文档结构中,是没有需要放大文字显示的语义场景的,于是元素被废弃。

时也命也!

3. pixi textBaseline文字显示不全的问题

pixi绘制文字比原生API绘制要方便不少,但实操下来会有奇怪的问题,例如,对于中文,如果设置textBaseline为top或者middle,会有中文部分显示的奇怪问题。

原因不详,要修复此问题,可以通过设置padding值修复。

**

**

2023.11.13-11.19

本周是学习成果丰硕的一周。

1. MP4视频解码与渲染

实现原理,先使用MP4Box.js获取MP4文件的各类信息,包括画面轨道数据和音轨数据等,然后使用Webcodecs API中的VideoDecoder方法进行解码了。

解码后的图片序列帧和背景图使用滤色混合模式进行混合,就可以实现各类氛围特效了,例如下图所示的下雨特效。

更多内容可以访问整理的这篇实现文档

2. Frag特效的应用

上周的Frag滤镜demo终于在项目中实战了,各项效果符合预期,例如下面抖音风格的抖动效果。

更多内容可以访问整理的这篇详述文档

2023.11.20-11.26

1. SVG文件的外链

以前外链SVG文件我都是使用<img>元素,这周研究了下,发现HTML中支持SVG元素外链调用的元素很多,例如<object><iframe><embed>都是可以的,甚至<input>元素也可以。

ini 复制代码
<img src="/assets/circle.svg" alt="圆形"> 
<object data="/assets/circle.svg" type="image/svg+xml">圆形</object>
<embed src="/assets/circle.svg" type="image/svg+xml" />
<iframe src="/assets/circle.svg">圆形</iframe>

2. 本地MP3封面读取

有些MP3文件是自带封面图的,JS也是可以读取这些信息的,查找了下,可以使用JavaScript-ID3-Reader这个项目,完成地址:github.com/aadsm/JavaS...

自己整了个demo跑了下,可行。

不过在Web中传输的MP3为了节约流量,大多删除了这些信息,所以有没有封面图还是要看的,像是腾讯音乐软件中下载的歌曲都是有封面的,纯Web传输的多半没有。

详见"本地MP3封面图、时长等信息的JS读取"这篇文章。

2023.11.27-12.3

<img>元素支持一个名为 srcset 属性的元素,可以设置在不同屏幕密度下显示不同尺寸的图片,例如:

ini 复制代码
<img src="w128.jpg" srcset="w256.jpg 2x, w512.jpg 3x" />

设备的屏幕密度越高,加载的图片尺寸越大,兼顾了资源和用户体验的平衡,是一个很好的特性。

然而此特性在坊间的使用频率很低,在过去还可以理解,因为准备多个素材的开发成本比较高,日后维护也麻烦,因此直接两倍图一了百了。

但是现在,静态资源都是走Cos存储的,可以轻松指定图片的尺寸规格,不需要额外的开发成本,因此,我觉得大家可以把srcset属性给拾起来了,流量也是要钱的,省一点就是为公司节约一点。

ini 复制代码
<img src="https://cos.somesite.com/imgPreview?/w/128" 
  srcset="https://cos.somesite.com/imgPreview?/w/256 2x, https://cos.somesite.com/imgPreview?/w/512 3x" 
/>

2023.12.4-12.10

本周的学习还是围绕HTML展开。

1. srcset属性中的w描述符

srcset只能实现基本的响应式图片效果,更高级的应用可以配合sizes属性和w描述符,实现更加兼顾用户体验和流量使用的效果。

例如:

ini 复制代码
<img src="/assets/rect@1x.png" 
  srcset="/assets/rect@1x.png 600w, /assets/rect@1.5x.png 900w, /assets/rect@2x.png 1200w" 
  sizes="(max-width: 480px) calc(100vw - 20px), 600px" 
>

此时,传统的显示器使用1倍图,然后手机,例如iPhone SE因为宽度小,屏幕密度只有2,此时要是加载2倍图,其实浪费了,有了w描述符,就能精准匹配最佳图片规则,这里加载的是1.5倍图。

iPhone 13 Pro Max的屏幕密度是3,于是加载的就是2倍图。

配合COS服务,我觉得可以大大优化网站的流量开销。

2. AVIF图片格式接入的可能性

还是关于网站流量优化的问题,周末在家转码了一个AVIF图片玩一玩,当看到其尺寸大小后,惊呆了,肉眼完全看不出区别,但是尺寸比JPG格式小了8,9倍,注意,是比JPG格式,不是PNG格式。

大小仅6.96K,同质量的JPG图片大小高达57.2K,WebP大小是34.9K。

看了下,Chrome和Firefox浏览器都是支持的,要是整站都接入avif格式,那可以给公司省多少流量费用啊。

我看了下,腾讯云的COS已经支持avif压缩了:

为了兼容不支持的设备,可以实现如下所示的代码:

ini 复制代码
<picture>   
  <source srcset="example.avif" type="image/avif">   
  <source srcset="example.webp" type="image/webp">   
  <img src="example.jpg"> 
</picture>

弄个工具跑一下,成本应该不高的,可以思考下🤔......

2023.12.11-12.17

语音合成的学习

这周在弄语音合成的事情,准备做个自己使用的小玩意。

首先要购买语音合成的服务,我研究了下市面上的多个云厂商,例如腾讯云和百度云,都是面向企业的,调用次数都是百万次起,一年费用至少也要几大千。

后来发现华为云有一年18块钱的语音合成服务,可以支持上万次调用,正好适合学习以及做私人玩具。

可能是因为体量低还是其他什么原因,语音合成的文档问题还不少。

例如,语音合成的演示示例使用的是sign签名作为验证,但是,签名获取的接口在语音合成服务中并没有,只能使用token做验证。

我是怎么知道这个事情的呢?我搞了一天,按照文档弄的,怎么都不行,就工单求助,那时候已经凌晨了,工单GG也不知道,然后让我安装了weMeeting,发起了会议,拉了几个开发一起看我的源码,这才搞清楚。

获取token的文档有两种方式,一种是用户名密码,一种是AK/SK,结果AK/SK是无效的,都是使用用户名密码,然后这个用户名还不能是主账号用户名,要新建一个身份,再定义密码。

你瞧瞧,这怎么搞,要不是直接和开发对接,打死也不知道要这么搞啊!

不过有一点我佩服的,凌晨1点半了,三个华为员工围观我的代码(共享桌面方式),指导我一步一步操作,真TM敬业。

后来终于调通了,速度还可以,就是这个质量......看AI合成的语音视频,夹杂英文单词和专业术语的时候很不流畅,我回头换个声音试试。

专业学习

本周专业学习比较琐碎。

JS部分:

HTML部分:

  • 重新认识了下image类型的input输入框,发现这玩意本质上就是个 IMG元素,属性都是一样的,宽高width、height,以及src,alt等,甚至CSS中的object-position/object-fit也同样支持,区别就在于变成input输入框后,自带表单提交的行为,不过此元素并不实用,了解即可。

CSS部分:

  • @scope规则,不过只是简单看了下,这周好好run一遍各种语法,了解下细节。

2023.12.18-12.24

select下拉列表触发显示

可以使用showPicker方法,绝了。

视频文件的音频提取

我一开始的想法是和图像序列提取一样,使用WebCodecs API,也获得了每一帧音频的切片数据,但是转而播放的时候,发现数据都是0,因此,没声音,不知道哪里出问题了......嗯......

后来发现其实完全没必要这么麻烦,直接decodeAudioData视频文件的arrayBuffer数据,就能得到对应的AudioBuffer数据了,有了AudioBuffer就可以对音频为所欲为,分割,复制拼接,合并都不在话下,自然也包括资源的提取。

您可以狠狠地点击这里:JS提取视频中的音频音轨并下载demo

原理说明可以参见整理的这篇文章 - 使用JS提取视频中的音频资源

2023.12.25-12.31

这周抽空将之前预研的图像对比和识别整理成文了,包括:

24年第1周 1.1-1.7

form:invalid的应用

表单内容未输入的时候,提交按钮禁用是非常场景的交互设计。有一种简易的方法可以实现此需求,利用invalid伪类。例如:

css 复制代码
<form>    
  <label>邮箱</label>  
  <input type="email" required>  
  <label>网址</label>  
  <input type="url">  
  <label>评论</label>  
  <textarea required></textarea> 
  <button>提交</button>
</form>

form {  display: grid;  gap: .5rem;}
:invalid button { filter: grayscale(1) opacity(.5);  pointer-events: none; }

此时,默认情况下,按钮的样式表现为禁用。

当输入邮箱和评论信息后,自动恢复。

整个交互无任何JavaScript代码参与。

24年第2周 1.8-1.14

Firefox浏览器也已经支持popover属性了,毫无疑问,在不久的将来大规模应用已是大势所趋。

两个优点:

  1. 使用方便

  2. 顶层特效

popover弹出层的显示与隐藏浏览器内置,无需额外的JavaScript代码,同时具有top-layer特效,不要担心弹出层会被覆盖。

更详细内容参见整理的这篇文章:"时代变了,该使用原生popover属性模拟下拉了"

24年第3周 1.15-1.21

之前了解了下@scope,这周终于有时间学习了下相关语法和细节,整理成文字版本了,有兴趣可以访问这里:"CSS @scope他来了"。

视频版可以访问B站:www.bilibili.com/video/BV1MH...

24年第4周1.22-1.28

这周好好学习了下Microdata微数据,我刚入行的时候也学过,不过忘得差不多了,且经过十几年的发展,已经有所不同了,例如词汇表现在一家独大了,所以又重新学习了起来。

Microdata也是WHATWG HTML标准的一部分,用于在网页上的现有内容中嵌套元数据。搜索引擎和网络爬虫可以从网页中提取和处理微数据,并使用它为用户提供更丰富的浏览体验。

主要是通过5个item开头的HTML属性实现的(在当前已有的HTML内容基础上额外设置,不会影响现有的样式与布局呈现),itemid、itemhref、itemscope、itemprop和itemtype,其中itemid和itemhref是非必须的,且和id、href属性的区别较大,itemid是可以重复的,且推荐用在指向同一元数据的场景下,itemhref指向的是其他元素的id,目的是在非嵌套HTML层级中依然有良好的微数据结构。

然后微数据需要了解词汇表,schema.org/ 这个网站上可以找到,例如人物、电影、地点等词汇表,通过itemtype指定(值就是scheme官网地址),itemprop指定对应的属性名称实现,例如:

具体可以见我这篇文章"HTML MicroData微数据结构简介",更精彩的介绍可以参见今年5月份,最晚6月份会出版的新书。

24年第5周 1.29-2.4

请了4天年假,凑了15天的假,哈哈哈,还学个尼玛,钓鱼去了......

24年第6周 2.5-2.11

接着钓鱼,接着玩......

24年第7周 2.12-2.18

假期为何如此短暂😭😭😭

本周学习的是puppeteer,整了个简易demo跑了下,算是入门了,可如何部署服务,如何后端通信交互,完全就是知识领域的空白,一个头两个大,算了,请教同事吧。


OK,以上就是最近四个月的学习记录,不得不吐槽下掘金的文章编辑器,居然不支持粘贴和截图上传,也不支持尺寸控制,弱爆了。

本文已放在了专门的学习记录专栏,每个季度更新一下。

欢迎关注哈。

相关推荐
小鼠米奇1 小时前
详解Ajax与axios的区别
前端·javascript·ajax
Bunury2 小时前
Vue3新组件transition(动画过渡)
前端·javascript·vue.js
zero.cyx2 小时前
JS函数部分
开发语言·前端·javascript
超级小的大杯柠檬水2 小时前
SpringBoot lombok(注解@Getter @Setter)
java·前端·spring
AvatarGiser2 小时前
《ElementUI/Plus 踩坑》el-table + sortablejs 拖拽顺序错乱(Vue2/3适用)
前端·vue.js·elementui
蓝染-惣右介2 小时前
【若依RuoYi-Vue | 项目实战】帝可得后台管理系统(二)
java·前端·后端·vue·springboot
哈哈哈哈cwl2 小时前
秒懂Vue.jsDiff算法与虚拟DOM
前端·javascript·vue.js
我码玄黄3 小时前
HTML翻牌器:用CSS和HTML元素创造动态数字展示
前端·css·html
JaxNext3 小时前
谁也别拦我们,网页里直接增删改查本地文件!
前端·javascript·面试
-草莓星球杯3 小时前
若依VUE项目安全kind-of postcss vite漏洞扫描和修复
前端·javascript·vue.js