14人参与 • 2025-02-14 • Javascript
本文将通过几个具体的代码片段,深入探讨 javascript 中的拖拽功能和观察者模式(发布-订阅模式)的实现及其应用场景。
这些代码片段不仅展示了如何实现这些功能,还解释了其背后的原理和实际用途。通过阅读本文,读者可以更好地理解 javascript 的高级特性,并将其应用到实际项目中。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>document</title> <style> #father { width: 100px; height: 100px; background: red; position: absolute; } #son { width: 100px; height: 100px; background: green; position: absolute; left: 110px; } </style> </head> <body> <div id="father">father</div> <div id="son">son</div> <script src="js/drag.js"></script> <script src="js/subdrag.js"></script> <script> new drag('#father'); new subdrag('#son'); </script> </body> </html>
拖拽类 drag
class drag { constructor(selector) { // 获取拖拽的对象 this.ele = document.queryselector(selector); // 添加事件 this.ele.onmousedown = function (evt) { // this: 原来指向了 ele 对象,这里需要一个实例对象 this.fndown(evt); }.bind(this); } fndown(evt) { let e = evt || window.event; // 求鼠标的相对坐标值 this.dis_x = e.offsetx; this.dis_y = e.offsety; // 移动事件 document.onmousemove = function (evt) { // this: document this.fnmove(evt); }.bind(this); // 鼠标抬起事件 document.onmouseup = this.fnup.bind(this); // 取消默认行为 document.ondragstart = function () { return false; }; } fnmove(evt) { let e = evt || window.event; this.ele.style.left = e.pagex - this.dis_x + 'px'; this.ele.style.top = e.pagey - this.dis_y + 'px'; } fnup() { document.onmousemove = null; } }
子类 subdrag
继承自 drag
class subdrag extends drag { constructor(selector) { // 调用父类的构造函数 super(selector); } fnmove(evt) { let e = evt || window.event; let left = e.pagex - this.dis_x; let top = e.pagey - this.dis_y; // 设置边界 if (left <= 0) { left = 0; } else if (left >= document.documentelement.clientwidth - this.ele.offsetwidth) { left = document.documentelement.clientwidth - this.ele.offsetwidth; } if (top <= 0) { top = 0; } else if (top >= document.documentelement.clientheight - this.ele.offsetheight) { top = document.documentelement.clientheight - this.ele.offsetheight; } this.ele.style.left = left + 'px'; this.ele.style.top = top + 'px'; } }
拖拽功能 是一种常见的用户交互方式,允许用户通过鼠标移动元素。在上述代码中,drag
类实现了基本的拖拽功能,包括:
dis_x
, dis_y
)。subdrag
类继承自 drag
类,并在其基础上增加了边界限制,确保拖拽的元素不会超出视口范围。这使得拖拽体验更加友好和实用。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie-edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>document</title> </head> <body> <script> // 发布者 - 药店 let drugstore = { // 花名册 obj: {}, // 订阅方法 listen: function (eventname, fn) { if (!(this.obj[eventname])) { this.obj[eventname] = []; } this.obj[eventname].push(fn); }, // 发布方法 publish: function (eventname, data) { this.obj[eventname]?.map(fn => { fn(data); }); } }; let data = { type: "n95", price: 30, num: 500 }; let liaohuadata = { type: '连花', price: 200, num: 50 }; // 小周 function xiaozhou(data) { if (data.price > 20) { console.log('黑店,太贵了,我就算不出门,我也不去买!'); } } drugstore.listen('mask', xiaozhou); // 小易 function xiaoyi(data) { if (data.type === 'n95') { console.log('先少买一点,等有普通医用口罩时,再多屯点'); } } drugstore.listen('mask', xiaoyi); // 小王 function xiaowang(data) { if (data.num > 100) { console.log('多屯点,再高价卖给别人'); } } drugstore.listen('mask', xiaowang); // 老王 function laowang(data) { console.log('有佛祖保佑,不需要口罩'); } drugstore.listen('mask', laowang); drugstore.publish('mask', data); </script> </body> </html>
观察者模式(发布-订阅模式)是一种设计模式,用于定义对象间的一种一对多依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。在上述代码中,drugstore
作为发布者,维护了一个名为 obj
的花名册,记录了不同事件的订阅者列表。
具体实现如下:
listen
:接收事件名称 eventname
和回调函数 fn
,将回调函数添加到对应事件的订阅者列表中。publish
:接收事件名称 eventname
和数据 data
,遍历对应的订阅者列表,依次调用每个回调函数并传递数据。通过这种方式,多个订阅者可以根据不同的条件对同一事件做出响应。例如,在上述代码中,四个不同的订阅者(小周、小易、小王、老王)根据药店发布的口罩信息做出了不同的反应。
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie-edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>document</title> </head> <body> <script> // 发布者--售楼处 let salesoffice = { // 花名册 arr: [], // 订阅方法 listen: function (fn) { this.arr.push(fn); }, // 发布消息 publish: function (data) { // 遍历花名册 this.arr.foreach(fn => { fn(data); }); } }; // 发布的消息 let data = { size: 80, money: '10000元/平', num: '50套' }; // 小明 salesoffice.listen(function (data) { if (data.size < 100) { console.log('房子太小,不在考虑'); } }); // 小龙 salesoffice.listen(function (data) { if (parseint(data.money) < 150000) { console.log('预算充足,价格还可以,马上去订购一套'); } }); // 小强 salesoffice.listen(function (data) { if (parseint(data.num) > 30) { console.log('赶紧去,先屯20套再说'); } }); // 发布消息 salesoffice.publish(data); </script> </body> </html>
在售楼处示例中,salesoffice
作为发布者,同样使用了花名册 arr
来记录订阅者的回调函数。不同的是,这里的订阅者只关心新楼盘推出的消息,而不需要区分不同的事件类型。
具体实现如下:
listen
:接收回调函数 fn
并将其添加到花名册中。publish
:接收数据 data
,遍历花名册中的所有回调函数并依次调用。通过这种方式,多个订阅者可以根据新楼盘的信息做出不同的反应。例如,在上述代码中,三个不同的订阅者(小明、小龙、小强)根据售楼处发布的房屋信息做出了不同的决策。
通过以上两个主要部分的详细探讨,我们深入分析了 javascript 中的拖拽功能和观察者模式的实现及其应用场景。拖拽功能使得用户能够直观地操作页面元素,而观察者模式则提供了一种优雅的方式来处理对象间的依赖关系,避免了紧耦合的问题。
在实际项目中,合理运用这些技术和模式可以显著提高用户体验和代码的可维护性。希望本文的内容对读者有所帮助,欢迎继续探索 javascript 的更多可能性。无论是构建复杂的用户界面还是实现高效的数据通信,掌握这些高级编程技巧都将为开发者带来更多的便利和灵活性。
到此这篇关于javascript 拖拽与观察者模式的实现及应用的文章就介绍到这了,更多相关js 拖拽与观察者模式内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论