结合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的朋友应该很快能够理解的。总结下来,这个实现也不是太难,对吧?我们一起去探索吧。。。