【问题标题】:AngularJS digest inside a function函数内部的AngularJS摘要
【发布时间】:2016-08-10 15:50:26
【问题描述】:

假设我有以下 HTML

<div ng-if="running">
    <div id="someid"></div>
</div>
<span ng-click="myfunc">Click</span>

在角度控制器中,我在单击按钮时设置了一个功能

$scope.myfunc = function(){
    $scope.running = true;

    //attach some jquery event
    $('#someid').on('animationend', function(){...})
}

我想在running=true 之后立即更新 DOM,因为如果我不这样做或将附加的事件放在其他地方,它就不起作用,因为 DOM 还不存在。 ng-if 似乎将其删除,并且仅在函数结束时才显示 div。我在运行后立即尝试$scope.$digest() 也不起作用,它显示错误。

那么附加上述事件的正确方法是什么?

【问题讨论】:

  • 看起来指令可以解决这个问题 - 我会阅读有关 Angular 指令以及如何操作元素并将事件附加到它的内容 :)
  • 如果您愿意,可以查看我的带有 Angular 指令的示例。

标签: javascript jquery angularjs events


【解决方案1】:

尝试在你的控制器中使用 $timeout,这样:

    myApp.controller('exampleController', ['$scope', '$timeout', function($scope, $timeout) {

                $scope.myfunc = function(){
                   $scope.running = true;            

                   var timeout = $timeout(function({
                     $('#someid').on('animationend', function(){...})  

                     $timeout.cancel(timeout);  
                   }, 0)
                }
            }]);

简而言之,$timeout 以 0 为间隔让您等待下一个摘要周期。

【讨论】:

  • 这是一种解决方法。请参阅我的示例,使用 Angular 指令。
【解决方案2】:
<div ng-if="running">
    <div id="someid"></div>
</div>
<span ng-click="myfunc()">Click</span>

//in controller
    $('#someid').on('animationend', function(){
     $scope.$apply(function() {
       //$scope.blabla = 'hello';
     })
    });

$scope.myfunc = function(){
    $scope.running = true;
}

但是你应该做一个指令

编辑:

var app = angular.module('myApp', []);

app.directive('startAnimate', function () {
	return {
		scope: {
			startAnimate: '@', //animation name (string)
			seconds: '@', //duration in seconds (int)
			startOnCreation: '=?', //start on creation of element (boolean) - optional
			onAnimationEnd: '=?', //callback at end - optional
			workspace: '=?' //create an object to allow two-way data binding with primitive values (boolean, int, ...) - optional
		},
		link: function (scope, element, attributes) {
			var animation = scope.startAnimate + ' ' + scope.seconds + 's';

			if (!scope.workspace) {
				scope.workspace = {};
			}

			scope.workspace.running = false;

			var setElementSAnimation = function (animation) {
				element.css({
					WebkitAnimation: animation,
					animation: animation
				});
			}

			var startAnimation = function () {
				setElementSAnimation(animation);

				scope.workspace.running = true;
			}

			if (scope.startOnCreation) {
				startAnimation();
			}

			element.click(function () {
				scope.$apply(function () {
					startAnimation();
				});
			});

			if (!scope.onAnimationEnd) {
				scope.onAnimationEnd = function () { };
			}

			var oldAnimationEnd = scope.onAnimationEnd;

			scope.onAnimationEnd = function () {
				oldAnimationEnd();

				//clean animation to allow to repeat it
				setElementSAnimation('');

				scope.$apply(function () {
					scope.workspace.running = false;
				})
			};

			element.on("webkitAnimationEnd animationend", scope.onAnimationEnd);
		}
	}
});

app.controller('myCtrl', function ($scope) {
	$scope.myfunc = function () {
		alert('finish');
	}

	$scope.showElement = false;

	$scope.workspace = {
		running: false
	}
});
#myDIV {
	width: 100px;
	height: 100px;
	background: orange;
	position: relative;
}

@-webkit-keyframes mymove {
	from {
		top: 0px;
		left: 0px;
	}

	to {
		top: 80px;
		left: 160px;
	}
}

@keyframes mymove {
	from {
		top: 0px;
		left: 0px;
	}

	to {
		top: 80px;
		left: 160px;
	}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div data-ng-app="myApp" data-ng-controller="myCtrl">
	<div data-ng-if="workspace.running">
		Yes, it's running!
	</div>

	<div id="myDIV" data-ng-if="showElement" data-start-animate="mymove" data-start-on-creation="true" data-seconds="4" data-on-animation-end="myfunc" data-workspace="workspace">
		<span>Click me to start the animation.</span>
	</div>

	<button type="button" data-ng-click="showElement = !showElement">Toggle element</button>
</div>

【讨论】:

  • $('#someid') 不存在,因为ng-if 从 DOM 中删除该 div
  • “但是你应该做一个指令”我在去年八月回答。抱歉耽搁了,现在我向您展示了正确的方法。
  • 与接受的答案相比,代码太多了......尝试一下
  • 接受的答案是一种解决方法,是不好的做法。您必须看到的代码是html代码。该指令是可重用的。 data-start-animate="mymove" data-start-on-creation="true" data-seconds="4" data-on-animation-end="myfunc" data-workspace="workspace"
猜你喜欢
  • 2016-08-13
  • 2015-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
相关资源
最近更新 更多