前端工程师小A学习JS的旅程
前端工程师小A学习JS的旅程
前端工程师小A学习JS的旅程
在网页里, 拖拽效果是很常见的形式,实现起来也比较简单,但是这么简单的代码,却能体现出很多前端开发工程湿的JS能力,我们来看看小A工程师的实现路程:
HTML代码:
<! DOCTYPE HTML > < html > < head > < title > 拖拽效果 </ title > < meta charset ="UTF-8" > < meta http-equiv ="X-UA-Compatible" content ="IE=Edge,chrome=1" > < style type ="text/css" > #drag_box { width : 150px ; height : 150px ; background-color : #ff0000 ; position : absolute ; margin : 0 ; top : 80px ; left : 0 ; } #diy,#dix { width : 70px ; display : inline-block ; height : 30px ; } </ style > </ head > < body > < span id ="dix" > X:0px </ span > < input type ="button" value ="锁定X轴" id ="closeX" data-open ="true" > < br /> < span id ="diy" > Y:80px </ span > < input type ="button" value ="锁定Y轴" id ="closeY" data-open ="true" > < div id ="drag_box" ></ div > </ body > </ html >
JS代码:
小A的拖拽JS代码第一版
<script type="text/javascript"> var closeX=document.getElementById("closeX"),closeY=document.getElementById("closeY" ); closeX.onclick = function (){ if ( this .getAttribute("data-open")=="true" ){ this .setAttribute("data-open","false" ); this .value="解开X轴" ; } else { this .setAttribute("data-open","true" ); this .value="锁定X轴" ; } } closeY.onclick = function (){ if ( this .getAttribute("data-open")=="true" ){ this .setAttribute("data-open","false" ); this .value="解开Y轴" ; } else { this .setAttribute("data-open","true" ); this .value="锁定Y轴" ; } } var box=document.getElementById('drag_box' ); var x=y=0 ; var dix=document.getElementById("dix"),diy=document.getElementById("diy" ); box.onmousedown = function (event){ var event=event|| window.event; x =event.clientX- this .offsetLeft; y =event.clientY- this .offsetTop; this .style.cursor="move" ; var that = this ; document.onmousemove = function (event){ var event=event|| window.event; var le=event.clientX-x,to=event.clientY- y; var maxL = document.documentElement.clientWidth - box.offsetWidth; var maxT = document.documentElement.clientHeight - box.offsetHeight; if (le<0 ){ le =0 } else if (le> maxL){ le = maxL; } if (to<80 ){ to =80 } else if (to> maxT){ to = maxT; } if (closeX.getAttribute("data-open")=="true" ){ that.style.left =le+"px" ; dix.innerHTML ="X:"+le+"px" ; } if (closeY.getAttribute("data-open")=="true" ){ that.style.top =to+"px" ; diy.innerHTML ="Y:"+to+"px" ; } if (that.releaseCapture){ that.releaseCapture(); } return false ; } this .onmouseup= function (){ document.onmousemove = null ; document.onmouseup = null ; this .style.cursor="default" ; if ( this .releaseCapture){ this .releaseCapture(); } return false ; } if ( this .releaseCapture){ this .releaseCapture(); } return false ; } </script>
这是小A初学JS一个月写出来的JS代码,完美实现了拖拽的功能,并且也能也能注意在适当的时候阻止事件的默认行为,还能用上 if(this.releaseCapture){ this.releaseCapture(); }这样的语句来防止鼠标离开拖拽BOX。对于小A来说,学习一个月能写出这样的代码来已经实属不易,我们也不得不承认小A是一个学习能力很强的前端工程师。
又学习了一个月小A学到了js的封装,于是重新看了看上面的代码,觉得处理锁定X轴和锁定Y轴的代码有些重复,而且拖拽的对象可能会发生变化,于是小A改造了一下上面的代码,创建了两个方法函数 drag和closexy把主体功能封转在两个函数里面:
小A的拖拽JS代码第二版
<script type="text/javascript"> function drag (box) { var x=y=0 ; var dix=document.getElementById("dix"),diy=document.getElementById("diy" ); box.onmousedown = function (event){ var event=event|| window.event; x =event.clientX- this .offsetLeft; y =event.clientY- this .offsetTop; this .style.cursor="move" ; var that = this ; document.onmousemove = function (event){ var event=event|| window.event; var le=event.clientX-x,to=event.clientY- y; var maxL = document.documentElement.clientWidth - box.offsetWidth; var maxT = document.documentElement.clientHeight - box.offsetHeight; if (le<0 ){ le =0 } else if (le> maxL){ le = maxL; } if (to<80 ){ to =80 } else if (to> maxT){ to = maxT; } if (closeX.getAttribute("data-open")=="true" ){ that.style.left =le+"px" ; dix.innerHTML ="X:"+le+"px" ; } if (closeY.getAttribute("data-open")=="true" ){ that.style.top =to+"px" ; diy.innerHTML ="Y:"+to+"px" ; } if (that.releaseCapture){ that.releaseCapture(); } return false ; } this .onmouseup= function (){ document.onmousemove = null ; document.onmouseup = null ; this .style.cursor="default" ; if ( this .releaseCapture){ this .releaseCapture(); } return false ; } if ( this .releaseCapture){ this .releaseCapture(); } return false ; } } function closexy(xy,obj){ if (obj.getAttribute("data-open")=="true" ){ obj.setAttribute( "data-open","false" ); obj.value ="解开"+xy+"轴" ; } else { obj.setAttribute( "data-open","true" ); obj.value ="锁定"+xy+"轴" ; } } var box=document.getElementById('drag_box' ); drag(box); var closeX=document.getElementById("closeX"),closeY=document.getElementById("closeY" ); closeX.onclick = function (){ closexy( "X", this ); } closeY.onclick = function (){ closexy( "Y", this ); } </script>
这样一看,代码量减少了许多,而且显得也比较调理,更重要的是封转后的方法在随意的对象上都可以调用,简单、方便!此时的小A学习js的激情高涨,于是就更加勤奋的学习!
又不知过了多久。小A的js水平有了大幅提高,这个时候小A回头看之前写过的拖拽代码,觉得有很多不妥的地方,比如:没有注意命名空间,没有成模块化、如果拖拽的外围边界不是body了怎么变、如果拖拽的范围变化了呢,拖拽的锁定可不可以做成开放性的呢。基于这些问题,于是小A觉得完全可以把拖拽功能做成一个拖拽库,开放接口,以应付千变万化的拖拽效果和需求,所以小A又写了第三版的拖拽JS代码:
小A的拖拽JS代码第三版
<script type="text/javascript"> /* * * * dragBox:拖动对象,可以是对象的ID; * * options:参数; * * maxContainer:设置拖动外围box,默认为body; * * minL:离外围边界左边最小距离,默认为0; * * maxL:离外边界左边最大距离,默认body的宽度-拖动对象宽度; * * minT:离外围边界上边最小距离,默认为0; * * maxT:离外围边界最大高度,默认为body高度-拖动对象高度; * * lockx:是否锁定X轴,默认不锁定; * * locky:是否锁定Y轴,默认不锁定; * * onStart:开始拖动回调函数; * * onMove:拖动过程中回调函数; * * onStop:拖动结束回调函数; */ function Drag(){ this .init.apply( this ,arguments); } Drag.prototype = { init: function (dragBox,options){ this .dragBox= this .$(dragBox); this .setOptions(options); this ._moveDrag= this .bind( this , this .moveDrag); this ._stopDrag= this .bind( this , this .stopDrag); this .maxContainer = this .options.maxContainer||document.documentElement || document.body; this .minL= this .options.minL||0 ; this .maxL= this .options.maxL||Math.max( this .maxContainer.clientWidth, this .maxContainer.scrollWidth)- this .dragBox.offsetWidth; this .minT= this .options.minT||0 ; this .maxT= this .options.maxT||Math.max( this .maxContainer.clientHeight, this .maxContainer.scrollHeight)- this .dragBox.offsetHeight; this .lockx = this .options.lockx|| false ; this .locky = this .options.locky|| false ; this .onStart= this .options.onStart|| null ; this .onMove= this .options.onMove|| null ; this .onStop= this .options.onStop|| null ; this .addHandle( this .dragBox, "mousedown", this .bind( this , this .startDrag)); this .haslayout(); }, haslayout: function (){ this .dragBox.style.left= this .minL+"px" ; this .dragBox.style.top= this .minT+"px" ; }, startDrag: function (event){ var event=event|| window.event; this ._x=event.clientX- this .dragBox.offsetLeft; this ._y=event.clientY- this .dragBox.offsetTop; this .addHandle(document,"mousemove", this ._moveDrag); this .addHandle(document,"mouseup", this ._stopDrag); this .preventDefault(event); this .dragBox.setCapture && this .dragBox.setCapture(); if ( typeof onStart==="function" ){ this .onStart(); } }, moveDrag: function (event){ var event=event|| window.event; this .dragBox.style.cursor = "move" ; var le=event.clientX- this ._x,to=event.clientY- this ._y; if (le< this .minL){ le = this .minL } else if (le> this .maxL){ le = this .maxL; } if (to< this .minT){ to = this .minT; } else if (to> this .maxT){ to = this .maxT; } if (! this .lockx){ this .dragBox.style.left=le+"px" ; } if (! this .locky){ this .dragBox.style.top=to+"px" ; } this .preventDefault(event); this .dragBox.setCapture && this .dragBox.setCapture(); if ( typeof onMove==="function" ){ this .onMove(); } }, stopDrag: function (){ this .removeHandle(document,"mousemove", this ._moveDrag); this .removeHandle(document,"mouseup", this ._stopDrag); this .dragBox.style.cursor = "default" ; this .dragBox.setCapture && this .dragBox.setCapture(); if ( typeof onStop==="function" ){ this .onStop(); } }, $: function (id){ return typeof id=="string" ? document.getElementById(id):id; }, addHandle: function (element,type,handler){ if (element.addEventListener){ element.addEventListener(type,handler, false ); } else if (element.attachEvent){ element.attachEvent( "on"+ type,handler); } else { element[ "on"+type]= handler; } }, removeHandle: function (element,type,handler){ if (element.removeEventListener){ element.removeEventListener(type,handler, false ); } else if (element.detachEvent){ element.detachEvent( "on"+ type,handler); } else { element[ "on"+type]= null ; } }, preventDefault: function (event){ if (event.preventDefault){ event.preventDefault(); } else { event.returnValue = false ; } }, setOptions : function (options){ this .options = {}; for ( var p in options) this .options[p] = options[p]; }, bind : function (object, fnHandler){ return function (){ return fnHandler.apply(object, arguments) } } }; // 应用 var box=document.getElementById("drag_box" ); var Mydrag= new Drag(box,{ minT: 10 , maxT: 100 , lockx: true }); </script>
这样,一个功能齐全的拖拽库就这样漂亮的诞生了!拖拽库开放接口很齐全,代码页很规范。从此小A就不用害怕任何拖拽功能需求了!
从小A学习js的旅程,我们可以看出,学习JS是一个循序渐进的过程,看似简单的功能,从最开始的实现功能,到不断改进,一直到最后写成一个插件,可以有很多版本,而这些不断改进的过程正是学习JS最好的方法!
标签: javascript
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息