JavaScript面对对象构造函数实战之drag实现元素拖拽操作,事件绑定中的this指向
首先先来看一下面对过程语句中对拖拽操作的代码实现,然后再看面对对象进行对比
先来看个图解,也就是下面用到的变量解释
对应代码
<!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> *{ margin: 0; padding: 0; } #div1{ height: 200px; width: 200px; background: blueviolet; position: absolute; left: 20px; top: 100px; } </style> <script> window.onload = function(){ var oDiv = document.getElementById("div1"); //获取元素 oDiv.onmousedown = function(ev){ //在oDiv元素上设置onmousedown事件 var e = ev || window.event; //应对浏览器兼容问题 var offsetX = e.pageX - oDiv.offsetLeft; //计算X轴上的坐标,使页面上的X轴的坐标减去oDiv的left偏离,来得到鼠标在当前oDiv上的位置
注意:不是鼠标在页面上的位置,而是以oDiv的左上角为基准计算鼠标在oDiv上的X轴对应位置
var offsetY = e.pageY - oDiv.offsetTop; //计算Y轴 document.onmousemove = function(ev){ //在document上设置onmousemove事件 var e = ev || window.event; oDiv.style.left = e.pageX - offsetX + "px"; //计算oDiv这个物体应得的left定位值,鼠标在页面上的X轴位置减去鼠标在oDiv上的X轴位置就等于oDiv的left值 oDiv.style.top = e.pageY - offsetY + "px"; //由于返回number类型所以要拼接px单位 } } oDiv.onmouseup = function(){ //当鼠标抬起时取消document.onmousemove的对应功能,这一切都发生document上 document.onmousemove = null; } } </script> </head> <body> <div id="div1"></div> </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> *{ margin: 0; padding: 0; } #div1{ height: 200px; width: 200px; background: blueviolet; position: absolute; left: 20px; top: 100px; } </style> <script> function Drag(id) { this.oDiv = document.getElementById(id); //通过传入一个可以自定义的id值来实现相对应的参数,以便于使用,id名千万不能写死 var _this = this; //通过中间变量_this来存储当前对象的this this.oDiv.onmousedown = function(ev){ //获取事件 _this.funcDown(ev); //调用通过new来创建的对象的funcDown方法,如果此处没有中间变量_this,则指向oDiv元素对象,应该指向的是Drag函数生成的object对象,如果指向oDiv,oDiv中没有funcDown方法,无法实现拖拽 }; document.onmouseup = this.funcUp; //这个不使用中间变量的原因是this指向document,而我们需要它指向的就是document } Drag.prototype.funcDown = function(ev){ var e = ev || window.event; this.offsetX = e.pageX - this.oDiv.offsetLeft; this.offsetY = e.pageY - this.oDiv.offsetTop; var _this = this; //改变this指向,使它指向对象而不是document,因为需要调用的funcMove是Drag对象的方法 document.onmousemove = function(ev){ _this.funcMove(ev); }; } Drag.prototype.funcMove = function(ev){ var e = ev || window.event; this.oDiv.style.left = e.pageX - this.offsetX + "px"; this.oDiv.style.top = e.pageY - this.offsetY + "px"; } Drag.prototype.funcUp = function(){ document.onmousemove = null; } window.onload = function(){ new Drag("div1"); } </script> </head> <body> <div id="div1"></div> </body> </html>
总结:
1、什么时候属性需要定义为函数的属性?也就是this.属性名的形式
构造函数中那些属性需要跨函数使用则声明成构造函数的属性
2、什么时候需要声明中间变量来改变this指向
首先我们要明确自己的需求,案例中通过中间变量来改变this属性的都使用了对象中的方法funcMove,funcUp等等,而如果不声明中间变量那么此时this的主人不是drag对象,当然也没有drag中对应的方法,最终最会报错无法执行,所以首先要学习当前this指向了谁,然后确定自己的需求也就是需要this指向谁
3、除了声明中间变量还有那些方法可以改变this指向?
可以通过bind()方法来改变this指向,也可以通过箭头函数来改变,具体原理可以通过百度知晓,一句两句话概括不完
4、为什么要使用面对对象构造方法
因为面对对象构造方法拥有继承和多态的特性,有利于后期开发和拓展,极大降低修改时间与成本,所以面对对象的趋势愈发猛烈。虽然过程有些许抽象,但是最终调用只需要一两句代码即可实现!花大量时间封装自己的js库也可以提升自身的开发效率
有其他疑问可以留言私信哦。