JavaScript 拖拽与观察者模式的实现及应用

前言

本文将通过几个具体的代码片段,深入探讨 JavaScript 中的拖拽功能和观察者模式(发布-订阅模式)的实现及其应用场景。

这些代码片段不仅展示了如何实现这些功能,还解释了其背后的原理和实际用途。通过阅读本文,读者可以更好地理解 JavaScript 的高级特性,并将其应用到实际项目中。


1. 拖拽功能的实现

在这里插入图片描述

代码片段

```html



    
    
    
    Document
    


    
father
son
```

代码解析

拖拽类 Drag
```javascript
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
```javascript
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 类实现了基本的拖拽功能,包括:

  1. 获取拖拽对象 :通过选择器获取要拖拽的 DOM 元素。
  2. 添加鼠标按下事件 :当用户按下鼠标时,记录鼠标相对于元素的位置 (dis_x, dis_y)。
  3. 添加鼠标移动事件 :根据鼠标的当前位置更新元素的位置。
  4. 添加鼠标抬起事件 :当用户释放鼠标时,移除鼠标移动事件,防止后续不必要的移动。
  5. 取消默认行为 :阻止浏览器的默认拖拽行为。

Subdrag 类继承自 Drag 类,并在其基础上增加了边界限制,确保拖拽的元素不会超出视口范围。这使得拖拽体验更加友好和实用。


2. 观察者模式(发布-订阅模式)

代码片段 1:药店示例

```html



    
    
    
    Document


    



```

在这里插入图片描述

代码解析

观察者模式 (发布-订阅模式)是一种设计模式,用于定义对象间的一种一对多依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会收到通知并自动更新。在上述代码中,drugstore 作为发布者,维护了一个名为 obj 的花名册,记录了不同事件的订阅者列表。

具体实现如下:

  1. 订阅方法listen:接收事件名称 eventName 和回调函数 fn,将回调函数添加到对应事件的订阅者列表中。
  2. 发布方法publish:接收事件名称 eventName 和数据 data,遍历对应的订阅者列表,依次调用每个回调函数并传递数据。

通过这种方式,多个订阅者可以根据不同的条件对同一事件做出响应。例如,在上述代码中,四个不同的订阅者(小周、小易、小王、老王)根据药店发布的口罩信息做出了不同的反应。

代码片段 2:售楼处示例

```html



    
    
    
    Document


    



```

在这里插入图片描述

代码解析

在售楼处示例中,salesOffice 作为发布者,同样使用了花名册 arr 来记录订阅者的回调函数。不同的是,这里的订阅者只关心新楼盘推出的消息,而不需要区分不同的事件类型。

具体实现如下:

  1. 订阅方法listen:接收回调函数 fn 并将其添加到花名册中。
  2. 发布方法publish:接收数据 data,遍历花名册中的所有回调函数并依次调用。

通过这种方式,多个订阅者可以根据新楼盘的信息做出不同的反应。例如,在上述代码中,三个不同的订阅者(小明、小龙、小强)根据售楼处发布的房屋信息做出了不同的决策。


结尾

通过以上两个主要部分的详细探讨,我们深入分析了 JavaScript 中的拖拽功能和观察者模式的实现及其应用场景。拖拽功能使得用户能够直观地操作页面元素,而观察者模式则提供了一种优雅的方式来处理对象间的依赖关系,避免了紧耦合的问题。

在实际项目中,合理运用这些技术和模式可以显著提高用户体验和代码的可维护性。希望本文的内容对读者有所帮助,欢迎继续探索 JavaScript 的更多可能性。无论是构建复杂的用户界面还是实现高效的数据通信,掌握这些高级编程技巧都将为开发者带来更多的便利和灵活性。


文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/6837.html

(0)
LomuLomu
上一篇 2025 年 1 月 19 日
下一篇 2025 年 1 月 21 日

相关推荐

  • python SQLAlchemy ORM——从零开始学习 01 安装库

    01基础库 1-1安装 依赖库:sqlalchemy “`python pip install sqlalchemy #直接安装即可 “` 1-2导入使用 这里讲解思路【个人的理解】,具体写其实就是这个框架: 导入必要的接口【有创建engine以及declarative_base】 通过create_engine接口创建engine,根据翻译可以翻译成引…

    2025 年 1 月 13 日
    38800
  • PostgreSQL 的历史

    title: PostgreSQL 的历史date: 2024/12/23updated: 2024/12/23author: cmdragon excerpt:PostgreSQL 是一款功能强大且广泛使用的开源关系型数据库管理系统。其历史可以追溯到1986年,当时由加州大学伯克利分校的一个研究团队开发。文章将深入探讨 PostgreSQL 的起源、发展历…

    2025 年 1 月 1 日
    41800
  • 2025新春源码免费送

    我们常常在日常生活中感到时间过得异常缓慢,仿佛未来遥不可及。然而,当我们回过头去审视过去,才发现时间早已悄然溜走,许多曾经等待的日子已经过去。时间总是在不经意间流逝,让人意识到它的宝贵和不可逆转。 尽管如此,我们依然应对未来保持从容的态度。生活充满了无数的可能性,未来依然充满了希望与机会。无论眼前的路看似如何曲折,抑或我们面临的挑战有多大,始终相信自己能够把…

    2025 年 1 月 10 日
    34900
  • Python深度学习(第2版)PDF免费下载

    适读人群 :想要学习深度学习的学生、职业开发者。 流行深度学习框架Keras之父执笔,涵盖Transformer架构等进展,文字生,简单方式解释复杂概念,不用一个数学公式,利用直觉自然入门深度学习。 电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版书籍 点击原文去下载 书籍信息 作者: [美] 弗朗索瓦·肖莱出版社: 人民邮电出版社出品方…

    2024 年 12 月 31 日
    25000
  • 全网最适合入门的面向对象编程教程:60 Python面向对象综合实例-传感器数据实时绘图器

    全网最适合入门的面向对象编程教程:60 Python 面向对象综合实例-传感器数据实时绘图器 摘要: 本文将结合之前内容实现模拟一个传感器系统软件,包括三个线程:传感器线程生成数据并通过串口发送给主机进程;主机进程通过串口接收指令,进行数据滤波和处理后,将处理结果发送给绘图线程;绘图线程负责接收数据并绘制更新数据曲线。 原文链接: FreakStudio的博…

    2024 年 12 月 24 日
    26700

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信