
获得徽章 1
#青训营笔记创作活动#
2月8日 Day26
Islands 架构原理
1.什么是 Islands 架构
这个架构主要用于 SSR (也包括 SSG) 应用,我们知道,在传统的 SSR 应用中,服务端会给浏览器响应完整的 HTML 内容,并在 HTML 中注入一段完整的 JS 脚本用于完成事件的绑定,也就是完成 hydration (注水) 的过程。当注水的过程完成之后,页面也才能真正地能够进行交互。当一个页面中只有部分的组件交互,那么对于这些可交互的组件,我们可以执行 hydration 过程,因为组件之间是互相独立的。而对于静态组件,即不可交互的组件,我们可以让其不参与 hydration 过程,直接复用服务端下发的 HTML 内容。可交互的组件就犹如整个页面中的孤岛(Island),因此这种模式叫做 Islands 架构。
2.实现原理
通过Astro来实现,在 Astro 中,默认所有的组件都是静态组件,Astro 除了支持本身 Astro 语法之外,也支持 Vue、React 等框架,可以通过插件的方式来导入。在构建的时候,Astro 只会打包并注入 Islands 组件的代码,并且在浏览器渲染,分别调用不同框架(Vue、React)的渲染函数完成各个 Islands 组件的 hydrate 过程。
2月8日 Day26
Islands 架构原理
1.什么是 Islands 架构
这个架构主要用于 SSR (也包括 SSG) 应用,我们知道,在传统的 SSR 应用中,服务端会给浏览器响应完整的 HTML 内容,并在 HTML 中注入一段完整的 JS 脚本用于完成事件的绑定,也就是完成 hydration (注水) 的过程。当注水的过程完成之后,页面也才能真正地能够进行交互。当一个页面中只有部分的组件交互,那么对于这些可交互的组件,我们可以执行 hydration 过程,因为组件之间是互相独立的。而对于静态组件,即不可交互的组件,我们可以让其不参与 hydration 过程,直接复用服务端下发的 HTML 内容。可交互的组件就犹如整个页面中的孤岛(Island),因此这种模式叫做 Islands 架构。
2.实现原理
通过Astro来实现,在 Astro 中,默认所有的组件都是静态组件,Astro 除了支持本身 Astro 语法之外,也支持 Vue、React 等框架,可以通过插件的方式来导入。在构建的时候,Astro 只会打包并注入 Islands 组件的代码,并且在浏览器渲染,分别调用不同框架(Vue、React)的渲染函数完成各个 Islands 组件的 hydrate 过程。
展开
评论
点赞
#青训营笔记创作活动#
2月7日 Day25
什么是Docker
富 Web 时代,应用变得越来越强大,与此同时也越来越复杂。集群部署、隔离环境、灰度发布以及动态扩容缺一不可,而容器化则成为中间的必要桥梁。
docker 使应用部署更加轻量,可移植,可扩展,更好的环境隔离也更大程度地避免了生产环境与测试环境不一致的巨大尴尬。
Docker 技术的三大核心概念,分别是:镜像 Image、容器 Container、仓库 Repository。Docker 底层使用了一些 linux 内核的特性,大概有 namespace,cgroups 和 ufs。
构建流程
首先安装Docker,可以通过软件安装或者命令行安装,然后我们使用Docker启动一个vue项目,然后对项目进行打包,此时项目目录下的 Dist 就是我们要部署的静态资源了。然后新建Dockerfile,拉去Nginx镜像,拉取成功后,在根目录创建Nginx配置文件,然后配置镜像和构建镜像,之后就可以运行容器和访问项目,最后发布镜像。
2月7日 Day25
什么是Docker
富 Web 时代,应用变得越来越强大,与此同时也越来越复杂。集群部署、隔离环境、灰度发布以及动态扩容缺一不可,而容器化则成为中间的必要桥梁。
docker 使应用部署更加轻量,可移植,可扩展,更好的环境隔离也更大程度地避免了生产环境与测试环境不一致的巨大尴尬。
Docker 技术的三大核心概念,分别是:镜像 Image、容器 Container、仓库 Repository。Docker 底层使用了一些 linux 内核的特性,大概有 namespace,cgroups 和 ufs。
构建流程
首先安装Docker,可以通过软件安装或者命令行安装,然后我们使用Docker启动一个vue项目,然后对项目进行打包,此时项目目录下的 Dist 就是我们要部署的静态资源了。然后新建Dockerfile,拉去Nginx镜像,拉取成功后,在根目录创建Nginx配置文件,然后配置镜像和构建镜像,之后就可以运行容器和访问项目,最后发布镜像。
展开
评论
点赞
#青训营笔记创作活动#
2月6日 Day24
三种大屏适配方案
1. vw+vh
按照设计稿的尺寸,将px按比例计算转为vw和vh,路径配置的话只需在vue.config.js里配置一下utils.scss的路径,用less的话就配置一下utils.less的路径,就可以全局使用了,这种使用方式有个弊端,就是屏幕尺寸发生变化后,需要手动刷新一下才能完成自适应调整,为了解决这个问题,你需要在各个图表中监听页面尺寸变化,重新调整图表,在 vue 项目中,也可以借助element-resize-detector,最好封装个 resize 的指令,在各图表中就只要使用该指令就可以了。
2.scale
通过 css 的 scale 属性,根据屏幕大小,对图表进行整体的等比缩放,从而达到自适应效果,比如当屏幕的尺寸比例刚好是 16:9 时,页面能刚好全屏展示,内容占满显示器,小于16:9 时,页面上下留白,左右占满并上下居中,显示比例保持 16:9,大于时,页面左右留白,上下占满并居中,显示比例仍然保持 16:9。
3.rem+vw+wh
显示效果跟scale的效果一样。rem(font size of the root element),是 css3 中新增的一个大小单位,即相对于根元素 font-size 值的大小。思路就是动态的计算出页面的 fontsize 从而改变 rem 的大小。首先获得 rem 的基准值,然后在页面内写一段 js 代码,动态的计算html根元素的font-size
2月6日 Day24
三种大屏适配方案
1. vw+vh
按照设计稿的尺寸,将px按比例计算转为vw和vh,路径配置的话只需在vue.config.js里配置一下utils.scss的路径,用less的话就配置一下utils.less的路径,就可以全局使用了,这种使用方式有个弊端,就是屏幕尺寸发生变化后,需要手动刷新一下才能完成自适应调整,为了解决这个问题,你需要在各个图表中监听页面尺寸变化,重新调整图表,在 vue 项目中,也可以借助element-resize-detector,最好封装个 resize 的指令,在各图表中就只要使用该指令就可以了。
2.scale
通过 css 的 scale 属性,根据屏幕大小,对图表进行整体的等比缩放,从而达到自适应效果,比如当屏幕的尺寸比例刚好是 16:9 时,页面能刚好全屏展示,内容占满显示器,小于16:9 时,页面上下留白,左右占满并上下居中,显示比例保持 16:9,大于时,页面左右留白,上下占满并居中,显示比例仍然保持 16:9。
3.rem+vw+wh
显示效果跟scale的效果一样。rem(font size of the root element),是 css3 中新增的一个大小单位,即相对于根元素 font-size 值的大小。思路就是动态的计算出页面的 fontsize 从而改变 rem 的大小。首先获得 rem 的基准值,然后在页面内写一段 js 代码,动态的计算html根元素的font-size
展开
评论
点赞
#青训营笔记创作活动#
2月5日 Day23
几个热门的开源前端低代码项目
1.LowCodeEngine
由阿里巴巴钉钉宜搭团队开发的低代码框架,基于阿里云的云基础设施和钉钉的企业数字化操作系统。使用者只需要基于低代码引擎便可以快速定制符合自己业务需求的低代码平台。同时LowCodeEngine还提供了很多的基础组件,可以帮助开发者快速的构建业务页面。
项目地址:
github.com
2.Amis
Amis 是百度开源的一款前端低代码框架,通过 JSON 配置就能生成各种后台页面,包括数据获取、表单提交及验证等功能,同时,Amis内置 100+ 种 UI 组件,能够满足各种页面组件展现的需求,极大减少开发成本,甚至可以不需要了解前端。
项目地址:
github.com
3.tmagic-editor
tmagic-editor是一款由腾讯技术中心出品的一款开源低代码框架,能够实现零代码/低代码生成页面 , 可以快速搭建可视化页面生产平台,让非技术人员可以通过拖拽和配置,自助生成H5页面、PC页面、TV页面,大大降低页面生产成本 。
项目地址:
gitee.com
4.vite-vue3-lowcode
vite-vue3-lowcode 是一款基于Vite2.x + Vue3.x + TypeScript技术框架的的H5 低代码平台。目前只是一个简单的模板,支持数据配置的导入和导出,配置的修改和删除操作,用到的技术有sandbox 中执行自定义逻辑、monaco-editor 自定义代码补全、vue3 createRenderer 自定义渲染器等。
项目地址:
github.com
2月5日 Day23
几个热门的开源前端低代码项目
1.LowCodeEngine
由阿里巴巴钉钉宜搭团队开发的低代码框架,基于阿里云的云基础设施和钉钉的企业数字化操作系统。使用者只需要基于低代码引擎便可以快速定制符合自己业务需求的低代码平台。同时LowCodeEngine还提供了很多的基础组件,可以帮助开发者快速的构建业务页面。
项目地址:
2.Amis
Amis 是百度开源的一款前端低代码框架,通过 JSON 配置就能生成各种后台页面,包括数据获取、表单提交及验证等功能,同时,Amis内置 100+ 种 UI 组件,能够满足各种页面组件展现的需求,极大减少开发成本,甚至可以不需要了解前端。
项目地址:
3.tmagic-editor
tmagic-editor是一款由腾讯技术中心出品的一款开源低代码框架,能够实现零代码/低代码生成页面 , 可以快速搭建可视化页面生产平台,让非技术人员可以通过拖拽和配置,自助生成H5页面、PC页面、TV页面,大大降低页面生产成本 。
项目地址:
4.vite-vue3-lowcode
vite-vue3-lowcode 是一款基于Vite2.x + Vue3.x + TypeScript技术框架的的H5 低代码平台。目前只是一个简单的模板,支持数据配置的导入和导出,配置的修改和删除操作,用到的技术有sandbox 中执行自定义逻辑、monaco-editor 自定义代码补全、vue3 createRenderer 自定义渲染器等。
项目地址:
展开
评论
点赞
#青训营笔记创作活动#
2月4日 Day22
高性能的树状结构
我们平时见到的树状结构一般都是每层数组中的item都会有一个children,里面嵌套一个数组然后每个子item也还会有各自的children,就这样一直嵌套下去。
而拍扁后的树状结构其实是一个对象,每个item都扁平化平铺在第一层,每一个item都有各自的parentId与childrenIds。
扁平化的不同
1.父节点
般都会有一个item专门来表示根节点,就比如这个对象第一行id为root的item。
2.子节点
对象中的每一项都可以当成是子节点,他们各自都拥有一个parentId,而根节点的parentId为空代表它没有父节点,他们的各自的childrenIds存储了他们各自item的子节点id。
3.渲染
我们一般渲染一个列表都是通过map进行遍历渲染,拿到对应的item通过itemRender()来处理对应的ReactNode,在渲染中其实两种状态的使用相差不大。
4.添加
不需要递归循环遍历整课树,可以发现,在整个结构中数据的表现是非常清晰的,每个item都是一样的。首先在Map新增一条子项数据,直接放在数据结构末尾即可,然后我们再给对应的父节点的childrenIds中push这个子项的id即可。
5.修改
拿到id之后就可以直接修改
6.删除
在Map形式中我们直接delete对应id的项即可,如果该项有父节点,我们可以在对应parentId项中的childrenIds移除对应的id即可。
2月4日 Day22
高性能的树状结构
我们平时见到的树状结构一般都是每层数组中的item都会有一个children,里面嵌套一个数组然后每个子item也还会有各自的children,就这样一直嵌套下去。
而拍扁后的树状结构其实是一个对象,每个item都扁平化平铺在第一层,每一个item都有各自的parentId与childrenIds。
扁平化的不同
1.父节点
般都会有一个item专门来表示根节点,就比如这个对象第一行id为root的item。
2.子节点
对象中的每一项都可以当成是子节点,他们各自都拥有一个parentId,而根节点的parentId为空代表它没有父节点,他们的各自的childrenIds存储了他们各自item的子节点id。
3.渲染
我们一般渲染一个列表都是通过map进行遍历渲染,拿到对应的item通过itemRender()来处理对应的ReactNode,在渲染中其实两种状态的使用相差不大。
4.添加
不需要递归循环遍历整课树,可以发现,在整个结构中数据的表现是非常清晰的,每个item都是一样的。首先在Map新增一条子项数据,直接放在数据结构末尾即可,然后我们再给对应的父节点的childrenIds中push这个子项的id即可。
5.修改
拿到id之后就可以直接修改
6.删除
在Map形式中我们直接delete对应id的项即可,如果该项有父节点,我们可以在对应parentId项中的childrenIds移除对应的id即可。
展开
评论
点赞
#青训营笔记创作活动#
2月3日 Day21
更好用的包管理器——pnpm
pnpm: Fast, disk space efficient package manager
特点:包安装速度极快,磁盘空间利用非常高效。
1.速度快
在绝多大数场景下,包安装的速度都是明显优于 npm/yarn,速度会比 npm/yarn 快 2-3 倍。
2.磁盘利用率高
pnpm 内部使用基于内容寻址的文件系统来存储磁盘上所有的文件,不会重复安装同一个包。即使一个包的不同版本,pnpm 也会极大程度地复用之前版本的代码。
3.支持 monorepo
在根目录下 pnpm add A -r, 那么所有的 package 中都会被添加 A 这个依赖。
4.pnpm依赖管理
将包本身和依赖放在同一个node_module下面,与原生 Node 完全兼容,又能将 package 与相关的依赖很好地组织到一起,根目录下的 node_modules 下面不再是眼花缭乱的依赖,而是跟 package.json 声明的依赖基本保持一致。即使 pnpm 内部会有一些包会设置依赖提升,会被提升到根目录 node_modules 当中,但整体上,根目录的node_modules比以前还是清晰和规范了许多。
5.安全问题
独创的一套依赖管理方式不仅解决了依赖提升的安全问题,还大大优化了时间和空间上的性能。
2月3日 Day21
更好用的包管理器——pnpm
pnpm: Fast, disk space efficient package manager
特点:包安装速度极快,磁盘空间利用非常高效。
1.速度快
在绝多大数场景下,包安装的速度都是明显优于 npm/yarn,速度会比 npm/yarn 快 2-3 倍。
2.磁盘利用率高
pnpm 内部使用基于内容寻址的文件系统来存储磁盘上所有的文件,不会重复安装同一个包。即使一个包的不同版本,pnpm 也会极大程度地复用之前版本的代码。
3.支持 monorepo
在根目录下 pnpm add A -r, 那么所有的 package 中都会被添加 A 这个依赖。
4.pnpm依赖管理
将包本身和依赖放在同一个node_module下面,与原生 Node 完全兼容,又能将 package 与相关的依赖很好地组织到一起,根目录下的 node_modules 下面不再是眼花缭乱的依赖,而是跟 package.json 声明的依赖基本保持一致。即使 pnpm 内部会有一些包会设置依赖提升,会被提升到根目录 node_modules 当中,但整体上,根目录的node_modules比以前还是清晰和规范了许多。
5.安全问题
独创的一套依赖管理方式不仅解决了依赖提升的安全问题,还大大优化了时间和空间上的性能。
展开
评论
点赞
赞了这篇文章
#青训营笔记创作活动#
2月2日 Day20
纯前端实现羊了个羊(基本框架记录)
游戏本体基本上就是由卡片组成,而卡片是以1/4为单位排列的
地图模拟主要分为单层和多层
1.基础生成
最基础的地图只关乎当前层,假设当前需要判定是否放置卡片的坐标为 [i, j],那么下面四个位置就不能存在卡片,否则就会出现同层卡片重叠。同时我们加入一个随机系数,保证每次生成的地图不同,Math.random() < 0.3 === true 的时候该位置才放置卡片
2.优化地图
卡片的分布是有规律的,左右对称,从顶层到底层越来越往中心聚集,卡片越来越少,上一层不会完全覆盖下一层。
3.卡片渲染
每次位置和随机数判定合格,我们应该实际放置一张卡片,一个实际的 dom。然后根据卡片的 x、y、z、宽高 值设置实际位置
4.填充数据
要保证卡片是 3 的倍数,同时需要随机(创建一个新数组,并且随机交换顺序即可)的把指定种类的卡片类型,以 3 的倍数填充(假设有 cardType 种类型的卡片,那么按 3 张重复填充即可)到现有卡片中去,只有顶层可以被点击,我们之前已经判定过卡片是否被覆盖的逻辑,做对应处理即可。一个简单的方法是给被覆盖的卡片设置一个特殊 style。
2月2日 Day20
纯前端实现羊了个羊(基本框架记录)
游戏本体基本上就是由卡片组成,而卡片是以1/4为单位排列的
地图模拟主要分为单层和多层
1.基础生成
最基础的地图只关乎当前层,假设当前需要判定是否放置卡片的坐标为 [i, j],那么下面四个位置就不能存在卡片,否则就会出现同层卡片重叠。同时我们加入一个随机系数,保证每次生成的地图不同,Math.random() < 0.3 === true 的时候该位置才放置卡片
2.优化地图
卡片的分布是有规律的,左右对称,从顶层到底层越来越往中心聚集,卡片越来越少,上一层不会完全覆盖下一层。
3.卡片渲染
每次位置和随机数判定合格,我们应该实际放置一张卡片,一个实际的 dom。然后根据卡片的 x、y、z、宽高 值设置实际位置
4.填充数据
要保证卡片是 3 的倍数,同时需要随机(创建一个新数组,并且随机交换顺序即可)的把指定种类的卡片类型,以 3 的倍数填充(假设有 cardType 种类型的卡片,那么按 3 张重复填充即可)到现有卡片中去,只有顶层可以被点击,我们之前已经判定过卡片是否被覆盖的逻辑,做对应处理即可。一个简单的方法是给被覆盖的卡片设置一个特殊 style。
展开
评论
点赞
#青训营笔记创作活动#
2月1日 Day19
一些浏览器调试技巧
1.console.log
最常用的功能,基本上每天都会使用到,作用也很简单,在控制台输出内容。
2.console.warn
在控制台输出警告信息,用于代码存在不合理或不符合规范但不影响系统运行的提示.
3.console.error
在控制台输出错误信息,用于代码错误和异常的提示
4.console.time和console.timeEnd
这两个方法一般是配合使用,用于计算代码段的执行时间,有助于性能调试和判断。我们可以根据输出的时间判断是否符合我们的预期,是否需要对其做进一步优化,也可以判断是否是由于某一块代码执行时间太长,占用太长线程时间,导致我们页面卡顿等一系列问题。
5.console.assert
第一个参数为 false(例如null,undefined,'',0,或者结果为false的逻辑等)的情况下会在控制台输出错误日志,可以减少书写判断逻辑,用于判断空值或者false逻辑还是很有用处的。
6.console.dir
对于DOM节点的打印输出,如果采用console.log,会以标签的形式输出,和直接查看没有太大的差异,有时我们可能想要查看DOM的相关事件和属性,可以采用console.dir,输出DOM节点对应的js对象映射。
DOM断点
当你想对DOM节点发生变化时进行断点,请使用 DOM 更改断点,最终还是会断点到触发dom操作的相应js上,但是更加高效。
2月1日 Day19
一些浏览器调试技巧
1.console.log
最常用的功能,基本上每天都会使用到,作用也很简单,在控制台输出内容。
2.console.warn
在控制台输出警告信息,用于代码存在不合理或不符合规范但不影响系统运行的提示.
3.console.error
在控制台输出错误信息,用于代码错误和异常的提示
4.console.time和console.timeEnd
这两个方法一般是配合使用,用于计算代码段的执行时间,有助于性能调试和判断。我们可以根据输出的时间判断是否符合我们的预期,是否需要对其做进一步优化,也可以判断是否是由于某一块代码执行时间太长,占用太长线程时间,导致我们页面卡顿等一系列问题。
5.console.assert
第一个参数为 false(例如null,undefined,'',0,或者结果为false的逻辑等)的情况下会在控制台输出错误日志,可以减少书写判断逻辑,用于判断空值或者false逻辑还是很有用处的。
6.console.dir
对于DOM节点的打印输出,如果采用console.log,会以标签的形式输出,和直接查看没有太大的差异,有时我们可能想要查看DOM的相关事件和属性,可以采用console.dir,输出DOM节点对应的js对象映射。
DOM断点
当你想对DOM节点发生变化时进行断点,请使用 DOM 更改断点,最终还是会断点到触发dom操作的相应js上,但是更加高效。
展开
评论
点赞
#青训营笔记创作活动#
1月31日 Day18
几个实用的CSS函数
1.Clamp()函数
作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。
使用场景:流体的尺寸和定位,装饰性元素,流体高度,Loading Bar
2.Max()函数
让你可以从一个逗号分隔的表达式列表中选择最大的值作为属性的值。接受一个或多个用逗号分隔的表达式作为他的参数,数值最大的表达式的值将会作为指定的属性的值。
使用CSS max()函数,根据视口宽度,将卡片的border-radius 从 0px 切换到 8px。
3.Min()函数
让你可以从一个逗号分隔的表达式列表中选择最小的值作为属性的值。接受一个或多个用逗号分隔的表达式作为他的参数,数值最小的表达式的值将会作为指定的属性的值。
min() 函数在 8px 和 calc((100vw - 4px - 100%) * 9999 的计算值之间进行比较,这会得到一个非常大的正数或负数。
1月31日 Day18
几个实用的CSS函数
1.Clamp()函数
作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。
使用场景:流体的尺寸和定位,装饰性元素,流体高度,Loading Bar
2.Max()函数
让你可以从一个逗号分隔的表达式列表中选择最大的值作为属性的值。接受一个或多个用逗号分隔的表达式作为他的参数,数值最大的表达式的值将会作为指定的属性的值。
使用CSS max()函数,根据视口宽度,将卡片的border-radius 从 0px 切换到 8px。
3.Min()函数
让你可以从一个逗号分隔的表达式列表中选择最小的值作为属性的值。接受一个或多个用逗号分隔的表达式作为他的参数,数值最小的表达式的值将会作为指定的属性的值。
min() 函数在 8px 和 calc((100vw - 4px - 100%) * 9999 的计算值之间进行比较,这会得到一个非常大的正数或负数。
展开
评论
点赞
#青训营笔记创作活动#
1月30日 Day17
用CSS来监听事件
很多场合都要用到定时器,比如延迟加载、定时查询等等,但定时器的控制有时候会有些许麻烦,比如鼠标移入停止、移出再重新开始。这个时候就可以借助CSS来控制,使用起来更方便。
1.hover延时触发
需求:在鼠标停留在一个元素上1s后才触发事件,不满1s就不会触发,这样的好处是,可以避免鼠标在快速划过时,频繁的触发事件。
实现:就是先给需要触发的元素加一个有延时的transition,里只需一个无关紧要的样式就行,如果opacity已经使用过了,可以使用其他的,比如transform:translateZ(.1px),也是可行的。然后添加监听transitionend方法,这样就可以了,甚至不用操作DOM。
2.长按触发事件
需求:长按触发元素选中。
实现:通过:active伪类中的transition来实现,然后添加监听transitionend方法.
3.轮播和暂停
需求:轮播图自动播放,然后鼠标hover时会暂停轮播图。
实现:借助setInterval来实现重复触发,然后设置animation为Infinite就可以实现无限循环,然后直接通过:hover伪类来暂停和播放动画,监听每次动画的触发可以用animationiteration这个方法,表示每个动画轮回就触发一次,然后再监听animationiteration事件就可以实现了。
1月30日 Day17
用CSS来监听事件
很多场合都要用到定时器,比如延迟加载、定时查询等等,但定时器的控制有时候会有些许麻烦,比如鼠标移入停止、移出再重新开始。这个时候就可以借助CSS来控制,使用起来更方便。
1.hover延时触发
需求:在鼠标停留在一个元素上1s后才触发事件,不满1s就不会触发,这样的好处是,可以避免鼠标在快速划过时,频繁的触发事件。
实现:就是先给需要触发的元素加一个有延时的transition,里只需一个无关紧要的样式就行,如果opacity已经使用过了,可以使用其他的,比如transform:translateZ(.1px),也是可行的。然后添加监听transitionend方法,这样就可以了,甚至不用操作DOM。
2.长按触发事件
需求:长按触发元素选中。
实现:通过:active伪类中的transition来实现,然后添加监听transitionend方法.
3.轮播和暂停
需求:轮播图自动播放,然后鼠标hover时会暂停轮播图。
实现:借助setInterval来实现重复触发,然后设置animation为Infinite就可以实现无限循环,然后直接通过:hover伪类来暂停和播放动画,监听每次动画的触发可以用animationiteration这个方法,表示每个动画轮回就触发一次,然后再监听animationiteration事件就可以实现了。
展开
评论
点赞
#青训营笔记创作活动#
1月29日 Day16
前端实现人脸识别
1.创建人脸模型
引入tensorflow训练好的人脸特征点检测模型,预测 486 个 3D 人脸特征点,推断出人脸的近似面部几何图形。
2.特征检测
人脸特征提取就是针对人脸的某些特征进行判断(以下的动作判断仅供参考,实际情况下需要多个特征点来判断某个动作)
2.1判断人脸的远近
取4帧 人脸占画面的比例,判断这组值是递增或递减,取第一帧和最后最后一帧的占比,根据阈值判断人脸的远近。
2.2判断张嘴
取2帧 嘴唇[10,152]占人脸长度[0,17]的比例,判断递增,取第一帧和最后最后一帧的距离,根据阈值判断张嘴。
2.3判断眨眼
根据左眼[159, 144] 右眼[385, 374]的距离,判断连续4帧小于阈值,即可判断眨眼了。
1月29日 Day16
前端实现人脸识别
1.创建人脸模型
引入tensorflow训练好的人脸特征点检测模型,预测 486 个 3D 人脸特征点,推断出人脸的近似面部几何图形。
2.特征检测
人脸特征提取就是针对人脸的某些特征进行判断(以下的动作判断仅供参考,实际情况下需要多个特征点来判断某个动作)
2.1判断人脸的远近
取4帧 人脸占画面的比例,判断这组值是递增或递减,取第一帧和最后最后一帧的占比,根据阈值判断人脸的远近。
2.2判断张嘴
取2帧 嘴唇[10,152]占人脸长度[0,17]的比例,判断递增,取第一帧和最后最后一帧的距离,根据阈值判断张嘴。
2.3判断眨眼
根据左眼[159, 144] 右眼[385, 374]的距离,判断连续4帧小于阈值,即可判断眨眼了。
展开
评论
点赞
#青训营笔记创作活动#
1月28日 Day15
Ant Design ——调试源码
1.前期工作
首先,我们用 create-react-app 创建一个 react 项目,创建成功后,进入到项目里,把 dev server 跑起来,然后我们安装 antd,在入口组件里引入样式和 Button 组件,页面会显示这个 Button。
2.调试主要流程
首先,创建一个 VSCode 调试配置,指定调试的 URL,然后启动调试,可以看到调用栈中上一帧是 renderWithHooks,这就是 react 源码里调用函数组件的地方。
3.直接调试tsx源码
用 sourcemap 来实现,antd 是 react 主流组件库,我们经常使用它但可能并没有调试过它的源码。
我们可以在 renderWithHooks 里调用函数组件的地方打个条件断点,在调用想调试的组件时断住,这样我们就可以 step into 到该组件定义的地方。
但是这样调试的并不是最初的源码,没有 jsx 和 ts 语法。
想调试最初的 tsx 源码需要用 sourcemap。把产物覆盖 antd 的 dist 下的产物,再调试就可以直接调试 antd 组件的 tsx 源码了。
1月28日 Day15
Ant Design ——调试源码
1.前期工作
首先,我们用 create-react-app 创建一个 react 项目,创建成功后,进入到项目里,把 dev server 跑起来,然后我们安装 antd,在入口组件里引入样式和 Button 组件,页面会显示这个 Button。
2.调试主要流程
首先,创建一个 VSCode 调试配置,指定调试的 URL,然后启动调试,可以看到调用栈中上一帧是 renderWithHooks,这就是 react 源码里调用函数组件的地方。
3.直接调试tsx源码
用 sourcemap 来实现,antd 是 react 主流组件库,我们经常使用它但可能并没有调试过它的源码。
我们可以在 renderWithHooks 里调用函数组件的地方打个条件断点,在调用想调试的组件时断住,这样我们就可以 step into 到该组件定义的地方。
但是这样调试的并不是最初的源码,没有 jsx 和 ts 语法。
想调试最初的 tsx 源码需要用 sourcemap。把产物覆盖 antd 的 dist 下的产物,再调试就可以直接调试 antd 组件的 tsx 源码了。
展开
评论
点赞
#青训营笔记创作活动#
1月27日 Day14
fabric.js快速开发图片编辑器
一个开源的项目,具体代码详见文末链接,该笔记只对功能设计层面进行记录。
1.架构设计
fabric.js是一个强大的canvas库,框架采用vue,主要解决如何把fabric的实例对象共享给各个功能组件,区分出是未选中、单选、多选状态,然后将选中、取消选中事件暴露给各个功能组件,子组件根据状态进行独立的功能开发。
2.解决方法
在入口文件中初始化实例,然后与mixins结合,在mixins中定义了选择类型(多选、单选、未选中)、选中元素类型、选中id等属性,以及选中、取消选中的事件,子组件通过引入mixins来开发对应功能;如子组件需要对fabric对象进行操作,则可以通过inject获得原始对象。
3.基本功能
背景设置(主要包括置画布大小、设置背景颜色、设置背景图片,也可以设置背景重复方向)。
插入元素(主要包括插入基础元素文字、正方形、圆形、三角形、SVG元素)。
属性调整(不同元素的属性会有差异,但通用属性是一致的,如填充颜色、坐标、旋转角度、透明度等,也有很多特定元素的特定属性,如文字的字体属性、图片的滤镜属性等,
字体属性可以自定义字体,需要先下载字体后再进行设置,可以通过fontfaceobserver工具库下载指定字体,成功后在设置字体名称)。
元素对齐(区分单选元素与多选元素,单选元素时只支持相对于画布水平、垂直、水平垂直对齐)
编辑器经常需要给元素进行分组/拆分组合、调整层级、回退、快捷键、画布放大/缩小、导入/导出文件等功能,不再一一罗列,这个小编辑器都已经支持,大家感兴趣的可以看源码。
fabric.js的功能很强大,可以很轻松的开发出一个简版的图片编辑器,自定义素材、模板、字体文件;还可以结合数据接口拼接模板生成图片,很轻松的实现定制模板 + 生成图片的功能
1月27日 Day14
fabric.js快速开发图片编辑器
一个开源的项目,具体代码详见文末链接,该笔记只对功能设计层面进行记录。
1.架构设计
fabric.js是一个强大的canvas库,框架采用vue,主要解决如何把fabric的实例对象共享给各个功能组件,区分出是未选中、单选、多选状态,然后将选中、取消选中事件暴露给各个功能组件,子组件根据状态进行独立的功能开发。
2.解决方法
在入口文件中初始化实例,然后与mixins结合,在mixins中定义了选择类型(多选、单选、未选中)、选中元素类型、选中id等属性,以及选中、取消选中的事件,子组件通过引入mixins来开发对应功能;如子组件需要对fabric对象进行操作,则可以通过inject获得原始对象。
3.基本功能
背景设置(主要包括置画布大小、设置背景颜色、设置背景图片,也可以设置背景重复方向)。
插入元素(主要包括插入基础元素文字、正方形、圆形、三角形、SVG元素)。
属性调整(不同元素的属性会有差异,但通用属性是一致的,如填充颜色、坐标、旋转角度、透明度等,也有很多特定元素的特定属性,如文字的字体属性、图片的滤镜属性等,
字体属性可以自定义字体,需要先下载字体后再进行设置,可以通过fontfaceobserver工具库下载指定字体,成功后在设置字体名称)。
元素对齐(区分单选元素与多选元素,单选元素时只支持相对于画布水平、垂直、水平垂直对齐)
编辑器经常需要给元素进行分组/拆分组合、调整层级、回退、快捷键、画布放大/缩小、导入/导出文件等功能,不再一一罗列,这个小编辑器都已经支持,大家感兴趣的可以看源码。
fabric.js的功能很强大,可以很轻松的开发出一个简版的图片编辑器,自定义素材、模板、字体文件;还可以结合数据接口拼接模板生成图片,很轻松的实现定制模板 + 生成图片的功能
展开
评论
点赞
#青训营笔记创作活动#
1月26日 Day13
用CSS来做节流
众所周知,函数节流(throttle)是 JS 中一个非常常见的优化手段,可以有效的避免函数过于频繁的执行。
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候很多人会使用throttle函数,或者直接引用lodash工具库
但其实也可以通CSS来实现。
1.实现思路
通过禁用事件来对点击事件进行限制,通过animation来设置事件的限制,每次点击后需要自动禁用300ms,时间过后重新恢复。至于点击行为也就是触发时机,通过伪类:active来实现。其实可以看作是对CSS动画的控制,比如有一个动画控制按钮从禁用->可点击的变化,每次点击时让这个动画重新执行一遍,在执行的过程中,一直处于禁用状态。
2.精准控制
设置点击事件后,这时的按钮连续点击就会不断地触发,定义一个动画,然后将这个动画绑定在按钮上,这里为了方便测试,将动画设置成了2s。这里动画的缓动函数设置成了阶梯曲线,step-end,它可以很方便的控制pointer-events的变化时间点。最后,在点击时重新执行一遍动画,只需要在按下时设置动画为none就行了。
3.其他思路
通过定时器,来使用CSS监听事件,通过:active去触发transition变化,然后通过监听transition回调去动态设置按钮的禁用状态。这样做的最大好处是,这部分禁用的逻辑是完全和业务逻辑是解耦的,可以在任意时候,任意场合下无缝接入,也不受框架和环境影响。
4.总结
CSS 的实现思路和 JS 不同,重点在于在于找到和该场景相关联的属性,还可以通过 transition 的回调函数动态设置按钮禁用状态,这种实现方式还是比较有局限的,仅限于点击行为,像很多时候,节流可能会用在滚动事件或者键盘事件上,像这些场景就用传统方式实现就行了。
1月26日 Day13
用CSS来做节流
众所周知,函数节流(throttle)是 JS 中一个非常常见的优化手段,可以有效的避免函数过于频繁的执行。
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候很多人会使用throttle函数,或者直接引用lodash工具库
但其实也可以通CSS来实现。
1.实现思路
通过禁用事件来对点击事件进行限制,通过animation来设置事件的限制,每次点击后需要自动禁用300ms,时间过后重新恢复。至于点击行为也就是触发时机,通过伪类:active来实现。其实可以看作是对CSS动画的控制,比如有一个动画控制按钮从禁用->可点击的变化,每次点击时让这个动画重新执行一遍,在执行的过程中,一直处于禁用状态。
2.精准控制
设置点击事件后,这时的按钮连续点击就会不断地触发,定义一个动画,然后将这个动画绑定在按钮上,这里为了方便测试,将动画设置成了2s。这里动画的缓动函数设置成了阶梯曲线,step-end,它可以很方便的控制pointer-events的变化时间点。最后,在点击时重新执行一遍动画,只需要在按下时设置动画为none就行了。
3.其他思路
通过定时器,来使用CSS监听事件,通过:active去触发transition变化,然后通过监听transition回调去动态设置按钮的禁用状态。这样做的最大好处是,这部分禁用的逻辑是完全和业务逻辑是解耦的,可以在任意时候,任意场合下无缝接入,也不受框架和环境影响。
4.总结
CSS 的实现思路和 JS 不同,重点在于在于找到和该场景相关联的属性,还可以通过 transition 的回调函数动态设置按钮禁用状态,这种实现方式还是比较有局限的,仅限于点击行为,像很多时候,节流可能会用在滚动事件或者键盘事件上,像这些场景就用传统方式实现就行了。
展开
评论
点赞
#青训营笔记创作活动#
1月25日 Day12
阿里的一次面试经历
一个朋友分享的阿里四面的问题,“请设计一个不能操作DOM和调接口的环境”。
传统的思路实现起来并不好实现,比如直接修改 window.document 的值,让开发者无法获取 document,但这个值其实是不能修改的,而禁用调接口的方法不能禁用第三方库,因为第三方库太多了。
而这个问题用沙箱就可以完美解决,沙箱(Sandbox) 是一种安全机制,为运行中的程序提供隔离环境,通常用于执行未经测试或不受信任的程序或代码,它会为待执行的程序创建一个独立的执行环境,内部程序的执行不会影响到外部程序的运行
iframe 标签可以创造一个独立的浏览器原生级别的运行环境,这个环境由浏览器实现了与主环境的隔离,利用 iframe 来实现一个沙箱是目前最方便、简单、安全的方法,可以把 iframe.contentWindow 作为沙箱执行的全局 window 对象,沙箱中对window的所有操作,都没有影响到外层的window,实现了隔离的效果。
然后主要进行两部分的操作
1.设置 blacklist 黑名单,添加 document、XMLHttpRequest、fetch、WebSocket 来禁止开发者操作DOM和调接口
2.判断要访问的变量,是否在当前环境的 window 对象中,不在的直接报错,实现禁止通过三方库调接口
而对于一些其他的获取DOM操作,比如通过 window.document 来获取 document 对象,依然是可以操作 DOM 的,所以需要在黑名单中添加windows字段来解决,同时虽然把 window 加入了黑名单,但 window 上的方法,如 open、close 等,依然是可以正常获取使用的。
对于通过new Image()调接口的方式,就可以通过在黑名单中添加Image字段来解决。
如果有其他的bug,也可以尝试在黑名单添加对应的字段来禁止调用。
1月25日 Day12
阿里的一次面试经历
一个朋友分享的阿里四面的问题,“请设计一个不能操作DOM和调接口的环境”。
传统的思路实现起来并不好实现,比如直接修改 window.document 的值,让开发者无法获取 document,但这个值其实是不能修改的,而禁用调接口的方法不能禁用第三方库,因为第三方库太多了。
而这个问题用沙箱就可以完美解决,沙箱(Sandbox) 是一种安全机制,为运行中的程序提供隔离环境,通常用于执行未经测试或不受信任的程序或代码,它会为待执行的程序创建一个独立的执行环境,内部程序的执行不会影响到外部程序的运行
iframe 标签可以创造一个独立的浏览器原生级别的运行环境,这个环境由浏览器实现了与主环境的隔离,利用 iframe 来实现一个沙箱是目前最方便、简单、安全的方法,可以把 iframe.contentWindow 作为沙箱执行的全局 window 对象,沙箱中对window的所有操作,都没有影响到外层的window,实现了隔离的效果。
然后主要进行两部分的操作
1.设置 blacklist 黑名单,添加 document、XMLHttpRequest、fetch、WebSocket 来禁止开发者操作DOM和调接口
2.判断要访问的变量,是否在当前环境的 window 对象中,不在的直接报错,实现禁止通过三方库调接口
而对于一些其他的获取DOM操作,比如通过 window.document 来获取 document 对象,依然是可以操作 DOM 的,所以需要在黑名单中添加windows字段来解决,同时虽然把 window 加入了黑名单,但 window 上的方法,如 open、close 等,依然是可以正常获取使用的。
对于通过new Image()调接口的方式,就可以通过在黑名单中添加Image字段来解决。
如果有其他的bug,也可以尝试在黑名单添加对应的字段来禁止调用。
展开
评论
点赞
#青训营笔记创作活动#
1月24日 Day11
一项技能——Vue项目屏幕适配方案
1.基于rem的适配方案
(1)rem的概念
rem是指相对于根元素的字体大小的单位,在日常开发过程中我们通常把根元素(html/body)的字体设置为10px,方便于我们计算(此时子元素的1rem就相当于10px)
(2)适用场景不固定宽高比的Web应用,适用于绝大部分业务场景。(3)应用步骤安装依赖npmipostcss-pxtoremautoprefixeramfe-flexible--save-devpostcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位autoprefixer浏览器前缀处理插件amfe-flexible可伸缩布局方案替代了原先的lib-flexible选用了当前众多浏览器兼容的viewport项目根目录创建postcss.config.js文件main.ts/js文件中导入依赖:import"amfe-flexible/index.js"重启项目
2.基于scale的适配方案
(1)scale的相关方法在CSS3中,我们可以使用transform属性的scale()方法来实现元素的缩放效果。缩放,指的是“缩小”和“放大”的意思。transform:scaleX(x);/沿x轴方向缩放/transform:scaleY(y);/沿y轴方向缩放/transform:scale();/同时沿x轴和y轴缩放/
(2)适用场景固定宽高比的Web应用,如大屏或者固定窗口业务应用
(3)应用步骤新建resize.ts/js文件相关界面引入resize.ts/js
1月24日 Day11
一项技能——Vue项目屏幕适配方案
1.基于rem的适配方案
(1)rem的概念
rem是指相对于根元素的字体大小的单位,在日常开发过程中我们通常把根元素(html/body)的字体设置为10px,方便于我们计算(此时子元素的1rem就相当于10px)
(2)适用场景不固定宽高比的Web应用,适用于绝大部分业务场景。(3)应用步骤安装依赖npmipostcss-pxtoremautoprefixeramfe-flexible--save-devpostcss-pxtorem是PostCSS的插件,用于将像素单元生成rem单位autoprefixer浏览器前缀处理插件amfe-flexible可伸缩布局方案替代了原先的lib-flexible选用了当前众多浏览器兼容的viewport项目根目录创建postcss.config.js文件main.ts/js文件中导入依赖:import"amfe-flexible/index.js"重启项目
2.基于scale的适配方案
(1)scale的相关方法在CSS3中,我们可以使用transform属性的scale()方法来实现元素的缩放效果。缩放,指的是“缩小”和“放大”的意思。transform:scaleX(x);/沿x轴方向缩放/transform:scaleY(y);/沿y轴方向缩放/transform:scale();/同时沿x轴和y轴缩放/
(2)适用场景固定宽高比的Web应用,如大屏或者固定窗口业务应用
(3)应用步骤新建resize.ts/js文件相关界面引入resize.ts/js
展开
评论
点赞
#青训营笔记创作活动#
1月23日 Day10
一些当时非常火的CSS属性
1. position: sticky
吸顶:也就是在滚动列表的时候,标题会一直贴着最顶上,sticky这个值就可以实现这个效果。
2. :empty 选择器
数据一般都是通过请求接口获取的,当然也会存在接口没有数据的情况。这个时候需要给用户一个提示,通过:empty这个选择器,就可以通过css来实现这个操作,通过:empty选中内容为空的容器,然后通过伪元素为空容器添加提示。
3. gap
让多个元素之间隔开某个值的距离,可以通过gap: xx px来设置。
4. background-clip: text
实现一个带背景的文字效果,也就是用图一的背景,填充图二的文字,达到一个带有背景的文字效果。
5. user-select
禁用光标选中。
6. :invalid 伪类
实现当input元素或form元素的值有效时,元素颜色为绿色,无效时为红色,直接设置input:required:invalid的border-color属性即可实现。
7. :focus-within 伪类
表示一个元素获得焦点,或该元素的后代元素获得焦点,就会出现颜色变化效果。
8. mix-blend-mode:difference
描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。其中,difference 表示差值。实现一种特殊的颜色混合模式,达到想要的不规则样式。
1月23日 Day10
一些当时非常火的CSS属性
1. position: sticky
吸顶:也就是在滚动列表的时候,标题会一直贴着最顶上,sticky这个值就可以实现这个效果。
2. :empty 选择器
数据一般都是通过请求接口获取的,当然也会存在接口没有数据的情况。这个时候需要给用户一个提示,通过:empty这个选择器,就可以通过css来实现这个操作,通过:empty选中内容为空的容器,然后通过伪元素为空容器添加提示。
3. gap
让多个元素之间隔开某个值的距离,可以通过gap: xx px来设置。
4. background-clip: text
实现一个带背景的文字效果,也就是用图一的背景,填充图二的文字,达到一个带有背景的文字效果。
5. user-select
禁用光标选中。
6. :invalid 伪类
实现当input元素或form元素的值有效时,元素颜色为绿色,无效时为红色,直接设置input:required:invalid的border-color属性即可实现。
7. :focus-within 伪类
表示一个元素获得焦点,或该元素的后代元素获得焦点,就会出现颜色变化效果。
8. mix-blend-mode:difference
描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。其中,difference 表示差值。实现一种特殊的颜色混合模式,达到想要的不规则样式。
展开
评论
点赞
#青训营笔记创作活动#
1月22日 Day9
图片压缩---前端的必备技能
1.TinyPng
很多时候,我们从 PS 等工具导出来的图片,或者是美术直接给到切图,都是未经过压缩的,体积都比较大。这里,就有了可优化的空间。TinyPNG使用智能的有损压缩技术来减少WEBP、JPEG和PNG文件的文件大小。通过选择性地减少图像中的颜色数量,使用更少的字节来存储数据。这种效果几乎是看不见的,但在文件大小上有非常大的差别。TinyPng提供两种压缩方法:一是通过在官网上进行手动压缩,二是通过官方提供的tinify进行压缩。
2.实现思路
总体分为五个过程,查找(找出所有的图片资源);分配(均分任务到每个进程);上传(把原图上传到TinyPng);下载(从TinyPng中下载压缩好的图片);写入(用下载的图片覆盖本地图片)。
3.具体流程
查找:通过命令行交互后,拿到目标文件夹的路径path,然后获取该path下的所有内容,接着遍历所有内容。首先判断该内容的文件信息:若为“文件夹”,则把该文件夹路径作为path,递归调用deepFindImg;若不为“文件夹”,判断该内容为图片,则读取图片数据,push到images中。最后,返回所有找到的图片。
均分:使用cluster,根据cpu核心数创建等量的进程,works用于保存已创建的进程,list中保存的是要处理的压缩任务,通过遍历list,把任务依次分给每一个进程。接着遍历works,通过send方法发送进程任务。通过监听message事件,利用pageNum记录进程任务的完成情况,当所有进程任务执行完毕后,则关闭进程。
上传:使用node自带的Https模块,构造请求头,把deepFindImg中返回的图片进行上传。上传成功后,会返回已经压缩好的图片的url链接。
下载:使用node自带的Https模块把upload中返回的图片链接进行下载。下载成功后,返回图片的buffer数据。
写入:process.on监听每个进程发送的任务,当接收到任务类型为「图片」,使用compressImg方法来处理图片。当任务类型为svga,使用compressSvga方法来处理svga。最后把处理好的资源写入到本地覆盖旧资源。
1月22日 Day9
图片压缩---前端的必备技能
1.TinyPng
很多时候,我们从 PS 等工具导出来的图片,或者是美术直接给到切图,都是未经过压缩的,体积都比较大。这里,就有了可优化的空间。TinyPNG使用智能的有损压缩技术来减少WEBP、JPEG和PNG文件的文件大小。通过选择性地减少图像中的颜色数量,使用更少的字节来存储数据。这种效果几乎是看不见的,但在文件大小上有非常大的差别。TinyPng提供两种压缩方法:一是通过在官网上进行手动压缩,二是通过官方提供的tinify进行压缩。
2.实现思路
总体分为五个过程,查找(找出所有的图片资源);分配(均分任务到每个进程);上传(把原图上传到TinyPng);下载(从TinyPng中下载压缩好的图片);写入(用下载的图片覆盖本地图片)。
3.具体流程
查找:通过命令行交互后,拿到目标文件夹的路径path,然后获取该path下的所有内容,接着遍历所有内容。首先判断该内容的文件信息:若为“文件夹”,则把该文件夹路径作为path,递归调用deepFindImg;若不为“文件夹”,判断该内容为图片,则读取图片数据,push到images中。最后,返回所有找到的图片。
均分:使用cluster,根据cpu核心数创建等量的进程,works用于保存已创建的进程,list中保存的是要处理的压缩任务,通过遍历list,把任务依次分给每一个进程。接着遍历works,通过send方法发送进程任务。通过监听message事件,利用pageNum记录进程任务的完成情况,当所有进程任务执行完毕后,则关闭进程。
上传:使用node自带的Https模块,构造请求头,把deepFindImg中返回的图片进行上传。上传成功后,会返回已经压缩好的图片的url链接。
下载:使用node自带的Https模块把upload中返回的图片链接进行下载。下载成功后,返回图片的buffer数据。
写入:process.on监听每个进程发送的任务,当接收到任务类型为「图片」,使用compressImg方法来处理图片。当任务类型为svga,使用compressSvga方法来处理svga。最后把处理好的资源写入到本地覆盖旧资源。
展开
评论
点赞