深究AngularJS中ng-drag、ng-drop的用法


Posted in Javascript onJune 12, 2017

1.相关地址:

插件下载:https://github.com/fatlinesofcode/ngDraggable/blob/master/ngDraggable.js

2.讲解

<div ng-drop="true" ng-drop-success="dropComplete($index,$data,$event)" ng-repeat="item in content">
  <li ng-drag="true" ng-drag-data="item" >
    姓名:{{item.name}},年龄:{{item.age}}
  </li>
</div>

ng-drag : 表示该元素能够被拖动

ng-drag-data : 表示拖动元素时跟着被拖走的数据

ng-drop : 表示该元素内可放置被拖动的元素

ng-drop-success : 放置在ngd-drop所在元素里后触发,一般写事件.

ng-drop-success触发的dropComplete方法的参数说明:

  1. $index : 表示拖动的数据所落的元素的下标
  2. $data : 被拖动的数据对象

3.拖拽排序示例

页面代码

<div ng-drop="true" ng-drop-success="dropComplete($index,$data)" ng-repeat="item in content">
  <li ng-drag="true" ng-drag-data="item" >
    姓名:{{item.name}},年龄:{{item.age}}
  </li>
</div>

js代码

//数据
$scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}];

/** 拖拽成功触发方法
*  index 拖拽后落下时的元素的序号(下标)
*  obj被拖动数据对象
*/
$scope.dropComplete = function(index, obj){
    //重新排序
    var idx = $scope.content.indexOf(obj);       
    $scope.content.splice(idx,1);
    $scope.content.splice(index,0,obj);  

};

4.拖拽交换示例

页面代码

<div ng-drop="true" ng-drop-success="dropComplete($index,$data)" ng-repeat="item in content">
  <li ng-drag="true" ng-drag-data="item" >
    姓名:{{item.name}},年龄:{{item.age}}
  </li>
</div>

JS代码

//数据
$scope.content = [{'name':'张春玲','age':28},{'name':'王晰','age':26},{'name':'吴正青','age':66}];

/** 拖拽成功触发方法
*  index 拖拽后落下时的元素的序号(下标)
*  obj 被拖动数据对象
*/
$scope.dropComplete = function(index, obj){
    var idx = $scope.content.indexOf(obj); 
    $scope.content[idx] = $scope.content[index];
    $scope.content[index] = obj;      
};

5. ngDraggable插件代码

/*
 *
 * https://github.com/fatlinesofcode/ngDraggable
 */
