從面相過程的拖拽到面向對象的拖拽再到簡易的組件拖拽

首先,是最基本的面向過程的拖拽代碼

<div id="box"></div>
複製代碼
#box{
    width: 100px;
    height: 100px;
    background-color: red;
    position: absolute;
  }
複製代碼
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;
  }
}
複製代碼

開始改寫版本一

儘可能不要出現函數嵌套函數javascript

  • 能夠有全局變量
  • 把onload中不是賦值的語句放在單獨函數中
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;
}
複製代碼

面向對象的改寫 es5

  • 全局變量就是屬性
    • 函數就是方法
    • onload中建立對象
    • 改this指向問題

在ie和谷歌下,這樣是能夠的,可是火狐下,應爲有些地方爲了this指向 嵌套了一層函數,但火狐可不這樣,他認爲event是事件函數傳遞的,也就是事件後面更着的函數,這是好就須要把event當作參數傳遞了css

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;
}
複製代碼

可是火狐下報錯:TypeError: event is undefinedhtml

火狐的解決辦法
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;
}
複製代碼

也能夠吧init 放進構造函數裏面,這樣只要new 一個就能夠生成拖拽了 ,以下所示java

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;
}
複製代碼

es6 面向對象的改寫,也能夠吧init 放進構造函數裏面

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;
  }
}
複製代碼

初步總結

  • 原則 先寫出普通的寫法,而後改寫成面向對象的寫法

    普通方法變形android

    • 儘可能不要出現函數嵌套函數
    • 能夠有全局變量
    • 把onload中不是賦值的語句放在單獨函數中

    改寫面向對象git

    • 全局變量就是屬性
    • 函數就是方法
    • onload中建立對象
    • 改this指向問題

說了這麼多,咱們來封裝一個拖拽組件吧

組件就該能夠自自定義樣式吧~~~~~,data-config寫入自定義的樣式,有人說你怎麼怎麼雞肋,不如css裏面寫寫快,但也是能夠不寫的,有默認參數,js裏面已經寫好了,若是data-config寫了的話是能夠覆蓋js裏面的,具體看js代碼es6

<div id="box1" data-config='{"width": "100px","height": "100px","backgroundColor": "black","position": "absolute"}'></div>
  <script src="./index.js"></script>
  <script> var div1 = new Drag('box1'); div1.init(); </script>

複製代碼

儘可能讓用戶少寫css,那你就幫他考慮周全吧github

*{
  padding: 0;
  margin: 0;
}
div{
  width: 200px;
  height: 200px;
}
複製代碼
// 外層包裹防止函數被污染
(function () {
  // Drag 類
  class Drag {
    constructor (id) {
      this.disX = 0;
      this.disY = 0;
      this.oDiv = document.getElementById(id);
      // 默認設置
      this.config = {
        'width': '200px',
        'height': '200px',
        'backgroundColor': 'red',
        'position': 'absolute'
      };
      // 如有自定義屬性,那就合併
      if (this.getConfig()) {
        Object.assign(this.config, this.getConfig());
      }
      console.log(this.config);
      this.init();
    }
    getConfig () {
      var config = this.oDiv.getAttribute('data-config');
      if (config && config !== '') {
        return JSON.parse(config);
      } else {
        return null;
      }
    }
    init () {
      var _this = this;
      this.oDiv.onmousedown = function (ev) {
        /* 傳入_this,爲了下面不在重複寫 */
        _this.fnDown(ev, _this);
      };
      // 改變設置的屬性
      for (const i in this.config) {
        this.oDiv.style[i] = this.config[i];
      }
    }
    /* 拖拽本體 */
    fnDown (ev, _this) {
      this.disX = ev.clientX - this.oDiv.offsetLeft;
      this.disY = ev.clientY - this.oDiv.offsetTop;
      document.onmousemove = function (ev) {
        _this.fnMove(ev);
      };
      document.onmouseup = this.fnUp;
      /* 阻止默認事件 */
      return false;
    }
    fnMove (ev) {
      this.oDiv.style.left = ev.clientX - this.disX + 'px';
      this.oDiv.style.top = ev.clientY - this.disY + 'px';
    };
    fnUp () {
      document.onmousemove = null;
      document.onmouseup = null;
    }
  }
  window.Drag = Drag;
})();
複製代碼

你說啥??不支持手機端??那就來支持一下吧

支持的不夠怎麼完美,見諒。。web

// 在fnDown裏面先判斷一下
// 判斷是否爲手機端
    var touch;
    if (ev.touches) {
        touch = ev.touches[0];
    } else {
        touch = ev;
    }
    this.disX = touch.clientX - this.oDiv.offsetLeft;
    this.disY = touch.clientY - this.oDiv.offsetTop;
複製代碼

pc上的web頁面鼠 標會產生onmousedown、onmouseup、onmouseout、onmouseover、onmousemove的事件,可是在移動終端如 iphone、Touch、ipad,android上的web頁面觸屏時會產生ontouchstart、ontouchmove、ontouchend、ontouchcancel 事件,分別對應了觸屏開始、拖拽及完成觸屏事件和取消。 當按下手指時,觸發ontouchstart; 當移動手指時,觸發ontouchmove; 當移走手指時,觸發ontouchend。iphone

// 原理仍是同樣的
// js代碼以下
(function () {
  // Drag 類
  class Drag {
    constructor(id) {
      this.disX = 0;
      this.disY = 0;
      this.oDiv = document.getElementById(id);
      // 默認設置
      this.config = {
        'width': '200px',
        'height': '200px',
        'backgroundColor': 'red',
        'position': 'absolute'
      };
      // 如有自定義屬性,那就合併
      if (this.getConfig()) {
        Object.assign(this.config, this.getConfig());
      }
      console.log(this.config);
      this.init();
    }
    getConfig() {
      var config = this.oDiv.getAttribute('data-config');
      if (config && config !== '') {
        return JSON.parse(config);
      } else {
        return null;
      }
    }
    init() {
      var _this = this;
      // pc端
      this.oDiv.onmousedown = function (ev) {
        /* 傳入_this,爲了下面不在重複寫 */
        _this.fnDown(ev, _this);
      };
      // 移動端
      this.oDiv.ontouchstart=function(ev){
        _this.fnDown(ev, _this);
      }
      // 改變設置的屬性
      for (const i in this.config) {
        this.oDiv.style[i] = this.config[i];
      }
    }
    /* 拖拽本體 */
    fnDown(ev, _this) {
      // 判斷是否爲手機端
      var touch;
      if (ev.touches) {
        touch = ev.touches[0];
      } else {
        touch = ev;
      }
      this.disX = touch.clientX - this.oDiv.offsetLeft;
      this.disY = touch.clientY - this.oDiv.offsetTop;
      // pc
      document.onmousemove = function (ev) {
        _this.fnMove(ev);
      };
      // 移動端
      document.ontouchmove = function (ev) {
        _this.fnMove(ev);
      };
      document.onmouseup = this.fnUp;
      document.ontouchend = this.fnUp;
      /* 阻止默認事件 */
      return false;
    }
    fnMove(ev) {
      var touch;
      if (ev.touches) {
        touch = ev.touches[0];
      } else {
        touch = ev;
      }
      this.oDiv.style.left = touch.clientX - this.disX + 'px';
      this.oDiv.style.top = touch.clientY - this.disY + 'px';
    };
    fnUp() {
      document.onmousemove = null;
      document.ontouchmove = null;
      document.onmouseup = null;
      document.ontouchend = null;
    }
  }
  window.Drag = Drag;
})();

複製代碼

傳送門:點擊查看演示 點擊查看源碼

相關文章
相關標籤/搜索