当前位置: 首页 > news >正文

有关网站设计与制作的论文乌市网站建设为

有关网站设计与制作的论文,乌市网站建设为,经营网站的备案,wordpress 主机伪静态404.php seo一、引入 在前端性能优化中#xff0c;关于图片/视频等内容的懒加载一直都是优化利器。当用户看到对应的视图模块时#xff0c;才去请求加载对应的图像。 原理也很简单#xff0c;通过浏览器提供的 IntersectionObserver - Web API 接口参考 | MDN (mozilla.org)#xff0c…一、引入 在前端性能优化中关于图片/视频等内容的懒加载一直都是优化利器。当用户看到对应的视图模块时才去请求加载对应的图像。 原理也很简单通过浏览器提供的 IntersectionObserver - Web API 接口参考 | MDN (mozilla.org)观察“哪个元素和视口交叉”从而进行懒加载。 这个API具有很好的性能因为它的监听是异步的不会影响JS的主线程所以比传统的“监听页面滚动”更佳。关于API的使用这里就不做过多说明了主要操作如下 const DOM document.querySelector(img) const io new IntersectionObserver((entries) {entries.forEach((k) {//回调函数可以利用 k.target 是否和我们要监听的DOM元素相等来判断当前是否是我们要监听的目标元素if(k.target DOM){ /* 做懒加载的操作 */}}); }, {/*一些配置详见MDN文档*/}); io.observe(DOM) //添加监听 二、可优化的点 值得注意的是一个observer实例可以监听多个DOM元素。如果我们需要封装一个图片组件并实现它的懒加载那么“每个组件都创建一个IntersectionObserver实例” 显然是不划算的如果页面上有上百个图片就会创建出上百个实例。 针对这种情况并且不想破坏组件的封装性于是考虑把实例提升到全局封装一个hook从而每个组件都能自行添加入该实例的观察对象中。但是监听的回调函数是创建实例的时候就决定的后续添加进入的DOM元素在回调函数中无法判断“是否轮到自己”了。 三、观察者模式 有什么办法能够让DOM元素动态的进入回调函数呢 我们可以利用对象引用地址不变的特性动态的往对象里添加数据这样在回调函数触发时就能够取出正确的数据了 这里我的灵感其实来源于Vue3的响应式原理 收集依赖 -- 监听 -- 触发依赖。Vue3是多对多的发布-订阅模式 这里是 一对多的观察者模式 /**回调函数的类型*/ type ObserverCallback (entryData: IntersectionObserverEntry) void /** 键是DOM元素值是该元素的回调函数Set 考虑到可能一个元素会有多个回调 */ const watchMap new WeakMapElement, SetObserverCallback() const io new IntersectionObserver((entries) {entries.forEach((k) {const set watchMap.get(k.target)if(set){set.forEach((fn) fn(k)) //从weakMap中取出对应的监听事件触发} }); }, {/*一些配置详见MDN文档*/}); 剩下要做的就是“依赖收集”了。基于面向对象的思想 可以创建多个实例多处复用互不干扰。 当有DOM元素需要被监听时添加进weakMap中需要取消监听时移除 observer触发回调时取出对应的元素的依赖执行回调函数。 手写过观察者模式或者发布订阅模式的小伙伴应该对下面的代码构造很熟悉。 /**视口监听器 - 观察者模式 */ export class ViewportObserverWatcher {/**IntersectionObserver 实例 */io: IntersectionObserver/**当前正在监听的元素的weakMap */watchMap new WeakMapElement, SetObserverCallback()constructor(options?: IntersectionObserverInit) {this.io new IntersectionObserver((entries) {entries.forEach((k) {this.watchMap.get(k.target)?.forEach((fn) fn(k)) //从weakMap中取出对应的监听事件触发});}, options);}/**添加对元素的一个监听回调可以选择触发条件* param target 目标元素* param callback 回调函数* param condition 触发回调条件 true | false | undefined 分别对应 与视口边界交叉 | 不与视口交叉 | 都*/addWatch (target: Element, callback: ObserverCallback, condition?: boolean) {const _callback: ObserverCallback (k) {if (condition undefined) { }//无论如何都触发 else if ((condition ! k.isIntersecting)) return //当触发条件和实际情况不相同时不触发 callback(k)}if (this.watchMap.has(target)) {this.watchMap.get(target)!.add(_callback)} else {this.io.observe(target)this.watchMap.set(target, new Set([_callback]))}}/**取消对元素的某个回调 */removeWatch (target: Element, callback: ObserverCallback) {const set this.watchMap.get(target)if (set) {set.delete(callback)if (set.size 0) {this.watchMap.delete(target)this.io.unobserve(target)}}}/**取消对该元素的全部回调 */cancelWatch (target: Element) {this.watchMap.delete(target)this.io.unobserve(target)} } 四、写个Hook吧 1. 元素创建时加入io的监听 2. 触发懒加载之后取消对该元素的监听。 3. 依赖项变化后重复前面的逻辑。 4. 只要是元素都能进行监听不只是图片/视频。有需要使用到该功能的元素都能使用。 import { DependencyList, RefObject, useEffect, useRef } from react;/**视口监听器 - 单例模式 */ const viewportObserver new ViewportObserverWatcher() //注如果你是NextJs, 在NextJS build的时候不能直接实例化IntersectionObserver否则会报错 因为在走服务端代码 可以先设置为null后续给这个变量赋值/**懒加载Hook。懒加载触发后将会取消监听* param watchRef 要监听的DOM元素* param onEntering 元素进入视口的回调函数* param onDestroy useEffect的return中要做的事* param deps useEffect的依赖数组 当什么变化时需要重新开始懒加载流程*/ const useLazyLoad (watchRef: RefObjectHTMLElement, onEntering: ObserverCallback, onDestroy?: () void, deps: DependencyList []) {/**是否完成懒加载 */const isLazySuccess useRef(false);useEffect(() {if (!watchRef.current) return; const callback: ObserverCallback (k) {//因为只要和视口在交叉就会不断触发这个函数故需要使用一个标识符来限制 if (isLazySuccess.current false) {onEntering(k)isLazySuccess.current true;viewportObserver!.removeWatch(watchRef.current!, callback) //加载完成就取消监听onEntering(k)}}viewportObserver.addWatch(watchRef.current, callback, true)return () {if (watchRef.current viewportObserver) viewportObserver.removeWatch(watchRef.current, callback); //卸载时也要取消监听 isLazySuccess.current false;onDestroy onDestroy()};}, deps) } 使用方法 核心思想到了视口才赋值真实路径其它时候使用占位符。 /**视频组件 */ export default function Video({ src, className, otherProps }: VideoProps) {const outRef useRefHTMLDivElement(null); //被监听的元素const [realSrc, setRealSrc] useStatestring(); //存放展示的src如果还没到视口就不展示useLazyLoad(outRef, () setRealSrc(src));return (div className{cn(className, rounded)} ref{outRef}{/* 其它逻辑.... */}{/* 正常展示视频 */}{realSrc video src{realSrc} {...otherProps} /}{/* 其它逻辑.... */}/div); } 五、使用效果 结合前面文章写的的瀑布流组件实现以下效果 图片链接来源于 岁月小筑随机图片API接口-随机背景图片-随机图片API (xjh.me)
http://www.hkea.cn/news/14586482/

