JavaScript 面向对象封装拖拽功能详解

作者:青柠

时间:2026-10-29

浏览:223

本文详细讲解如何利用 JavaScript 面向对象思想封装鼠标拖拽功能。通过对比面向过程与面向对象两种写法,演示如何将全局变量转化为属性、函数挂载至原型,并重点解决 this 指针指向及 event 对象传递等核心问题,帮助开发者掌握前端交互组件的封装技巧。

文章目录

面向对象拖拽封装概述

首先介绍面向对象编程练习的基本规范与常见挑战。

实践步骤为:先编写面向过程的普通实现,随后将其重构为面向对象模式。

重构时需遵循以下原则: · 避免函数内部嵌套定义其他函数。 · 允许保留必要的全局变量。 · 将 window.onload 中非赋值的逻辑代码提取至独立函数中。

接下来演示如何将其转换为面向对象结构。

转换的核心规则包括: · 将全局变量定义为对象的属性。 · 将独立函数定义为对象的方法。 · 在 window.onload 中实例化对象。 · 修正 this 指针的指向问题。

拖拽布局与基础实现

首先完善拖拽功能所需的布局结构: HTML结构:

<div id="box"></div>

CSS样式: #box{position: absolute;width: 200px;height: 200px;background: red;}

第一步,回顾面向过程的拖拽实现逻辑。

代码如下:

window.onload = function (){
// 获取元素和初始值
var oBox = document.getElementById('box'),
disX = 0, disY = 0;
// 容器鼠标按下事件
oBox.onmousedown = function (e){
var e = e || window.event;
disX = e.clientX - this.offsetLeft;
disY = e.clientY - this.offsetTop;
document.onmousemove = function (e){
var e = e || window.event;
oBox.style.left = (e.clientX - disX) + 'px';
oBox.style.top = (e.clientY - disY) + 'px';
        };
document.onmouseup = function (){
document.onmousemove = null;
document.onmouseup = null;
        };
return false;
    };
};

面向对象重构与代码分析

第二步,将上述面向过程的代码重构为面向对象写法。

代码如下:

window.onload = function (){
var drag = new Drag('box');
drag.init();
};
// 构造函数Drag
function Drag(id){
this.obj = document.getElementById(id);
this.disX = 0;
this.disY = 0;
}
Drag.prototype.init = function (){
// this指针
var me = this;
this.obj.onmousedown = function (e){
var e = e || event;
me.mouseDown(e);
// 阻止默认事件
return false;
    };
};
Drag.prototype.mouseDown = function (e){
// this指针
var me = this;
this.disX = e.clientX - this.obj.offsetLeft;
this.disY = e.clientY - this.obj.offsetTop;
document.onmousemove = function (e){
var e = e || window.event;
me.mouseMove(e);
    };  
document.onmouseup = function (){
me.mouseUp();
    }
};
Drag.prototype.mouseMove = function (e){
this.obj.style.left = (e.clientX - this.disX) + 'px';
this.obj.style.top = (e.clientY - this.disY) + 'px';
};
Drag.prototype.mouseUp = function (){
document.onmousemove = null;
document.onmouseup = null;
};

第三步,分析重构前后代码的差异点。

首先使用构造函数来创建对象实例:

代码如下:

// 构造函数Drag
function Drag(id){
this.obj = document.getElementById(id);
this.disX = 0;
this.disY = 0;
}

遵循之前制定的规则,将所有全局变量转换为对象属性。

随后将相关函数定义在原型对象上:

代码如下:

Drag.prototype.init = function (){
};
Drag.prototype.mouseDown = function (){
};
Drag.prototype.mouseMove = function (){
};
Drag.prototype.mouseUp = function (){
};

首先分析 init 函数的实现:

代码如下:

Drag.prototype.init = function (){
// this指针
var me = this;
this.obj.onmousedown = function (e){
var e = e || event;
me.mouseDown(e);
// 阻止默认事件
return false;
    };
};

此处使用 me 变量缓存了 this 指针,旨在防止后续嵌套函数中 this 指向发生错误。

接着分析 mouseDown 函数:

代码如下:

Drag.prototype.mouseDown = function (e){
// this指针
var me = this;
this.disX = e.clientX - this.obj.offsetLeft;
this.disY = e.clientY - this.obj.offsetTop;
document.onmousemove = function (e){
var e = e || window.event;
me.mouseMove(e);
    };  
document.onmouseup = function (){
me.mouseUp();
    }
};

在重构为面向对象时,需特别注意 event 对象。由于 event 仅存在于事件触发上下文中,因此必须将其保存为变量并通过参数传递。

后续的 mouseMove 和 mouseUp 函数实现逻辑较为直观,无需特殊处理。

关键问题与注意事项

注意事项

关于 this 指针的问题,在面向对象编程中 this 至关重要。 this拓展阅读: http://div.io/topic/809

关于 event 对象的问题,由于 event 对象仅在事件处理函数内有效,因此在编写方法时需格外注意其作用域和传递方式。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章