JavaScript原生拖拽的面向對象寫法

本篇文章和上一篇介紹用面向對象的編程技術來實現tab的效果一樣,也先用面向過程的編程技術來將拖拽的效果實現一遍,然後通過變型,再用面向對象的編程技術將其實現一遍,讓讀者在對比中學習。
拖拽的效果其實在網頁開發中是一種普遍的效果,它可以讓用戶自定義的構造我們的系統界面,例如自定義地顯示錶格的列呀,自定義地設置系統的導航呀等等。
這個拖拽效果的html結構代碼如下:

<div id="drag"></div>

很簡單,它就是一個div塊而已。它的css的代碼如下:

#drag{
  width: 100px;
  height: 100px;
  background: #4693EC;
  position: absolute;
}

效果圖如下:
這裏寫圖片描述
這裏需要注意的是,我們要將拖拽的對象設置爲絕對定位,因爲只有定位的元素才能設置它的left,top等位置值,同時絕對定位的元素不佔用空間也是好處之一。
其實實現拖拽的原理很簡單,就是當鼠標點中被拖拽的對象的時候,通過觸發被拖拽對象的鼠標移動事件,不斷地設置被拖拽對象的left值爲鼠標水平移動的距離加上被拖拽對象的左邊線與瀏覽器左邊線的距離(offsetLeft),top值爲鼠標豎直移動的距離加上被拖拽對象的上邊線與瀏覽器上邊線的距離(offsetTop)。代碼如下:

window.onload = function () {
  var oDrag = document.getElementById('drag');

  // 過程式
  oDrag.onmousedown = function (event) {
    var disX = event.clientX - oDrag.offsetLeft;
    var disY = event.clientY - oDrag.offsetTop;
    document.onmousemove = function (event) {
      oDrag.style.left = event.clientX - disX + 'px';
      oDrag.style.top = event.clientY - disY + 'px';
    };
    document.onmouseup = function () {
      document.onmousemove = null;
      document.onmouseup = null;
    };
  }
}

以上是面向過程的代碼,然後我們要將其變型:

//變型
//儘量不要出現函數嵌套函數
//可以有全局變量
//把onload中不是賦值的語句放到單獨函數中
var disX = 0;
var disY = 0;
var oDrag = document.getElementById('drag');
window.onload = function () {
  init();
};
function fnMove(event) {
  oDrag.style.left = event.clientX - disX + 'px';
  oDrag.style.top = event.clientY - disY + 'px';
}
function fnUp() {
  document.onmousemove = null;
  document.onmouseup = null;
}
function fnDown(event) {
  disX = event.clientX - oDrag.offsetLeft;
  disY = event.clientY - oDrag.offsetTop;
  document.onmousemove = fnMove;
  document.onmouseup = fnUp;
}
function init() {
  oDrag.onmousedown = fnDown;
}

將其變型以後就可以將它改造成面向對象的寫法了,代碼如下:

//面向對象
//全局變量就是屬性
//函數就是方法
//onload中創建對象

//改this指向問題 : 事件或者是定時器,儘量讓面向對象中的this指向正確的對象
function Drag(id) {
  this.disX = 0;
  this.disY = 0;
  this.oDrag = document.getElementById(id);
}
Drag.prototype.fnMove = function (event) {
  this.oDrag.style.left = event.clientX - this.disX + 'px';
  this.oDrag.style.top = event.clientY - this.disY + 'px';
};
Drag.prototype.fnUp = function () {
  document.onmousemove = null;
  document.onmouseup = null;  
};
Drag.prototype.fnDown = function (event) {
  this.disX = event.clientX - this.oDrag.offsetLeft;
  this.disY = event.clientY - this.oDrag.offsetTop;
  _this = this;
  document.onmousemove = function (event) {
    _this.fnMove(event);
  };
  document.onmouseup = this.fnUp;
};
Drag.prototype.init = function () {
  _this = this;
  this.oDrag.onmousedown = function (event) {
    _this.fnDown(event);
  }
};
window.onload = function () {
  var drag = new Drag('drag');
  drag.init();
}

在將代碼改造成面向對象的風格的過程中,一定要非常的注意this的指向的問題。
我在這裏也額外的補充一個相關的知識點,看一下下面的代碼:

function q() {
  function test() {
    console.log(this);
  }
  return test();
}
q();

函數運行後的結果是什麼?很顯然是打印出window對象,因爲q()方法是由window對象調用的。至此,我們就成功地用面向對象的編程技術實現了拖拽的效果了。

發佈了65 篇原創文章 · 獲贊 77 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章