相关文章:

  • 三亚房产网站建设运维是做什么的
  • 装修招投标网站建设企石镇网站建设
  • 红色博客网站源码wordpress门户网站
  • 南宁网站建设搭建网站静态页面模板
  • 山西国人伟业网站app引导页模板html
  • 青岛市黄岛区网站建设设计师 必备的网站
  • 成都设计网站建设网店代运营费用多少钱
  • 网站备案信息是什么外贸论坛有哪些?
  • 深圳网站改版公司wordpress 4.01
  • 传媒在线网站模板shopex进入网站自动回跳转到别的网站 是否被挂马
  • 服饰网站建设目的在线代理网页版proxy
  • 电子商务网站建设的工具东莞网站建设乐云seo在线制作
  • dede旅游网站源码帮客户做ppt什么的在哪个网站
  • 个人网站怎样申请简约门户网站源码
  • 小企业网站建设有多少北京最好的网站制作公司
  • 孝感58同城网站建设马克杯网站开发
  • 调兵山网站建个企业网站
  • 宿州移动网站建设大连网站建设资讯
  • 南宁网站建设设计深圳注册公司在什么网站
  • 保定网站seo个体户营业执照可以网站备案
  • 自己做网站需要哪些软件台州市建设工程造价管理处网站
  • 江苏扬州建设局网站网站建设管理情况报告
  • 网站类型怎么分广州一共几个区
  • 网站seo诊断报告例子微信营销和微博营销的本质区别
  • 建设银行代发工资清单网站移动端网站开发流程
  • 做毕设好的网站wix做网站步骤
  • dnf交易网站建设怎么建立自己网站 asp
  • 红河网页设计临沂网站seo
  • 哪个网站能接效果图做360做的网站首页
  • jsp做网站案例重庆网站建设选夹夹虫