15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > web前端设计模式 (三)

web前端设计模式 (三)

时间:2023-09-04 08:42:02 | 来源:网站运营

时间:2023-09-04 08:42:02 来源:网站运营

web前端设计模式 (三):

一、设计模式

1.1 迭代器模式

定义:在不暴露对象内部结构的同时,可以顺序的访问聚合对象内部的元素。

行为型设计模式

特点;

可以顺序的访问聚合对象中的每个元素,

简化循环语句,结构清晰

迭代器并没有移出循环语句,而是移动到迭代器中。

迭代器在处理一个对象时,我们只需要提供处理方法,并不关系对象内部结构。

解决了使用者与对象内部结构解析之间的耦合

为我们提供统一的操作对象接口

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li>7</li> <li>8</li> <li>9</li> <li>10</li> </ul> <script> // ES6中提供了迭代器接口 // 我们实现一个类似jQuery的迭代器 function Iterator(selector) { // 存储选择器 this.selector = selector; // 获取元素 this.elements = document.querySelectorAll(selector); // 维护一个索引自豪 this.index = 0; } // 提供一些方法 Iterator.prototype = { // 重写构造函数 constructor: Iterator, // 获取当前元素 getCurrent: function() { return this.elements[this.index] }, // 获取第一个 first: function() { // 更改index指向 this.index = 0; // 返回元素 return this.getCurrent(); }, // 前一个 prev: function() { this.index--; // 判断边界 if (this.index < 0) { this.index = 0; throw new Error('已经是第一个了') } return this.getCurrent(); }, // 后一个 next: function() { this.index++; // 判断边界 if (this.index >= this.elements.length) { this.index = this.elements.length - 1; throw new Error('已经是最后一个了'); } return this.getCurrent(); }, // 获取最后一个 last: function() { // 更改index指向 this.index = this.elements.length - 1;; // 返回元素 return this.getCurrent();; }, // 获取第几个 eq: function(index) { this.index = index; return this.getCurrent(); } } // 获取li var lis = new Iterator('li'); console.log(lis.first()) console.log(lis.last()) console.log(lis.prev()) console.log(lis.prev()) console.log(lis.next()) console.log(lis.eq(3)) </script></body></html>


1.2 委托模式

多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求。

解决请求与委托者之间的耦合

被委托者接收到请求分发给委托者去处理

应用:

请求委托:

浏览器同时并发处理请求的个数是有限的,因此对于一个页面来说,如果请求过多的话,会导致后面的请求被延迟(堵塞),我们为了加快这些请求发出,

我们将这些请求合并成一个,这样当请求结束后,我们在分发这些请求的数据

事件委托

1.3 事件委托

对于每一个元素我们都要绑定一个事件,这样对于资源开销很大(如果有1w个元素,要绑定1w个事件)

对于每一个类元素都要for循环遍历一次,开发成本很高。所以我们可以通过事件委托来解决上面的问题

事件委托:将所有元素的事件绑定委托给同一个父元素,根据事件冒泡捕获机制,可以在父元素绑定事件中获取的触发事件的这个元素,根据这个元素具有的某类

特征(例如元素名称,元素id,元素类,元素属性等等)做不同的处理,实现事件从父元素到被委托的元素传递。其特点:

减少事件数量

预言未来元素

新增的元素也可以绑定事件

避免内存外泄:

通常创建一个对象需要占用一些内存,这类占用是有意义的;有时候一些垃圾(已经被删除数据)还占用着内存,这部分内存对我们来说是没用的,就是

外泄内存

jQuery中的事件委托

delegate:

第一个参数是被委托的元素(子元素)

第二个参数是事件类型

(这里还可以传递自定数据)

第三个参数是事件回调函数

本质上是调用的on方法,只不过他的委托语义化更强

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div id="box"> <button id="btn">按钮</button> </div> <script> // 在低版本IE浏览器下会产生内存外协的问题 // 高版本浏览器垃圾回收机制是计数的 // 低版本IE浏览器垃圾回收机制是引用的(指向的) // js中指向了元素,元素指向了js,此时将元素删除,由于还与js有关系,因此不能被垃圾回收机制回收 // 点击按钮,box显示 "新内容" // var btn = document.getElementById('btn'); // var box = document.getElementById('box'); // // 绑定事件 // btn.onclick = function() { // // 内存外协:box设置设置了新的内容,按钮元素被删除了,但是按钮元素还绑定了js中的click事件,因此没办法被销毁,泄露在内存中。 // // 更新box的内容 // box.innerHTML = '新内容' // } // 使用事件委托模式,避免内存外协 var box = document.getElementById('box'); // 给盒子绑定事件 box.onclick = function(e) { // 判断点击的是否是按钮 if (e.target.tagName.toUpperCase() === 'BUTTON') { // 更新盒子内容 box.innerHTML = "新内容"; } } </script></body></html>


1.4 节流器

定义:对重复的业务逻辑进行节流控制,执行最后一次操作并取消其它操作,以提高性能。

特点

延迟:通过计时器延迟程序的执行

异步:通过计时器,使程序异步执行,避免开销大的程序造成的堵塞

条件

程序可控:即是否可以继续执行

异步执行:即程序是否可以异步执行

1.5 节流与防抖

节流器:触发操作

让程序延迟执行

清除操作

清除还没有执行的操作

节流可以分成两种

按操作节流

在规定时间内,重复执行的时候,取消前一次执行,执行当前的操作。

这种节流操作有的人也叫防抖,