angular.module("ngDraggable", [])
  .service('ngDraggable', [function() {


    var scope = this;
    scope.inputEvent = function(event) {
      if (angular.isDefined(event.touches)) {
        return event.touches[0];
      }
      //Checking both is not redundent. If only check if touches isDefined, angularjs isDefnied will return error and stop the remaining scripty if event.originalEvent is not defined.
      else if (angular.isDefined(event.originalEvent) && angular.isDefined(event.originalEvent.touches)) {
        return event.originalEvent.touches[0];
      }
      return event;
    };

  }])
  .directive('ngDrag', ['$rootScope', '$parse', '$document', '$window', 'ngDraggable', function ($rootScope, $parse, $document, $window, ngDraggable) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        scope.value = attrs.ngDrag;
        var offset,_centerAnchor=false,_mx,_my,_tx,_ty,_mrx,_mry;
        var _hasTouch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
        var _pressEvents = 'touchstart mousedown';
        var _moveEvents = 'touchmove mousemove';
        var _releaseEvents = 'touchend mouseup';
        var _dragHandle;

        // to identify the element in order to prevent getting superflous events when a single element has both drag and drop directives on it.
        var _myid = scope.$id;
        var _data = null;

        var _dragOffset = null;

        var _dragEnabled = false;

        var _pressTimer = null;

        var onDragStartCallback = $parse(attrs.ngDragStart) || null;
        var onDragStopCallback = $parse(attrs.ngDragStop) || null;
        var onDragSuccessCallback = $parse(attrs.ngDragSuccess) || null;
        var allowTransform = angular.isDefined(attrs.allowTransform) ? scope.$eval(attrs.allowTransform) : true;

        var getDragData = $parse(attrs.ngDragData);

        // deregistration function for mouse move events in $rootScope triggered by jqLite trigger handler
        var _deregisterRootMoveListener = angular.noop;

        var initialize = function () {
          element.attr('draggable', 'false'); // prevent native drag
          // check to see if drag handle(s) was specified
          // if querySelectorAll is available, we use this instead of find
          // as JQLite find is limited to tagnames
          if (element[0].querySelectorAll) {
            var dragHandles = angular.element(element[0].querySelectorAll('[ng-drag-handle]'));
          } else {
            var dragHandles = element.find('[ng-drag-handle]');
          }
          if (dragHandles.length) {
            _dragHandle = dragHandles;
          }
          toggleListeners(true);
        };

        var toggleListeners = function (enable) {
          if (!enable)return;
          // add listeners.

          scope.$on('$destroy', onDestroy);
          scope.$watch(attrs.ngDrag, onEnableChange);
          scope.$watch(attrs.ngCenterAnchor, onCenterAnchor);
          // wire up touch events
          if (_dragHandle) {
            // handle(s) specified, use those to initiate drag
            _dragHandle.on(_pressEvents, onpress);
          } else {
            // no handle(s) specified, use the element as the handle
            element.on(_pressEvents, onpress);
          }
          if(! _hasTouch && element[0].nodeName.toLowerCase() == "img"){
            element.on('mousedown', function(){ return false;}); // prevent native drag for images
          }
        };
        var onDestroy = function (enable) {
          toggleListeners(false);
        };
        var onEnableChange = function (newVal, oldVal) {
          _dragEnabled = (newVal);
        };
        var onCenterAnchor = function (newVal, oldVal) {
          if(angular.isDefined(newVal))
            _centerAnchor = (newVal || 'true');
        };

        var isClickableElement = function (evt) {
          return (
            angular.isDefined(angular.element(evt.target).attr("ng-cancel-drag"))
          );
        };
        /*
         * When the element is clicked start the drag behaviour
         * On touch devices as a small delay so as not to prevent native window scrolling
         */
        var onpress = function(evt) {
          if(! _dragEnabled)return;

          if (isClickableElement(evt)) {
            return;
          }

          if (evt.type == "mousedown" && evt.button != 0) {
            // Do not start dragging on right-click
            return;
          }

          if(_hasTouch){
            cancelPress();
            _pressTimer = setTimeout(function(){
              cancelPress();
              onlongpress(evt);
            },100);
            $document.on(_moveEvents, cancelPress);
            $document.on(_releaseEvents, cancelPress);
          }else{
            onlongpress(evt);
          }

        };

        var cancelPress = function() {
          clearTimeout(_pressTimer);
          $document.off(_moveEvents, cancelPress);
          $document.off(_releaseEvents, cancelPress);
        };

        var onlongpress = function(evt) {
          if(! _dragEnabled)return;
          evt.preventDefault();

          offset = element[0].getBoundingClientRect();
          if(allowTransform)
            _dragOffset = offset;
          else{
            _dragOffset = {left:document.body.scrollLeft, top:document.body.scrollTop};
          }


          element.centerX = element[0].offsetWidth / 2;
          element.centerY = element[0].offsetHeight / 2;

          _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX');
          _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY');
          _mrx = _mx - offset.left;
          _mry = _my - offset.top;
          if (_centerAnchor) {
            _tx = _mx - element.centerX - $window.pageXOffset;
            _ty = _my - element.centerY - $window.pageYOffset;
          } else {
            _tx = _mx - _mrx - $window.pageXOffset;
            _ty = _my - _mry - $window.pageYOffset;
          }

          $document.on(_moveEvents, onmove);
          $document.on(_releaseEvents, onrelease);
          // This event is used to receive manually triggered mouse move events
          // jqLite unfortunately only supports triggerHandler(...)
          // See http://api.jquery.com/triggerHandler/
          // _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', onmove);
          _deregisterRootMoveListener = $rootScope.$on('draggable:_triggerHandlerMove', function(event, origEvent) {
            onmove(origEvent);
          });
        };

        var onmove = function (evt) {
          if (!_dragEnabled)return;
          evt.preventDefault();

          if (!element.hasClass('dragging')) {
            _data = getDragData(scope);
            element.addClass('dragging');
            $rootScope.$broadcast('draggable:start', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data});

            if (onDragStartCallback ){
              scope.$apply(function () {
                onDragStartCallback(scope, {$data: _data, $event: evt});
              });
            }
          }

          _mx = ngDraggable.inputEvent(evt).pageX;//ngDraggable.getEventProp(evt, 'pageX');
          _my = ngDraggable.inputEvent(evt).pageY;//ngDraggable.getEventProp(evt, 'pageY');

          if (_centerAnchor) {
            _tx = _mx - element.centerX - _dragOffset.left;
            _ty = _my - element.centerY - _dragOffset.top;
          } else {
            _tx = _mx - _mrx - _dragOffset.left;
            _ty = _my - _mry - _dragOffset.top;
          }

          moveElement(_tx, _ty);

          $rootScope.$broadcast('draggable:move', { x: _mx, y: _my, tx: _tx, ty: _ty, event: evt, element: element, data: _data, uid: _myid, dragOffset: _dragOffset });
        };

        var onrelease = function(evt) {
          if (!_dragEnabled)
            return;
          evt.preventDefault();
          $rootScope.$broadcast('draggable:end', {x:_mx, y:_my, tx:_tx, ty:_ty, event:evt, element:element, data:_data, callback:onDragComplete, uid: _myid});
          element.removeClass('dragging');
          element.parent().find('.drag-enter').removeClass('drag-enter');
          reset();
          $document.off(_moveEvents, onmove);
          $document.off(_releaseEvents, onrelease);

          if (onDragStopCallback ){
            scope.$apply(function () {
              onDragStopCallback(scope, {$data: _data, $event: evt});
            });
          }

          _deregisterRootMoveListener();
        };

        var onDragComplete = function(evt) {


          if (!onDragSuccessCallback )return;

          scope.$apply(function () {
            onDragSuccessCallback(scope, {$data: _data, $event: evt});
          });
        };

        var reset = function() {
          if(allowTransform)
            element.css({transform:'', 'z-index':'', '-webkit-transform':'', '-ms-transform':''});
          else
            element.css({'position':'',top:'',left:''});
        };

        var moveElement = function (x, y) {
          if(allowTransform) {
            element.css({
              transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)',
              'z-index': 99999,
              '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, ' + x + ', ' + y + ', 0, 1)',
              '-ms-transform': 'matrix(1, 0, 0, 1, ' + x + ', ' + y + ')'
            });
          }else{
            element.css({'left':x+'px','top':y+'px', 'position':'fixed'});
          }
        };
        initialize();
      }
    };
  }])

  .directive('ngDrop', ['$parse', '$timeout', '$window', '$document', 'ngDraggable', function ($parse, $timeout, $window, $document, ngDraggable) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        scope.value = attrs.ngDrop;
        scope.isTouching = false;

        var _lastDropTouch=null;

        var _myid = scope.$id;

        var _dropEnabled=false;

        var onDropCallback = $parse(attrs.ngDropSuccess);// || function(){};

        var onDragStartCallback = $parse(attrs.ngDragStart);
        var onDragStopCallback = $parse(attrs.ngDragStop);
        var onDragMoveCallback = $parse(attrs.ngDragMove);

        var initialize = function () {
          toggleListeners(true);
        };

        var toggleListeners = function (enable) {
          // remove listeners

          if (!enable)return;
          // add listeners.
          scope.$watch(attrs.ngDrop, onEnableChange);
          scope.$on('$destroy', onDestroy);
          scope.$on('draggable:start', onDragStart);
          scope.$on('draggable:move', onDragMove);
          scope.$on('draggable:end', onDragEnd);
        };

        var onDestroy = function (enable) {
          toggleListeners(false);
        };
        var onEnableChange = function (newVal, oldVal) {
          _dropEnabled=newVal;
        };
        var onDragStart = function(evt, obj) {
          if(! _dropEnabled)return;
          isTouching(obj.x,obj.y,obj.element);

          if (attrs.ngDragStart) {
            $timeout(function(){
              onDragStartCallback(scope, {$data: obj.data, $event: obj});
            });
          }
        };
        var onDragMove = function(evt, obj) {
          if(! _dropEnabled)return;
          isTouching(obj.x,obj.y,obj.element);

          if (attrs.ngDragMove) {
            $timeout(function(){
              onDragMoveCallback(scope, {$data: obj.data, $event: obj});
            });
          }
        };

        var onDragEnd = function (evt, obj) {

          // don't listen to drop events if this is the element being dragged
          // only update the styles and return
          if (!_dropEnabled || _myid === obj.uid) {
            updateDragStyles(false, obj.element);
            return;
          }
          if (isTouching(obj.x, obj.y, obj.element)) {
            // call the ngDraggable ngDragSuccess element callback
            if(obj.callback){
              obj.callback(obj);
            }

            if (attrs.ngDropSuccess) {
              $timeout(function(){
                onDropCallback(scope, {$data: obj.data, $event: obj, $target: scope.$eval(scope.value)});
              });
            }
          }

          if (attrs.ngDragStop) {
            $timeout(function(){
              onDragStopCallback(scope, {$data: obj.data, $event: obj});
            });
          }

          updateDragStyles(false, obj.element);
        };

        var isTouching = function(mouseX, mouseY, dragElement) {
          var touching= hitTest(mouseX, mouseY);
          scope.isTouching = touching;
          if(touching){
            _lastDropTouch = element;
          }
          updateDragStyles(touching, dragElement);
          return touching;
        };

        var updateDragStyles = function(touching, dragElement) {
          if(touching){
            element.addClass('drag-enter');
            dragElement.addClass('drag-over');
          }else if(_lastDropTouch == element){
            _lastDropTouch=null;
            element.removeClass('drag-enter');
            dragElement.removeClass('drag-over');
          }
        };

        var hitTest = function(x, y) {
          var bounds = element[0].getBoundingClientRect();// ngDraggable.getPrivOffset(element);
          x -= $document[0].body.scrollLeft + $document[0].documentElement.scrollLeft;
          y -= $document[0].body.scrollTop + $document[0].documentElement.scrollTop;
          return x >= bounds.left
            && x <= bounds.right
            && y <= bounds.bottom
            && y >= bounds.top;
        };

        initialize();
      }
    };
  }])
  .directive('ngDragClone', ['$parse', '$timeout', 'ngDraggable', function ($parse, $timeout, ngDraggable) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        var img, _allowClone=true;
        var _dragOffset = null;
        scope.clonedData = {};
        var initialize = function () {

          img = element.find('img');
          element.attr('draggable', 'false');
          img.attr('draggable', 'false');
          reset();
          toggleListeners(true);
        };


        var toggleListeners = function (enable) {
          // remove listeners

          if (!enable)return;
          // add listeners.
          scope.$on('draggable:start', onDragStart);
          scope.$on('draggable:move', onDragMove);
          scope.$on('draggable:end', onDragEnd);
          preventContextMenu();

        };
        var preventContextMenu = function() {
          // element.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_);
          img.off('mousedown touchstart touchmove touchend touchcancel', absorbEvent_);
          // element.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_);
          img.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_);
        };
        var onDragStart = function(evt, obj, elm) {
          _allowClone=true;
          if(angular.isDefined(obj.data.allowClone)){
            _allowClone=obj.data.allowClone;
          }
          if(_allowClone) {
            scope.$apply(function () {
              scope.clonedData = obj.data;
            });
            element.css('width', obj.element[0].offsetWidth);
            element.css('height', obj.element[0].offsetHeight);

            moveElement(obj.tx, obj.ty);
          }

        };
        var onDragMove = function(evt, obj) {
          if(_allowClone) {

            _tx = obj.tx + obj.dragOffset.left;
            _ty = obj.ty + obj.dragOffset.top;

            moveElement(_tx, _ty);
          }
        };
        var onDragEnd = function(evt, obj) {
          //moveElement(obj.tx,obj.ty);
          if(_allowClone) {
            reset();
          }
        };

        var reset = function() {
          element.css({left:0,top:0, position:'fixed', 'z-index':-1, visibility:'hidden'});
        };
        var moveElement = function(x,y) {
          element.css({
            transform: 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)', 'z-index': 99999, 'visibility': 'visible',
            '-webkit-transform': 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, '+x+', '+y+', 0, 1)',
            '-ms-transform': 'matrix(1, 0, 0, 1, '+x+', '+y+')'
            //,margin: '0' don't monkey with the margin,
          });
        };

        var absorbEvent_ = function (event) {
          var e = event;//.originalEvent;
          e.preventDefault && e.preventDefault();
          e.stopPropagation && e.stopPropagation();
          e.cancelBubble = true;
          e.returnValue = false;
          return false;
        };

        initialize();
      }
    };
  }])
  .directive('ngPreventDrag', ['$parse', '$timeout', function ($parse, $timeout) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        var initialize = function () {

          element.attr('draggable', 'false');
          toggleListeners(true);
        };


        var toggleListeners = function (enable) {
          // remove listeners

          if (!enable)return;
          // add listeners.
          element.on('mousedown touchstart touchmove touchend touchcancel', absorbEvent_);
        };


        var absorbEvent_ = function (event) {
          var e = event.originalEvent;
          e.preventDefault && e.preventDefault();
          e.stopPropagation && e.stopPropagation();
          e.cancelBubble = true;
          e.returnValue = false;
          return false;
        };

        initialize();
      }
    };
  }])
  .directive('ngCancelDrag', [function () {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        element.find('*').attr('ng-cancel-drag', 'ng-cancel-drag');
      }
    };
  }])
  .directive('ngDragScroll', ['$window', '$interval', '$timeout', '$document', '$rootScope', function($window, $interval, $timeout, $document, $rootScope) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        var intervalPromise = null;
        var lastMouseEvent = null;

        var config = {
          verticalScroll: attrs.verticalScroll || true,
          horizontalScroll: attrs.horizontalScroll || true,
          activationDistance: attrs.activationDistance || 75,
          scrollDistance: attrs.scrollDistance || 15
        };


        var reqAnimFrame = (function() {
          return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame ||
            function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
              window.setTimeout(callback, 1000 / 60);
            };
        })();

        var animationIsOn = false;
        var createInterval = function() {
          animationIsOn = true;

          function nextFrame(callback) {
            var args = Array.prototype.slice.call(arguments);
            if(animationIsOn) {
              reqAnimFrame(function () {
                $rootScope.$apply(function () {
                  callback.apply(null, args);
                  nextFrame(callback);
                });
              })
            }
          }

          nextFrame(function() {
            if (!lastMouseEvent) return;

            var viewportWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
            var viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

            var scrollX = 0;
            var scrollY = 0;

            if (config.horizontalScroll) {
              // If horizontal scrolling is active.
              if (lastMouseEvent.clientX < config.activationDistance) {
                // If the mouse is on the left of the viewport within the activation distance.
                scrollX = -config.scrollDistance;
              }
              else if (lastMouseEvent.clientX > viewportWidth - config.activationDistance) {
                // If the mouse is on the right of the viewport within the activation distance.
                scrollX = config.scrollDistance;
              }
            }

            if (config.verticalScroll) {
              // If vertical scrolling is active.
              if (lastMouseEvent.clientY < config.activationDistance) {
                // If the mouse is on the top of the viewport within the activation distance.
                scrollY = -config.scrollDistance;
              }
              else if (lastMouseEvent.clientY > viewportHeight - config.activationDistance) {
                // If the mouse is on the bottom of the viewport within the activation distance.
                scrollY = config.scrollDistance;
              }
            }



            if (scrollX !== 0 || scrollY !== 0) {
              // Record the current scroll position.
              var currentScrollLeft = ($window.pageXOffset || $document[0].documentElement.scrollLeft);
              var currentScrollTop = ($window.pageYOffset || $document[0].documentElement.scrollTop);

              // Remove the transformation from the element, scroll the window by the scroll distance
              // record how far we scrolled, then reapply the element transformation.
              var elementTransform = element.css('transform');
              element.css('transform', 'initial');

              $window.scrollBy(scrollX, scrollY);

              var horizontalScrollAmount = ($window.pageXOffset || $document[0].documentElement.scrollLeft) - currentScrollLeft;
              var verticalScrollAmount = ($window.pageYOffset || $document[0].documentElement.scrollTop) - currentScrollTop;

              element.css('transform', elementTransform);

              lastMouseEvent.pageX += horizontalScrollAmount;
              lastMouseEvent.pageY += verticalScrollAmount;

              $rootScope.$emit('draggable:_triggerHandlerMove', lastMouseEvent);
            }

          });
        };

        var clearInterval = function() {
          animationIsOn = false;
        };

        scope.$on('draggable:start', function(event, obj) {
          // Ignore this event if it's not for this element.
          if (obj.element[0] !== element[0]) return;

          if (!animationIsOn) createInterval();
        });

        scope.$on('draggable:end', function(event, obj) {
          // Ignore this event if it's not for this element.
          if (obj.element[0] !== element[0]) return;

          if (animationIsOn) clearInterval();
        });

        scope.$on('draggable:move', function(event, obj) {
          // Ignore this event if it's not for this element.
          if (obj.element[0] !== element[0]) return;

          lastMouseEvent = obj.event;
        });
      }
    };
  }]);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
