JavaScript 面向对象封装拖拽功能详解
本文详细讲解如何利用 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 对象仅在事件处理函数内有效,因此在编写方法时需格外注意其作用域和传递方式。
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