例如:对返回顶部的优化

按时间节流

在规定时间内,只允许执行一次。

例如:对icon浮层的优化

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> #back { position: fixed; right: 100px; bottom: 50px; width: 40px; height: 40px; padding: 15px; background-color: pink; font-size: 20px; color: green; } #qq { border: 1px solid pink; } #qq img { display: none; } </style></head><body> <div id="qq"> <span>官方QQ号</span> <img src="./qq.jpg" alt=""> </div> <h1>1-1-1</h1> <h1>2-2-2</h1> <h1>3-3-3</h1> <h1>4-4-4</h1> <h1>5-5-5</h1> <h1>6-6-6</h1> <h1>7-7-7</h1> <h1>8-8-8</h1> <h1>9-9-9</h1> <h1>10-10-10</h1> <h1>11-11-11</h1> <h1>12-12-12</h1> <h1>13-13-13</h1> <h1>14-14-14</h1> <h1>15-15-15</h1> <h1>16-16-16</h1> <h1>17-17-17</h1> <h1>18-18-18</h1> <h1>19-19-19</h1> <h1>20-20-20</h1> <div id="back">返回顶部</div> <script src="jquery.js"></script> <script> // 加载数据的方法 function getData() { // 当滚动条距离页面顶部的距离 + 视口的高度 + 300 > 页面的高度 的时候,加载数据 if (scrollY + innerHeight + 300 > document.body.clientHeight) { // 获取数据 $.get('data/all.json', function(res) { console.log(res); }) } } // 监听页面滚动 window.onscroll = function() { // 返回顶部 // getData(); throttle(getData); } // 基于时间,节流器方法 function throttle(fn, time, context, args) { // 在函数自身添加锁 if (fn.__lock) { // 被锁住了就不能执行 return; } // 添加锁 fn.__lock = true; // 执行函数 fn.apply(context, args); // 1秒之后解锁 setTimeout(function() { fn.__lock = false; }, time || 1000) } </script></body></html>


1.6 实现 jQuery

jQuery本身是一个工厂方法

jQuery中,内置了一个寄生类,寄生在原型上。

jQuery中,始终返回this即可实现链式调用

jQuery中,通过extend可以为jQuery添加静态方法以及原型方法

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <div class="app">hello</div> <div class="app">hello</div> <div class="app">hello</div> <script src="jquery.js"></script> <script> // $('.app').css('color', 'red').css({ // fontSize: '50px', // backgroundColor: 'pink' // }).attr('title', 'hello') </script> <!-- 实现jQuery --> <script> // // jQuery本身是一个工厂方法 // function jQuery(selector) { // // 返回实例 // return new init(selector) // } // // 真正的jQuery类 // function init() { // } // jQuery本身是一个工厂方法 // function jQuery(selector) { // // 返回实例 // return new init(selector) // } // // 工厂方法的原型 // jQuery.prototype = { // // 更正构造函数 // constructor: jQuery, // // 将真正的jQ类放在了工厂方法的原型对象上 // // 每次访问init都要写 jQuery.prototype.init 太麻烦了,取了一个别名: jQuery.fn 代表原型对象 // init: init // } // // 真正的jQuery类 // function init() { // } // jQuery本身是一个工厂方法 function jQuery(selector) { // 返回实例 // return new init(selector) // 重新访问init return new jQuery.fn.init(selector); } // 工厂方法的原型 // 这样访问jQuery.fn 相当于访问jQuery.prototype jQuery.fn = jQuery.prototype = { // 更正构造函数 constructor: jQuery, // 将真正的jQ类放在了工厂方法的原型对象上 // 每次访问init都要写 jQuery.prototype.init 太麻烦了,取了一个别名: jQuery.fn 代表原型对象 // init: init, version: '1.0', demo() { console.log('demo') }, // 拓展一些方法,让其更像数组 push: Array.prototype.push, splice: Array.prototype.splice } // 真正的jQuery类 jQuery.fn.init = function(selector) { // 根据选择器,将元素获取 var dom = document.querySelectorAll(selector); // 存储选择器 this.selector = selector; // 定义长度 this.length = 0; // 将获取的元素,存储再自身 for (var i = 0; i < dom.length; i++) { // 存储一个成员并更改长度 this[i] = dom[i]; this.length ++; } } // 让init类的实例,具有jQuery原型上的方法 // jQuery.fn.init.prototype = jQuery.prototype; jQuery.fn.init.prototype = jQuery.fn; // jquery又定义了拓展方法 jQuery.extend = jQuery.fn.extend = function(obj) { // 解析对象 for (var key in obj) { this[key] = obj[key]; } } // 静态属性 // jQuery.extend({ // color: 'red' // }) // 拓展原型属性 jQuery.fn.extend({ css: function(key, value) { // 如果key是字符串,直接赋值 if (typeof key === 'string') { // 给每一个元素设置样式 for (var i = 0; i < this.length; i++) { this[i].style[key] = value; } } else { // 遍历对象设置样式 for (var k in key) { this.css(k, key[k]) } } // 链式调用 return this; }, // 设置属性方法 attr: function(key, value) { // 为每一个成员设置属性 for (var i = 0; i < this.length; i++) { this[i][key] = value; } } }) // 对jQuery起别名 var $ = jQuery; // console.log(jQuery('.app')); $('.app').css('color', 'red').css({ fontSize: '50px', backgroundColor: 'pink' }).attr('title', 'hello') console.log($('.app')); </script></body></html>

关键词:模式,设计

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