使用jQuery模板来展现json数据的代码
Oct 22 Javascript
使用AmplifyJS组件配合JavaScript进行编程的指南
Jul 28 Javascript
jQuery焦点图切换特效代码分享
Sep 15 Javascript
jQuery通用的全局遍历方法$.each()用法实例
Jul 04 Javascript
Javascript typeof与instanceof的区别
Oct 18 Javascript
vue项目中做编辑功能传递数据时遇到问题的解决方法
Dec 19 Javascript
从零开始做一个pagination分页组件
Mar 15 Javascript
jquery基于layui实现二级联动下拉选择(省份城市选择)
Jun 20 jQuery
JS实现标签滚动切换效果
Dec 25 Javascript
vue实现短信验证码登录功能(流程详解)
Dec 10 Javascript
深入webpack打包原理及loader和plugin的实现
May 06 Javascript
Vue实现指令式动态追加小球动画组件的步骤
Dec 18 Vue.js
深究AngularJS中$sce的使用
Jun 12 #Javascript
JS身份证信息验证正则表达式
Jun 12 #Javascript
用原生JS实现简单的多选框功能
Jun 12 #Javascript
Angularjs 双向绑定时字符串的转换成数字类型的问题
Jun 12 #Javascript
微信小程序 es6-promise.js封装请求与处理异步进程
Jun 12 #Javascript
AngularJS 异步解决实现方法
Jun 12 #Javascript
jquery+css实现侧边导航栏效果
Jun 12 #jQuery
You might like
PHP发明人谈MVC和网站设计架构 貌似他不支持php用mvc
2011/06/04 PHP
php实现12306火车票余票查询和价格查询(12306火车票查询)
2014/01/14 PHP
php对象和数组相互转换的方法
2015/05/12 PHP
php读取torrent种子文件内容的方法(测试可用)
2016/05/03 PHP
js apply/call/caller/callee/bind使用方法与区别分析
2009/10/28 Javascript
Javascript 设计模式(二) 闭包
2010/05/26 Javascript
使用node.js 制作网站前台后台
2014/11/13 Javascript
JavaScript实现文字与图片拖拽效果的方法
2015/02/16 Javascript
使用Vue.js创建一个时间跟踪的单页应用
2016/11/28 Javascript
Bootstrap和Java分页实例第二篇
2016/12/23 Javascript
webpack入门+react环境配置
2017/02/08 Javascript
不得不知的ES6小技巧
2018/07/28 Javascript
vue+element-ui集成随机验证码+用户名+密码的form表单验证功能
2018/08/05 Javascript
Vue scrollBehavior 滚动行为实现后退页面显示在上次浏览的位置
2019/05/27 Javascript
jQuery擦除插件eraser使用方法详解
2020/01/11 jQuery
JS如何监听div的resize事件详解
2020/12/03 Javascript
[28:05]完美世界DOTA2联赛循环赛Inki vs DeMonsTer 第一场 10月30日
2020/10/31 DOTA
Python自动化测试工具Splinter简介和使用实例
2014/05/13 Python
Python cx_freeze打包工具处理问题思路及解决办法
2016/02/13 Python
matplotlib绘制动画代码示例
2018/01/02 Python
python抓取网站的图片并下载到本地的方法
2018/05/22 Python
使用Python为中秋节绘制一块美味的月饼
2019/09/11 Python
Python3爬虫关于代理池的维护详解
2020/07/30 Python
全球酒店比价网:HotelsCombined
2017/06/20 全球购物
Foot Locker德国官方网站:美国运动服和鞋类零售商
2018/11/01 全球购物
平面设计师工作职责范文
2013/12/03 职场文书
英语自荐信范文
2013/12/11 职场文书
大家访活动实施方案
2014/03/10 职场文书
《长江之歌》教学反思
2014/04/17 职场文书
教师师德演讲稿
2014/05/06 职场文书
精神文明建设先进个人事迹材料
2014/12/24 职场文书
司机岗位职责范本
2015/04/10 职场文书
公司年会晚会开幕词
2019/04/02 职场文书
导游词之西安大清真寺
2019/12/17 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL
WinServer2012搭建DNS服务器的方法步骤
2022/06/10 Servers