从面相过程的拖拽到面向对象的拖拽

首先,是最基本的面向过程的拖拽代码


/*css*/
<style>
  #box{
    width: 100px;
    height: 100px;
    background-color: red;
    position: absolute;
  }
</style>

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

/*js*/
<script>
window.onload=function(){
  var oDiv=document.getElementById('box');
  var disX=0;
  var disY=0;
  oDiv.onmousedown=function(event){
  //获取事件对象
    var event=event||window.event;
    // disX相当于鼠标到div左侧的距离,同理disY
    disX=event.clientX-oDiv.offsetLeft;
    disY=event.clientY-oDiv.offsetTop;
    document.onmousemove=function(event){
      var event=event||window.event;
      oDiv.style.left=event.clientX-disX+'px';
      oDiv.style.top=event.clientY-disY+'px';
    }
    document.onmouseup=function () {
    // 鼠标释放时事件清空
      document.onmousemove=null;
      document.onmouseup=null;
    }
    return false;
  }
}
</script>

开始改写版本一

尽量不要出现函数嵌套函数

  • 可以有全局变量
  • 把onload中不是赋值的语句放在单独函数中

<script>
var oDiv=null;
var disX=0;
var disY=0;
window.onload=function(){
  oDiv=document.getElementById('box');
  init()
}
function init() {
  oDiv.onmousedown=fnDown;
}
function fnDown(event){
  var event=event||window.event;
  disX=event.clientX-oDiv.offsetLeft;
  disY=event.clientY-oDiv.offsetTop;
  document.onmousemove=fnMove;
  document.onmouseup=fnUp;
  return false;
}
function fnMove(event){
  var event=event||window.event;
  oDiv.style.left=event.clientX-disX+'px';
  oDiv.style.top=event.clientY-disY+'px';
}
function fnUp() {
  document.onmousemove=null;
  document.onmouseup=null;
}
</script>

面向对象的改写 es5

  • 全局变量就是属性
    • 函数就是方法
    • onload中创建对象
    • 改this指向问题

在ie和谷歌下,这样是可以的,但是火狐下,应为有些地方为了this指向 嵌套了一层函数,但火狐可不这样,他认为event是事件函数传递的,也就是事件后面更着的函数,这是好就需要把event当做参数传递了

<script>
window.onload=function(){
  var d=new Drag('box');
  d.init();
}
//构造函数
function Drag(id) {
  this.disX=0;
  this.disY=0;
  this.oDiv=document.getElementById(id);
}
Drag.prototype.init=function () {
 // 这里的this 指向的是Drag这个类
  var _this=this;
  this.oDiv.onmousedown=function () { //这里嵌套一层是为了解决若写成this.fnDown的话,下面fnDown里面的this就会变成this.oDiv,相当于this就变成div了
  // 匿名函数里的this是指window,因为this指的是调用他的对象,但是匿名函数不知道是谁调用的,所以可以认为是被window调用的
    _this.fnDown()
  };
}
Drag.prototype.fnDown=function (event) {
  var event=event||window.event;
  this.disX=event.clientX-this.oDiv.offsetLeft;
  this.disY=event.clientY-this.oDiv.offsetTop;
  var _this=this;
  document.onmousemove=function () {
    _this.fnMove()
  };
  document.onmouseup=this.fnUp;
  return false;
}
Drag.prototype.fnMove=function (event) {
  var event=event||window.event;
  this.oDiv.style.left=event.clientX- this.disX+'px';
  this.oDiv.style.top=event.clientY- this.disY+'px';
}
Drag.prototype.fnUp=function () {
  document.onmousemove=null;
  document.onmouseup=null;
}
</script>

但是火狐下报错:TypeError: event is undefined

火狐的解决办法
<script>
window.onload = function () {
  var d = new Drag('box');
  d.init();
}
//构造函数
function Drag(id) {
  this.disX = 0;
  this.disY = 0;
  this.oDiv = document.getElementById('box');
}
Drag.prototype.init = function () {
  var _this = this;
  this.oDiv.onmousedown = function (event) { //嵌套是为了解决this问题
    var event = event || window.event;
    _this.fnDown(event)
  };
}
Drag.prototype.fnDown = function (event) {
  this.disX = event.clientX - this.oDiv.offsetLeft;
  this.disY = event.clientY - this.oDiv.offsetTop;
  var _this = this;
  document.onmousemove = function (event) {
    _this.fnMove(event)
  };
  document.onmouseup = this.fnUp;
  return false;
}
Drag.prototype.fnMove = function (event) {
  this.oDiv.style.left = event.clientX - this.disX + 'px';
  this.oDiv.style.top = event.clientY - this.disY + 'px';
}
Drag.prototype.fnUp = function () {
  document.onmousemove = null;
  document.onmouseup = null;
}
</script>

也可以吧init 放进构造函数里面,这样只要new 一个就可以生成拖拽了
,如下所示

<script>
window.onload=function(){
 var d=new Drag('box');
}
//构造函数
function Drag(id) {
 var _this=this;
 this.disX=0;
 this.disY=0;
       this.oDiv=document.getElementById('box');
       this.oDiv.onmousedown=function (event) { //嵌套是为了解决this问题
           var event=event||window.event;
           _this.fnDown(event)
       };
}

Drag.prototype.fnDown=function (event) {
 this.disX=event.clientX-this.oDiv.offsetLeft;
 this.disY=event.clientY-this.oDiv.offsetTop;
 var _this=this;
 document.onmousemove=function (event) {
   _this.fnMove(event)
 };
 document.onmouseup=this.fnUp;
 return false;
}
Drag.prototype.fnMove=function (event) {
 this.oDiv.style.left=event.clientX- this.disX+'px';
 this.oDiv.style.top=event.clientY- this.disY+'px';
}
Drag.prototype.fnUp=function () {
 document.onmousemove=null;
 document.onmouseup=null;
}
</script>

es6 面向对象的改写,也可以吧init 放进构造函数里面

<script>
window.onload = function () {
  var d = new Drag('box');
  d.init();
}
// 类
class Drag {
  //构造函数
  constructor(id) {
    this.disX = 0;
    this.disY = 0;
    this.oDiv = document.getElementById(id);
  }
  init() {
    var _this = this;
    this.oDiv.onmousedown = function (event) {
      var event = event || window.event;
      _this.fnDown(event)
    };
  }
  fnDown(event) {
    this.disX = event.clientX - this.oDiv.offsetLeft;
    this.disY = event.clientY - this.oDiv.offsetTop;
    var _this = this;
    document.onmousemove = function (event) {
      _this.fnMove(event)
    };
    document.onmouseup = this.fnUp;
    return false;
  }
  fnMove(event) {
    this.oDiv.style.left = event.clientX - this.disX + 'px';
    this.oDiv.style.top = event.clientY - this.disY + 'px';
  }
  fnUp() {
    document.onmousemove = null;
    document.onmouseup = null;
  }
}
</script>

总结

  • 原则
    先写出普通的写法,然后改写成面向对象的写法

    普通方法变形

    • 尽量不要出现函数嵌套函数
    • 可以有全局变量
    • 把onload中不是赋值的语句放在单独函数中

    改写面向对象

    • 全局变量就是属性
    • 函数就是方法
    • onload中创建对象
    • 改this指向问题
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,420评论 0 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,497评论 18 399
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,674评论 0 38
  • 巢因斯坦阅读 96评论 0 0
  • 起个名字真的好难,想用的都被占了,想了半天就它了! 当别人问这是谁写的?作者是谁?你可以告诉他一“就是它”写的!哈...
    就是它阅读 210评论 0 0