当前的技能体系:
-
前端。
已知:
-
原生Js方向原型的方面的了解是比较笼统的阶段,说他笼统主要是没有具体的实践。Js是基于原型链的继承模型。
更新一波,最近读了一遍JavaScript20年,里面有提到关于这部分的内容,里面提到class的继承方式不推荐,主推function式编程。
基于原型的链的继承方式其实并没有难以理解:如类中的继承可能是这样的:
class A { handler() { console.log(1) } } class B extends A { ... handler() { super() console.log(2) } ... }
那基于原型链则是:
function A(){} A.prototype.handler = function () { console.log(this.a) } function B() { this.a = 5 } B.prototype.handler = function () { A.prototype.handler.call(this) console.log(2) }
最主要的也就是this的指向问题,call, apply, bind都可以用来解决这个问题。
更新:
关于继承方面的问题有一个主要问题就是关于constructor的继承:
基于原型链的继承上要继承出constructor,你需要:
function A() { this.a = 1 console.log(this.a) } function B() { A.apply(this, arguements) } // 其他的继承 B.prototype = Object.create(A && A.prototype)
对于原生对象的constructor的原型链继承方式 ...还没看懂babel怎么做的。
-
CSS方向,CSS基本体系还算可以,薄弱项:动画,svg。
-
canvas与svg是一个绝对的弱项。 canvas后面在结合webRTC和视频做录制以及直播时小小了解了一下,动画方面主要还是帧的问题。之前写CSS主要关注点是最终呈现什么样的状态,过渡时间控制控制运动轨迹时间指定一个固定的模式然后其他的不管了。用canvas的话就是你几乎一切都需要自己去画,一秒钟执行60帧,每一帧的这个图像运动到了什么地方你都需要自己去计算控制。
原生且强大,像是拿起了画笔,还需要配备一些工具。
动画后面做了一个简单点的内容,要注意的点就是帧率,用animation属性做的话还是可以的,注意的点是自定义运动曲线cubic。
svg小小尝试一波,微信公众号内的svg交互动画,目前没什么实践。这里我最近写了一个点赞组件,记录一下,顺便说一说我所了解到的动画流程。
首先动画是由静态的画面组合而成,这里习得的概念是帧,每一帧就有一张图片,而在1秒钟内播放连续的多帧就可以达到动画的效果,和小时候每一页画一幅图然后快速翻阅一个道理。常见的电影24帧,主流30帧,60帧,以及手机最近的90帧刷新率,120帧刷新率。
前端可以实现的动画我目前已知的可以用:
- DOM,配合animation,transition。
- Canvas。
- gif,mp4,svg。
逐个来看:
-
DOM这种方式,所需要提供的是 关键帧,也就是不需要你一帧帧的全提供(当然全提供也行)需要你给出关键的地方,比如25%,50%,100%。
还有就是DOM这个方式必须是从
有
到有
的变化,不能是从无
到有
的变化。一般能执行的动画就是对已经渲染出来的DOM变到另一种状态的动画。
-
Canvas这种方式,提供的能力是绘制帧,而不是动画,动画是由帧合成,Canvas在每一帧的时间内不停的擦除原画板画上新内容就变成了动画。
要掌握Canvas动画首先要绘制出一帧的画,然后通过window.requestAnimationFrame也好,setTimeout/Interval也好进行连续绘制。
-
你懂得。
一个很简单的飘❤动画,我用的DOM实现的,先说下DOM的思路:
❤是一个svg,点击后会首先生成一个SVG,然后指定初始class,生成后在设置它应该到达的位置(颜色,大小等)的style,在transition之后将其删除,性能方面还可以,瓶颈在于频繁的增删DOM。 ```javascript const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.classList.add('tools-btn__icon', 'icon', 'brumb'); const use = document.createElementNS('http://www.w3.org/2000/svg', 'use'); use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', '#icon-dianzanshixin'); svg.appendChild(use); ref.appendChild(svg); // transition需要从有到有 setTimeout(() => { svg.classList.add('zan'); svg.style = this.getStyleString(style); }); ``` 这里注意为啥用setTimeout而不直接用Promise.then,基于https://html.spec.whatwg.org/multipage/webappapis.html#performing-a-microtask-checkpoint 这里面Processing model的执行流程,微任务的执行先于渲染UI,也就是说执行到ref.appendChild(svg);这一句,已经添加了DOM,但还未开始渲染,优先执行了微任务内的逻辑。而DOM的动画上面说了是从有到有的过程。
Canvas也很好实现,首先❤还是一个svg,每次点击(触发新增)都会将一组状态推入一个数组,
{ top: 0, left: 0, topSpeed: -0.1, leftSpeed: -0.2, random: false }
这样,window.requestAnimationFrame触发回调,这里要写一个避免重复触发和停止的标记,每次回调都会遍历数组,将新一次的状态更新并保存,判断下删除即可。
svg 实现了一个animation demo。
-
框架方面主要技术栈是Vue,React。 Vue剩余的内容感觉只有学习源码与架构了。
这里对Vue的源码部分稍微探索了一点:
核心双向绑定基于事件机制,数据变动时通知调度器变化,调度器调用打补丁函数对UI修修补补。
扩展方面的插件机制。
最近看了Vue3 reactivity的源码,用同样的思路撸了一个有observe/observable/computed的简易版工具。手摸手实现Vue3 ReactivityReact这里写了一个上线项目后暂时没有做后续的跟进,没有需求,准备业余时间搞一搞,Ts+React。
-
HTTP方向上状态码,2的多路复用。
这边我后面做了一个抓包,详细分析了一下3握4挥,以及HTTPS下协商用不用2(TLS握手),
抓包的时候HTTP2的多路复用可以看得很清楚,1.1下每条请求都会发起一个相应的3握4挥,但如果用的是HTTP2那只有一次3握4挥。
详细看tcp && ip.addr == 123.206.177.175.pcapng,放在wireshakr里。当然只分析了基础,还有一些需要了解的内容待探索:
二进制分帧层。 -
缓存策略,cache-control。
缓存上做了一个比较大的实践,结合一次优化公司核心产品的机会,这次优化方方面面都有优化,
核心产品白屏时间从1000ms左右降低至350ms,FCP从10s降低至1.9s,打包后体积减少300Kb(GZIP)/1Mb(parserd)左右。详细可看 web程序优化思路。.pdf 和 基于思考所做的探索/性能方面的探索.md。
-
性能调优上,缓存(CDN),懒加载(分块,动态加载异步组件),减少体积,提取公共部分,web worker,延迟加载(只加载必要的部分)。
同上。
-
webpack打包了解,entry,output,loader,plugins。loader与plugins没有写过自定义插件阶段在用,调优上optimiztion,splitChunk,tree-shaking(usedExport)。 关于tree-shaking的一些更进一步的理解: 对于webpack4来说,tree-shaking默认开启,因为tree-shaking是基于es6的静态导入,所以需要配置Babel转译时不要编译成非ES6模式的导入了。 tree-shaking很好理解就是剔除无用代码,但关键点在于这个看似无用的代码是不是真的无用,所以webpack要求给出这些文件是否含有副作用,一个易于理解的副作用例子是: 如果写了一个类,并把它注册成事件的回调,那么将会调用它的handleEvent方法,但并没有显式的调用它,比如better-scroll里所注册的事件,不过好像webpack并未做对类的shaking。
```javascript class Scroll { handleEvent() { console.log('You called me.') } } window.addEventListener('visibilitychange', new Scroll()) ```
-
Node端的脚手架(不了解,需要了解)。
-
Ts是方面React小小的尝试了一下Ts -> 主要就是T,配合React做了一个完整的上线项目,挺小不过五脏俱全:
- d.ts用来声明某些内容所含的内容,比如微信会嵌入一个WxJs,这时候就可以(必须)做一个类型的声明。
- 基础的接口啥的可以直接查文档,interface,变量,函数的类型声明等。
-
小程序写过项目。 这边除了原生,最近调研了一下多端小程序框架。
uni-app,社区活跃,案例很好,符合团队Vue技术栈,UI库上看着不错,瑕疵是字节小程序案例内的视频无法播放。
taro,宇宙警备队总教官,实力最强的奥特曼,taro3已支持Vue,同时还支持React,UI库上看着也很舒服,案例上字节小程序无法打开,有提供播放视频组件不过未有案例。
这边最终选了uni-app,做了一下demo。
-
适配方面vw适配方案感觉是很棒的,rem次之。
-
浏览器方面:Js事件循环一次task伴随多次microTask,主要应用 -> Vue中的nextTick(目前是一个microTask,在某个task执行之后会将当前所有的microTask执行,不然的话会排到task尾,一个例子是UI更新,这个会在微任务执行之后进行更新,如果nextTick是一个task那如果nextTick中的代码影响了UI更新总是会使其在这之后eg:
<div :style={ absolute, top: currentTop }></div>...scrollEventHandler() { this.$nextTick(() => { this.currentTop = clientTopHeight }) }
作用就是此元素始终保持在顶部(不要说为什么不用fixed)如果此时是一个task那么在滚动之后$nextTick注册的会在UI更新之后在执行,出现的视觉效果就是抖动,top的变化是 0 -> UI更新 -> 10px -> UI更新,那么如果是microTask,执行的则是 0 -> 10px -> UI更新,microtask一般有Promise.then,catch,finally, mutationObserver。 13.1 浏览器机制:冒泡/捕获 -> 冒泡是从触发的元素向上冒泡,捕获则是从外层向内传播。<body> <div> 1 </div> </body>
冒泡 -> div -> body。 捕获 body -> div。
跨域:这个主要在后端,放在后端讲,在这里提及主要是因为是这个限制是浏览器做的限制,解决方法由后端完成。
存储:cookies/localStore/sessionStore/indexedDB(没用过)
开发工具:performance/layers/Js Profilters/memery简单内存泄漏的修正。
预加载/异步script(调优用)
浏览器渲染:解析HTML -> 解析CSS ↓ ↓ -> 合并 -> 生成渲染树 -> 绘制 -> 显示。 生成DOM树 生成CSSDOM树
遇到script时会暂停DOM树的生成,直到脚本完成。 重绘与回流 重绘的发生是局部的,不影响整体会把部分重新渲染。 回流通常是整体的,元素的大小布局等改变。 重绘与回流不可避免但相对的不要频繁的触发他们,调试工具 chrome -> more tools -> render。
-
Js方面:核心注意点:变量范围,闭包作用域,this指向,事件循环,Promise,ES6的分包,import/export,new,继承。
-
部署方面,drone/Jenkins。
-
代码检查Eslint。
-
服务器端渲染(Nuxt)。
-
一些安全方面的知识(近期修复了XSS问题,以及针对XSS做了一次简略的分享,还有附带的CSRF)。
-
JS方面冒泡与捕获上的深入,由一个需求说起,为页面上非常多的可点击按钮增加一些额外的效果,使得在点击后先进行一些检查。
- 直接做的话是去已经绑定的点击事件中逐一添加这个检查函数,这样做的好处是直接去读绑定的事件即可知道所有的内容比较直观,符合第一印象,坏处是如果需要添加的内容非常多,那写起来非常麻烦并且如果后续要删除掉会很难受。
- 另一种方法是如果这些点击事件都进行了API的交互,那么可以在API请求前设置拦截器拦截对应的请求并作出相应的响应,这样的好处是代码统一管理,坏处是并不直观(考虑增加一些log)。
- 第三种方法目前只证实了可行并未实际使用,收集所有需要点击的按钮的class或id,需要唯一,至少页面内唯一,然后为其注册一个捕获事件,验证后发出一个自定义的同样事件重新冒泡。
这样做的好处与2.一致,坏处很明显,并不直观且容易造成BUG,因为class并不唯一。 当然实现方式上,如果结合Vue也可以用自定义指令配合1.来实现。
-
一个奇怪的腾讯视频Nuxt下的BUG,腾讯视频会添加一个后缀,而在Nuxt应用里会将后缀去除导致无限循环,去除逻辑在middleware里执行: https://nuxtjs.org/guides/concepts/nuxt-lifecycle/,看样子middleware会先与asyncData执行。
-
------...2020
这样。
那用纯CSS的写法我自己的实现是通过float的文字环绕效果+cover实现,
21.1 首先呢右下角的2020需要通过float:right 同时设置shape-outside: content-box以及padding-top让他出现在右下角,同时文字还能环绕在2020上方,利用的是shape-outside文字环绕效果。
22.2 这个多行省略没有直接的CSS属性可以用,我的实现是两层,一层是...另一层是cover,...恒定出现在同一个位置,也是文字环绕效果。
22.3 同时给文字设定一个position: relative,文字的最小高度与两行文字高度一致,不设置最大高度,同时最外层的高度是文字的最小高度一致,overflow: hidden,这一步是实现的是文字环绕+多行省略,文字折行后内层高度不断变高而外层hidden情况下就变成了省略,此时文字环绕效果生效会自动在在...处折行,这样就实现了多行省略。
22.4 上一步实现了多行省略,再来实现不多行时的不省略,这时候需要另一个cover,cover放在文字内,cover与...宽高一致,背景与外层背景一致,position: absolute,bottom: 0,right: 刚好在...位置,由于设置的最小高度与外层一致,所以bottom:0后只要right调的正好就可以覆盖住...,而当文字变成3行时,高度变高,cover随之变低,被挤下去hidden,这样就实现了一个多行省略。优缺点:
优点是可以实现上述效果。
缺点是right似乎在不同浏览器下渲染的px数不同,要做适配或者百分比固定,二是背景如果是图片或者渐变色需要写额外的内容。 -
less 里媒体查询重置变量:https://stackoverflow.com/questions/10906114/less-css-set-variables-in-media-query
-
读一读源码。
尤大说自己学习的方法就是看源码。我也来看源码,先从一个略微简单的看起。
需扩展:
-
Ts深入一点(高)。
-
React深入一点(高)。
-
Vue源码方向(高,当前目标)。
-
多端(低)。
-
微前端(中)。
-
canvas,svg(低看情况)。
-
Node(中)。
-
调优手段实践+体系构建(高,这个已经实践,效果不错继续加油)。
-
部署(低,已实践过需扩展下广度)。
现在看来广度应该并不必要,学习成本很低。
-
设计模式架构层(高)。
-
监控上报体系(高,当前目标)。
对于监控体系目前没有实践,不过借由一个机会我梳理了一个很小的思路,
上报:百度统计的对应dmt-hm的自定义属性以及全局状态的click判断target是一个很好的埋点切入点。
汇总:这里有开源的方案Grafana。
不了解:
- 测试体系。
- SEO。
- 可视化组件构建。
-
-
后端。 Python。 抓包工具,burp,wrishark。 Nginx(能说一说配一配)。 网络层(这里我狭义的理解为TCP/UDP相关内容,可以简略说一说,关于TCP后面做了一次简略的分享基本可以看那个pcapng的Wrishark分析包)。 数据库(查文档水平mysql用过)。 缓存(Redis查文档水平用过)。 跨域在这里说一下:需要返回一些HTTP头信息让浏览器确认这个域名可以跨域。具体可以在后端程序处或者Nginx处做处理。
-
软技能。
英语,还行,看文档没啥压力,听/写有点弱。
-
优。
Github不错有几个星星多的项目,学习能力不错。
-
劣。
学历没有,人脉不足,上限可能会低。
-
算法。 排序:归并(分治),快排(分治),冒泡,选择。
二叉树 -> 二叉排序树 -> 2-3(之前略懂,现在忘了) -> 红黑(不懂)
动态规划(解决子问题)。
回溯。
BFS/DFS。
图。
最短路径(忘了)。
堆。
栈。
队列。很久了,前端的业务方向接触的算法不多。
-
Git。
版本控制。 add commit push pull log checkout branch merge reset submodule cherry-pick rebase。