如何监听容器高度变化(二)
在【如何监听容器高度变化(一)】 中介绍了几种使用模拟(iframe/object/scroll)的方式获取容器实时高度的方法,这篇文章主要介绍可以监听变化的API。
Mutation Events容器高度是由 dom 节点的操作(如插入、渲染、移除等)引起的,如果我们可以监听到 dom 节点的子节点、属性、文本节点等的变化,就可以获取到此时容器的高度,从而实现对于容器高度的监听。
Mutation Events 是 DOM3 中定义的针对 dom 节点更改的事件,支持的事件如下:
DOMAttrModified:dom 属性变更
DOMAttributeNameChanged:dom 属性名修改
DOMCharacterDataModified:dom 文本数据发生修改
DOMElementNameChanged:dom 元素名发生变化
DOMNodeInserted:dom 节点插入
DOMNodeInsertedIntoDocument:dom 节点插入
DOMNodeRemoved:dom 节点删除
DOMNodeRemovedFromDocument:dom 节点删除
DO ...
如何监听容器高度变化(一)
首先说一下场景:单品页详情模块有一个折叠展示的功能,如果内容超出指定高度只展示一部分并显示“查看全部”的按钮。因为详情部分除了文字、表格之外,还会有图片等异步加载的资源会影响内容整体的高度,所以需要获取内容部分的实时高度。
如果要实现上面的功能,有以下方式:
变通一下,因为详情模块不会在首屏展示,可以修改成滚动到该模块的时候再获取高度。这纯粹是个懒办法,如果有相似功能的模块在首屏展示,这种方法不适用。
给异步加载的资源添加onload事件,加载完成后更新容器的高度。这种方式只有在添加了onload事件的资源加载完成后才会更新高度,如果有些异步资源没有绑定事件或者通过js改变了元素高度,最后获取的高度可能不准确。
使用setInterval定时获取容器高度。这种方式和上一种比较的话,实现方式简单,但是setInterval会占用内存,有一定的性能问题,而且在容器高度固定之后还会一直被执行,也不是理想的实现方式。
监听容器高度的动态变化。
这篇文章要讲的是第3种方式。
resize提到高度变化,我们第一个想到的应该是resize事件,在window对象上添加resize事件,可以监听浏 ...
react源码之调度开始
3.调度开始上一节讲到,react根据更新任务的优先级lanePriority来执行不同的调度任务.
lanePriority=SyncLanePriority,执行同步调度,scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root))
lanePriority!=SyncLanePriority&&!=SyncBatchedLanePriority,执行异步调度,scheduleCallback(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root))
同步调度:
123456789101112131415function scheduleSyncCallback(callback) { // Push this callback into an internal queue. We'll flush these either in // the next tick, or earlier if so ...
react源码之调度入口
2. 调度入口
获取rootFiber;更新fiber的lanes;从当前fiber往上遍历至fiberRoot,更新父fiber的childLanes
更新rootFiber的pendingLanes和eventTimes
若是同步非批量更新,调用performSyncWorkOnRoot(root);同步非批量更新和异步更新,调用ensureRootIsScheduled(root, eventTime)
1234567891011121314151617181920212223242526272829303132333435363738function scheduleUpdateOnFiber(fiber, lane, eventTime) { // 得到fiberRoot节点 // 更新fiber的lanes;从当前fiber往上遍历至fiberRoot,更新父fiber的childLanes var root = markUpdateLaneFromFiberToRoot(fiber, lane); // 更新rootFiber的pendingLanes ...
微前端实践一
微前端起源微前端的概念最早由 thoughtworks 在 2016 年提出。其核心思路是借鉴后端微服务架构理念,将一个单体的庞大的前端应用拆分为多个简单独立的前端工程。每个前端工程可以独立开发、测试、部署。最终再由一个容器应用,将拆分后的微前端工程组合为一个整体,面向用户提供服务
微前端的价值
技术栈无关主框架不限制接入应用的技术栈,子应用具备完全自主权
独立开发、独立部署子应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
独立运行时每个子应用之间状态隔离,运行时状态不共享
微前端架构旨在解决单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后,随之而来的应用不可维护的问题。这类问题在企业级 Web 应用中尤其常见。
解决方案:MPA: 多页面应用(Multi page web application)SPA: 单页面应用(Single page web appliction)
MPA:
优点: 部署简单、各应用之间硬隔离,天生具备技术栈无关、独立开发、独立部署的特性。
缺点 ...
为什么选择使用TS
为什么选择使用TS一个非常有争议性的观点:由于 TypeScript 具有更强的可扩展性 并且 可以带给开发者更好的体验,开发者应该更愿意选择 TypeScript 而不是 JavaScript。
开发者回避使用 TypeScript 的三个借口
它让 JavaScript 更像 Java 和 .NET
优秀的 JavaScript 开发者会提醒你避免使用 OOP 的风格。太多开发者一上来就写个class的原因通常是因为 他/她 是从OOP背景过来的 —— 在Java,你不能光秃秃地定义一个常量,一个函数或者一个表达式,你得先有个类,然后在类里定义一个静态不可变的属性 (public static final 三连) 才能产生一个常量,类似的,也只能在类里定义一个(静态或者非静态)的方法才能让函数有容身之地在大部分场景下不鼓励使用JavaScript class
问题的关键是:TypeScript 不会改变 JavaScript,它只是被加到 JavaScript 中。
它使代码变得不必要的冗长/复杂
TypeScript 意味着更多的代码,但这些东西是元数据ーー它有助于描 ...
react源码之react入口函数
react源码版本是17.0.2
1. react 入口react入口函数有三种模式:
legacy(传统)模式: ReactDOM.render(, rootNode);LegacyRoot = 0。
这是当前 React app 使用的方式。构建dom的过程是同步的,所以在render阶段,如果diff特别耗时,会导致js一直阻塞高优先级的任务(例如用户的点击事件),表现为页面的卡顿,无法响应。
blocking(阻塞)模式: ReactDOM.createBlockingRoot(rootNode).render();BlockingRoot = 1。目前正在实验中。作为迁移到 concurrent 模式的第一个步骤。
最新的react文档指出,下面所有关于 “blocking 模式” 和 createBlockingRoot 的说法都已过时,应忽略。
concurrent(并发)模式: ReactDOM.createRoot(rootNode).render();ConcurrentRoot = 2。
目前在实验中,未来稳定之后,打算作为 React 的默认开发模式。 ...
react源码之前置知识
react源码版本是17.0.2
0. react前置知识react的基本理念是实现快速响应,实现上,是将同步的更新变为异步可中断、带优先级的更新。
0.1 源码架构react17源码可以分为以下模块:
Scheduler(调度器): 排序优先级,让优先级高的任务先进行Reconciler
Reconciler(协调器): 找出哪些节点发生了改变,并打上不同的Tag,发生在render(更新渲染)阶段
Renderer(渲染器): 将Reconciler中打好标签的节点渲染到视图上,发生在commit(提交)阶段
Scheduler(调度器)js是单线程,浏览器在同一时间内只能执行一个事件。若js代码执行时间过长,可能会导致以下两种情况:1)阻塞用户交互事件(比如点击事件);2)阻塞浏览器绘制和渲染dom,造成卡帧、丢帧的现象。
GUI渲染线程与JS引擎是互斥的,当JS引擎执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行
Scheduler存在的主要作用就是为了解决上述问题:
调度优先级,高优先级的任务可以打断低优先级的任务;
时间切片, ...
从输入一个URL谈前端优化
从输入一个URL谈前端优化DNS查询
与服务器交互首先要进行DNS查询,得到服务器的IP地址,浏览器会首先查询自己的缓存,之后会查询本地HOSTS,如果仍然没找到会发起向DNS服务器查询的请求。
在这里我们可以做的优化不多,DNS是我们相对不可控的一个条件,但我们仍然可以做的一个优化策略是预查询。
进行DNS预查询
在文档顶部我们可以将我们即将要请求的地址的DNS预先查询,通过插入一个link标签
1<link rel="dns-prefetch" href="https://xxx.com/">
来告知浏览器我们将要从这个地址(通常会是存放静态资源的CDN的地址)拉取数据。
建立HTTP(TCP)连接
得到服务器IP之后,首先进行三次握手,之后会进行SSL握手(HTTPS),SSL握手时会向服务器端确认HTTP的版本。
针对这方面的优化,前端可做的事情不多,主要是服务器端的事情,不过仍然要了解一下前端可以看得到的策略。
keep-alive
由于TCP的可靠性,每条独立 ...
H5 项目如何适配暗黑模式
H5 项目如何适配暗黑模式背景
随着 iOS 13 的发布,深色模式(Dark Mode)越来越多地出现在大众的视野中,支持深色模式已经成为现代移动应用和网站的一个潮流。
优势
可大幅减少耗电量(具体取决于设备的屏幕技术)。
为弱视以及对强光敏感的用户提高可视性。
让所有人都可以在光线较暗的环境中更轻松地使用设备。
系统兼容情况
macOS 10.14 引入了 darkmode
ios13 2019 年 3 月发布的 ios13 版本加入了 darkmode
Android 10 (API 级别 29) 及更高版本中提供深色主题背景
window10 2018.10.10
如何切换深色模式
iOS:“设置”–“显示与亮度”–“外观”,选择“深色”
Android:“系统设置”–“显示”–“深色模式”。
问题
如果系统设置了深色模式,H5页面不做相应的处理,会出现背景色冲突、深色文字显示异常,深色图标显示异常等一些显示上的问题。
所以,需要对深色模式进行一些适配。
原理
将同一个资源,创建出两种模式的样式。系统根据当前选择的样式,自动获取该样式的资源
每次系统更新 ...