js实现拖拽效果(构造函数)


Posted in Javascript onDecember 14, 2015

一、利用构造函数模式进行开发的优势

1、业务逻辑思路更清晰;

2、避免了大量全局变量的产生,只有一个全局变量,相当于就是这一功能模块向外暴露的唯一接口;

      3、如果结合模块化开发,很方便就可以把自定义的模块加到统一modules中,只要自定义的模块名不冲突,使用起来也不会互相干扰;

      4、代码可维护性好,利人利己;

二、下面就利用这一模式,以拖拽为实例,进行讲解。
1、html,如下:

<body>
<div class="box" id="box1"><div class="main"><div class="bar">拖拽区</div><div class="content">内容区块</div></div></div>

<div class="box" id="box2"><div class="main"><div class="bar">拖拽区</div><div class="content">内容区块</div></div></div>

<div class="box" id="box3"><div class="main"><div class="bar">拖拽区</div><div class="content">内容区块</div></div></div>
</body>

2、css

<style type="text/css">
  .box{position:absolute;left:100px;top:100px;padding: 5px;box-shadow:2px 2px 4px #666666; font-size:12px;}
  #box2{left:500px;}
  #box3{left:900px; }
  .main{border:1px solid #a0b3d6;background-color: #fff; }
  .bar{line-height:24px;padding-left:5px;border-bottom:1px solid #a0b3d6;background-color:#beceeb;cursor:move;}
  .content{padding: 10px 5px;height:200px;width:250px;}
</style>

3、js

// 定义Drag构造函数,并设置每个实例的特权属性(也就是将来要创建的每个实例对象私有的属性);
function Drag(bar, target) {
  // 此处的bar是指触发拖拽事件的对象;
  this.bar = bar;

  // 此处的target是值实际上被拖动的对象;
  this.target = target;

  // 这个flag相当于是一个开关,用于判断事件是否能够执行;
  this.flag = false;
}
// 构造函数原型上添加方法,也是为其实例添加公用方法公用方法;
Drag.prototype = {
  // 重新声明原型的constructor属性,也就是为实例指定正真的创建者;这里不重新指定也没问题,就是为了。。。
  constructor : Drag,

  // 初始化每个实例的属性,为绑定事件做好准备;
  init : function(){
    // 这边的this其实是指调用这个init函数方法的那个对象,也就是我们所创建的实例;
    // 这么写有好处,代码执行到绑定事件那一块再详细的讲;
    var temp = this;

    // 获取实例对象上最先设定的样式值,这边就是left和top属性;
    temp.left = temp.getCss(temp.target, "left");
    temp.top = temp.getCss(temp.target, "top");

    // 预先声明下面要用的到值,这边是指储存鼠标点下去的瞬间鼠标相对于屏幕的位置(clientX、clientY)
    temp.mousePosX = null;
    temp.mousePosY = null;

    // 发出为实例对象绑定事件的命令;
    temp.bindEvent();
  },
  //
  getCss : function(o , prop){
    // Dom对象的style属性指向的对象只能获得嵌入式样式的值,比如<a style="..."></a>,这种写在元素内部的可以获得;
    // 但是通过外联样式表和内联样式表设置的样式值,只能通过以下方法获得,currentStyle对应的是Ie,另一个对应的是其他浏览器;
    return o.currentStyle ? o.currentStyle[prop] : document.defaultView.getComputedStyle(o, null)[prop];
  },
  bindEvent : function(){
    // 先把调用这个bindEvent方法的this对象(也就是我们创建的实例对象)传递给temp变量,于是temp也就指向了实例对象;
    // 因此,在当前函数的执行环境内,想要调用这个实例对象,而不必要使用this了,因为此时的this可能指向的其他的对象;
    // 比如,在为某个对象绑定事件的时候,这个事件内部的this肯定是指向绑定的对象的,而不是我们想要的最开始的那个“this”
    var temp = this;

    // 监听鼠标点下的事件函数
    temp.bar.onmousedown = function(e){
      // 这边的e是指事件对象,老Ie不能直接使用,得通过window.event来引用;
      e = e || window.event;

      // 点下的瞬间就把这个开关打开,表明现在可以拖动了;
      temp.flag = true;

      // 获取鼠标相对与浏览器窗口的位置,并且赋值给实例对象的mousePos属性;
      temp.mousePosX = e.clientX;
      temp.mousePosY = e.clientY;
    };

    // 监听鼠标移动事件,注意这个绑定到document对象上的事件,因为鼠标在整个文档上移动;
    // 这边不能用onmousemove方法绑定事件,因为我们的实例可能有多个,如果用次方法,最后初始化的那个实例才绑定到事件函数;
    document.addEventListener('mousemove' ,function(e){
      e = e || window.event;

      // 因为在鼠标点下的时候,已经指定flag为true了,所以下面的代码才会执行;
      // 如果没有这个开关控制,我们移动鼠标的时候,我们创建的实例对象都要移动;
      if(temp.flag){

        // (e.clientX - temp.mousePosX)代表了鼠标自按下后滑动的距离;
        // parseInt(temp.left)是指鼠标还没滑动时,被拖动对象的初始位置;
        temp.target.style.left = parseInt(temp.left) + e.clientX - temp.mousePosX + "px";
        temp.target.style.top = parseInt(temp.top) + e.clientY - temp.mousePosY + "px";
      }
    });

    // 鼠标放开后事件
    document.addEventListener('mouseup', function(e){
      // 鼠标放开后,就把这个开关了,就说明拖动对象不能被拖动了;
      temp.flag = false;

      // 记录被拖动对象的被拖动后的位置
      temp.left = temp.getCss(temp.target, "left");
      temp.top = temp.getCss(temp.target, "top");
    });
  }
}

// 获取Dom元素,oBar是指拖动条,oBox是指实际上拖拽对象;
var oBox = document.getElementsByClassName('box');
var oBar = document.getElementsByClassName('bar');
// 创建实例对象,注意参数顺序;
var drag1 = new Drag(oBar[0], oBox[0]);
var drag2 = new Drag(oBar[1], oBox[1]);
var drag3 = new Drag(oBar[2], oBox[2]);
// 调用实例对象上的init方法,为实例对象指定设计好的操作流程;
drag1.init();
drag2.init();
drag3.init();

具体的过程都通过js注释说明了,希望能够帮助大家更好地利用构造函数实现拖拽效果。

Javascript 相关文章推荐
jQuery帮助之筛选查找 children([expr])
Jan 31 Javascript
JavaScript极简入门教程(二):对象和函数
Oct 25 Javascript
浅谈利用JavaScript进行的DDoS攻击原理与防御
Jun 04 Javascript
javascript的几种继承方法介绍
Mar 22 Javascript
举例讲解jQuery对DOM元素的向上遍历、向下遍历和水平遍历
Jul 07 Javascript
js select实现省市区联动选择
Apr 17 Javascript
微信小程序自定义组件封装及父子间组件传值的方法
Aug 28 Javascript
JS实现字符串翻转的方法分析
Aug 31 Javascript
VueJs里利用CryptoJs实现加密及解密的方法示例
Apr 29 Javascript
layui 解决富文本框form表单提交为空的问题
Oct 26 Javascript
jQuery操作选中select下拉框的值代码实例
Feb 07 jQuery
JavaScript架构搭建前端监控如何采集异常数据
Jun 25 Javascript
jQuery滚动加载图片实现原理
Dec 14 #Javascript
jQuery点击按钮弹出遮罩层且内容居中特效
Dec 14 #Javascript
jquery实现倒计时效果
Dec 14 #Javascript
JavaScript 七大技巧(一)
Dec 13 #Javascript
JavaScript 七大技巧(二)
Dec 13 #Javascript
js自定义回调函数
Dec 13 #Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
Dec 13 #Javascript
You might like
php写的带缓存数据功能的mysqli类
2012/09/06 PHP
PHP实现多图片上传类实例
2014/07/26 PHP
YII2.0之Activeform表单组件用法实例
2016/01/09 PHP
RR vs IO BO3 第一场2.13
2021/03/10 DOTA
JQuery模板插件 jquery.tmpl 动态ajax扩展
2011/11/10 Javascript
AngularJS内置指令
2015/02/04 Javascript
自己封装的一个简单的倒计时功能实例
2016/11/23 Javascript
使用vue.js实现联动效果的示例代码
2017/01/10 Javascript
JS实现禁止高频率连续点击的方法【基于ES6语法】
2017/04/25 Javascript
EasyUI Datebox 日期验证之开始日期小于结束时间
2017/05/19 Javascript
js 显示日期时间的实例(时间过一秒加1)
2017/10/25 Javascript
node.js基于fs模块对系统文件及目录进行读写操作的方法详解
2017/11/10 Javascript
vue父组件点击触发子组件事件的实例讲解
2018/02/08 Javascript
Vue-路由导航菜单栏的高亮设置方法
2018/03/17 Javascript
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
2种在vue项目中使用百度地图的简单方法
2018/09/28 Javascript
Node.js Buffer模块功能及常用方法实例分析
2019/01/05 Javascript
JS实现碰撞检测效果
2020/03/12 Javascript
VUE实现吸底按钮
2021/03/04 Vue.js
在Python中关于中文编码问题的处理建议
2015/04/08 Python
Django imgareaselect手动剪切头像实现方法
2015/05/26 Python
Python监控主机是否存活并以邮件报警
2015/09/22 Python
在Mac OS上使用mod_wsgi连接Python与Apache服务器
2015/12/24 Python
Python机器学习之决策树算法
2017/12/22 Python
Python多线程处理实例详解【单进程/多进程】
2019/01/30 Python
Python HTML解析模块HTMLParser用法分析【爬虫工具】
2019/04/05 Python
Python人脸识别第三方库face_recognition接口说明文档
2019/05/03 Python
wxpython实现按钮切换界面的方法
2019/11/19 Python
Python安装与卸载流程详细步骤(图解)
2020/02/20 Python
CSS3 3D位移translate效果实例介绍
2016/05/03 HTML / CSS
中医临床专业自我鉴定范文
2014/01/15 职场文书
“四风”问题对照检查材料思想汇报
2014/09/16 职场文书
车辆年检委托书范本
2014/10/14 职场文书
2015年清明节扫墓演讲稿
2015/03/18 职场文书
运动会新闻稿
2015/07/17 职场文书
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA