结合AngularJS实现拖拽
最近项目中要实现,左侧树向右侧树中元素的拖拽功能,开始在网上看了好多ng-drag等等操作,都没有实现预想的效果,偶然发现一篇博客,然后根据博客改编,实现了自己想要的效果。下面简单的分析一下实现过程。首先我先附上源码,如下:
1 DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>testtitle> 7 <script src="angular.min.js">script> 8 <style> 9 ul { 10 padding: 0; 11 margin: 0; 12 width: 300px; 13 } 14 15 .left { 16 float: left; 17 background-color: #ddd; 18 margin-left: 300px; 19 } 20 21 .right { 22 float: right; 23 background-color: #aaa; 24 margin-right: 300px; 25 } 26 27 li { 28 line-height: 30px; 29 } 30 31 .left li:hover { 32 background-color: orange; 33 cursor: move; 34 } 35 36 .right li:hover { 37 background-color: red; 38 cursor: move; 39 } 40 style> 41 head> 42 43 <body ng-app="myApp" ng-controller="MyCtrl"> 44 <ul class="left"> 45 <li ng-repeat="item in dogs" draggable="true" ruby-dragstart="dragstart(item)">{{ item.name }}li> 46 ul> 47 <ul class="right"> 48 <li ng-repeat="item in cats" ruby-drop="drop(event,item)" ruby-dragover="dragover(event)">{{ item.name }}li> 49 ul> 50 <script> 51 var app = angular.module('myApp', []); 52 app.controller('MyCtrl', ['$scope', function($scope) { 53 $scope.dogs = [ 54 { 'id': '1', 'name': '大狗' }, 55 { 'id': '2', 'name': '二狗' }, 56 { 'id': '3', 'name': '三狗' }, 57 { 'id': '4', 'name': '四狗' } 58 ]; 59 $scope.cats = [ 60 { 'id': '11', 'name': '大猫' }, 61 { 'id': '12', 'name': '二猫' }, 62 { 'id': '13', 'name': '三猫' }, 63 { 'id': '14', 'name': '四猫' } 64 ]; 65 $scope.dragover = function(event) { 66 event.preventDefault(); 67 } 68 $scope.dragstart = function(item) { 69 $scope.clientInfo = item; 70 } 71 $scope.drop = function(event, item) { 72 event.preventDefault(); 73 console.log("dog:->", $scope.clientInfo); 74 console.log("cat:->", item); 75 } 76 }]); 77 var convertFirstUpperCase = function(str) { 78 return str.replace(/(\w)/, function(s) { 79 return s.toUpperCase(); 80 }); 81 }; 82 rubyDragEventDirectives = {}; 83 angular.forEach("dragstart drag dragenter dragover drop dragleave dragend".split(' '), function(eventName) { 84 var rubyEventName = 'ruby' + convertFirstUpperCase(eventName); 85 rubyDragEventDirectives[rubyEventName] = ['$parse', function($parse) { 86 //$parse 语句解析器 87 return { 88 restrict: 'A', 89 compile: function(ele, attr) { 90 var fn = $parse(attr[rubyEventName]); 91 return function rubyEventHandler(scope, ele) { 92 ele[0].addEventListener(eventName, function(event) { 93 if (eventName == 'dragover' || eventName == 'drop') { 94 event.preventDefault(); 95 } 96 var callback = function() { 97 fn(scope, { event: event }); 98 }; 99 callback(); 100 }); 101 } 102 } 103 } 104 }] 105 }); 106 app.directive(rubyDragEventDirectives); 107 script> 108 body> 109 110 html>
为了简便,我把整个html,css以及js写在一个文件了,如果是真实项目中,最好将其分开。其实大家可以发现,html中仅仅只是加入了自定义指令
ruby-dragstart,开始拖动,可以检测到开始拖动的整个event及DOM元素;
ruby-dragover,当某被拖动的对象在另一对象容器范围内拖动时触发此事件.在该事件里填写: event.preventDefault() 。注:事件的默认行为是不允许被拖拽元素在其他元素上释放或放置(即无法触发 drop 事件),需要通过 event.preventDefault() 来阻止默认行为才能触发后续的 drop 事件)
ruby-drop,拖动的目标元素,当你拖动结束,会检测到是在哪个DOM元素上结束的拖拽事件;
draggable="true" ,是允许拖动,加上之后,拖动的时候会显示一个加号。
CSS这里就不再赘述了,大家想怎么玩就怎么玩,还要注意的一点就是自定义指令rubyDragEventDirectives,在自定义模块中,convertFirstUpperCase是为入参做一个合理接收,熟悉JS的朋友应该很快能够理解的。总结下来,这个实现也不是太难,对吧?我们一起去探索吧。。。