时间:2023-09-04 02:54:01 | 来源:网站运营
时间:2023-09-04 02:54:01 来源:网站运营
web前端之设计模式(二):<!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> <script> // 观察者模式又叫发布订阅者模式,消息系统,消息机制,自定义事件 var Observer = (function() { // 消息队列 var _msg = {}; // 暴露接口 return { /*** * 订阅消息 * @type 消息名称 * fn 回调函数 * 将消息回调函数,存储在消息队列中 **/ on: function(type, fn) { // 判断这种类型的消息是否存在 if (_msg[type]) { // 继续存储 _msg[type].push(fn) } else { // 初始化一个消息管道 _msg[type] = [fn] } // console.log(_msg); }, /*** * 发布消息 * @type 消息类型 * 从第二个参数开始,表示执行消息回调函数的时候,传递的参数 * 遍历该类型的消息回调函数,并逐一执行 **/ trigger: function(type) { // 该类型的消息是否存在 if (_msg[type]) { // 获取传递的参数 var args = Array.prototype.slice.call(arguments, 1); // console.log(args); // 遍历消息管道,逐一执行每一个方法 for(var i = 0; i < _msg[type].length; i++) { // 执行每一个函数, // args是一个数组,要逐一传递,因此要借助apply _msg[type][i].apply(null, args) // _msg[type][i](args) } } }, /*** * 注销消息 * @type 消息名称 * fn 回调函数 注意:匿名函数无法注销 * 从消息队列中,移除该回调函数 **/ off: function(type, fn) { // 没有传递参数,情况消息队列 // 传递了type,情况该类型的消息管道 // 传递了type和fn,从该类型的消息管道中,找到fn,并将其移除 // 没有传递参数,情况消息队列 if (type === undefined) { _msg = {}; return; } // 是否有fn if (fn) { // 传递了type和fn,从该类型的消息管道中,找到fn,并将其移除 for (var i = _msg[type].length - 1; i >= 0; i--) { // 寻找fn if (_msg[type][i] === fn) { // 移除fn, 从后向前遍历时候,从数组中删除成员不会影响遍历 _msg[type].splice(i, 1) // 删除了,不需要继续遍历了。 return; } } } else { // 传递了type,情况该类型的消息管道 _msg[type] = []; } }, /*** * 单次订阅的 * @type 消息名称 * fn 回调函数 * 注册后将其移除 **/ once: function(type, fn) { // this.on(type, fn) // this.off(type, fn) // 缓存this var me = this; // 包装函数 function callback() { // 注销回调函数, 防止无限循环。 me.off(type, callback) // 执行回调函数,并传递参数 // apply第二个参数可以是数组,也可以是类数组对象。 fn.apply(null, arguments); // console.log('执行了') } // 订阅 this.on(type, callback) } } })() // 观察者模式问题:一定是先订阅,再发布。 Observer.trigger('test', 100, 200) // 单次订阅 Observer.once('test', function() { console.log('run test', arguments); Observer.trigger('test', 'hello', 'ickt') }) // Observer.trigger('test', 100, 200) // Observer.trigger('test', true, false) // Observer.trigger('test', 'hello', 'ickt') // function demo() { // // console.log('helle ickt', this) // console.log('helle ickt') // } // // 订阅消息 // Observer.on('ickt', function(num1, num2, bool, msg) { // // console.log(arguments) // console.log(num1, num2, bool, msg); // }) // Observer.on('ickt', demo) // Observer.on('demo', function() { // console.log(arguments) // }) // // 清空 // // Observer.off(); // // Observer.off('ickt'); // // 没办法注销匿名函数 // // Observer.off('ickt', function() { // // // console.log('helle ickt', this) // // console.log('helle ickt') // // }); // // Observer.off('ickt', demo) // // 发布消息 // Observer.trigger('ickt', 100, 200, true, 'hello') // Observer.trigger('ickt', 100, 200, true, 'hello') // Observer.trigger('test', 100, 200) // Observer.trigger('demo', 100, 200) </script></body></html>
<!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> a:hover { color: #f90; } a { margin-right: 20px; } </style></head><body> <script src="./ickt.js"></script> <script> // 定义基类,让所有类继承 function Base() { // 当前元素 this.element = null; // 存储子类 this.children = []; } // 定义这些行文方法 Base.prototype.init = function() { // 基类不能初始化 throw new Error('基类不能初始化') } // 获取当前实例对应的元素 Base.prototype.getElement = function() { return this.element; } // 添加子元素 Base.prototype.add = function(child) { // 存储子对象 this.children.push(child); // 处理dom this.element.appendChild(child.getElement()); // 链式调用 return this; } // 容器类 function Container(id, parent) { // 构造函数式继承 Base.call(this); // 存储数据 this.id = id; this.parent = parent; // 初始化 this.init(); } // 可以使用类式继承,也可以使用寄生式继承 // Container.prototype = new Base(); _.inherit(Container, Base); // 重写方法 // 初始化方法 Container.prototype.init = function() { // 创建元素 this.element = document.createElement('ul'); // 添加id this.element.id = this.id; // 添加类 this.element.className = 'container' } // 显示容器 Container.prototype.show = function() { // 让容器元素上树 this.parent.appendChild(this.element); } // 每一行的类 function Item(className) { // 构造函数继承 Base.call(this); // 存储数据 this.className = className || 'item'; // 初始化 this.init(); } // 继承 _.inherit(Item, Base); // 重写方法 Item.prototype.init = function() { // 创建元素 this.element = document.createElement('li'); // 设置属性 this.element.className = this.className; } // 没有分类的新闻 function TitleNews(text, href) { // 构造函数继承 Base.call(this); // 存储数据 this.text = text; this.href = href; // 初始化 this.init(); } // 继承 _.inherit(TitleNews, Base) // 重写方法 // 初始化方法 TitleNews.prototype.init = function() { // 定义元素 this.element = document.createElement('a'); // 设置属性 this.element.href = this.href; // 设置内容 this.element.innerHTML = this.text; } // 分类新闻 function TypeNews(text, href, type) { // 构造函数继承 Base.call(this); // 存储数据 this.text = text; this.href = href; this.type = type; // 初始化 this.init(); } // 继承 _.inherit(TypeNews, Base) // 重写方法 // 初始化方法 TypeNews.prototype.init = function() { // 创建元素 this.element = document.createElement('a'); var span = document.createElement('span'); var text = document.createTextNode(this.text); // 设置内容 span.innerHTML = this.type + ' | '; // 设置属性 this.element.href = this.href; // 组装 this.element.appendChild(span) this.element.appendChild(text) } // 使用类 new Container('sport', document.body) .add( new Item() .add( new TitleNews('国安官宣与池忠国完成续约', 'www.baidu.com') ) .add( new TitleNews('足协明确外援出场规则', 'www.baidu.com') ) ) .add( new Item() .add( new TitleNews('180万!詹皇球星卡拍卖创纪录', 'www.baidu.com') ) ) .add( new Item() .add( new TypeNews('沈梦辰时髦穿搭 赵丽颖夏日针织', '#demo', '时尚') ) ) .add( new Item() .add( new TypeNews('影院归来票房超350万:赔本攒人气 但总要开始', '#demo', '科技') ) ) // 上树 .show(); // 构造一个新模块 new Container('car', document.body) .add( new Item() .add( new TitleNews('小鹏汽车完成C+轮近5亿美元融资', '#demo') ) ) .add( new Item() .add( new TypeNews('理想汽车计划7月31日在纳斯达克挂牌上市', '#demo', '汽车') ) ) .show(); </script></body></html>
<!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> <input type="text"> <script> // 封装校验算法 var strage = (function() { // 校验算法 var methods = { // 校验数字 number: function(value) { // 判断数组 if (!/^/d+$/.test(value)) { // 不是数字 return '不是数字' } }, // 校验内容 en: function(value) { // 判断数组 if (!/^[a-zA-Z]+$/.test(value)) { // 不是数字 return '不都是英文' } } } // 接口方法 return { // 校验方法 use: function(type, value) { // 找到校验策略,校验数据 return methods[type] && methods[type](value) }, // 添加策略 add: function(type, fn) { // 存储校验策略 methods[type] = fn; } } })() // 输入框输入完成 var inp = document.getElementsByTagName('input')[0]; // 失去焦点 inp.onblur = function(e) { // 校验 // var result = strage.use('number', e.target.value) // var result = strage.use('en', e.target.value) // 添加校验方法 strage.add('nickname', function(value) { // 校验 if (!/^/w{2,8}$/.test(value)) { // 提示错误 return '用户名是2到8为的字母数字下划线'; } }) var result = strage.use('nickname', e.target.value) console.log(result); } </script></body></html>
<!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 style="text-align: center;"> <canvas width="1000" height="600" style="border: 1px solid pink"></canvas> <script> // // 获取canvas // var canvas = document.getElementsByTagName('canvas')[0]; // // 设置样式 // canvas.style.border = '1px solid pink'; // // 绘制圆 // var ctx = canvas.getContext('2d'); // // 绘制元素 // ctx.beginPath(); // // 绘制圆 // ctx.arc(200, 200, 100, 0, Math.PI * 2); // ctx.closePath(); // // 设置颜色 // ctx.strokeStyle = 'green'; // ctx.stroke(); // 分装一个指令对象 var Command = (function() { // 获取canvas var canvas = document.getElementsByTagName('canvas')[0]; // 绘制圆 var ctx = canvas.getContext('2d'); // 封装指令 var _C = { // 描边圆 strokeCircle: function(x, y, r, color) { ctx.beginPath(); ctx.arc(x, y, r, 0, 2 * Math.PI); ctx.closePath(); // 设置颜色并描边 ctx.strokeStyle = color; ctx.stroke(); }, // 填充元素 fillCircle: function(x, y, r, color) { ctx.beginPath(); ctx.arc(x, y, r, 0, 2 * Math.PI); ctx.closePath(); // 设置颜色并描边 ctx.fillStyle = color; ctx.fill(); }, // 绘制矩形 fillCenterRect: function(x, y, width, height, color) { // 传递了颜色,设置颜色 if (color) { ctx.fillStyle = color; } // 绘制 ctx.fillRect(x - width / 2, y - height / 2, width, height) } } // 暴露接口 return { // 执行方法 exec: function(type) { // 获取第二个参数开始,传递的参数 var args = Array.prototype.slice.call(arguments, 1); // 执行指令 _C[type] && _C[type].apply(null, args); // 链式调用 return this; } } })() // 绘制圆 Command.exec('fillCircle', 100, 100, 50, 'green') Command.exec('strokeCircle', 300, 300, 50, 'pink') // 还可以链式调用 .exec('fillCircle', 300, 100, 50, 'green') .exec('fillCenterRect', 400, 200, 100, 100, 'orange') </script></body></html>
关键词:模式,设计