Javascript AngularJs$双路绑定手表
我正在创建一个页面,其中有范围滑块,根据它们的设置相互影响。我有一个如下所示的手表功能,它是单向工作的,但是我希望两种方式都有手表效果,但我不知道是否有一种方法可以做到这一点,而不为每个值创建一个(大约有12个滑块) 下面是一个Plunker,概述了我要做的事情:Javascript AngularJs$双路绑定手表,javascript,angularjs,Javascript,Angularjs,我正在创建一个页面,其中有范围滑块,根据它们的设置相互影响。我有一个如下所示的手表功能,它是单向工作的,但是我希望两种方式都有手表效果,但我不知道是否有一种方法可以做到这一点,而不为每个值创建一个(大约有12个滑块) 下面是一个Plunker,概述了我要做的事情: 我相信这就是你想要的 $scope.watchList = [$scope.item1, $scope.item2]; $scope.$watchCollection('watchList', function(newValues){
我相信这就是你想要的
$scope.watchList = [$scope.item1, $scope.item2];
$scope.$watchCollection('watchList', function(newValues){...});
这样,您就可以在同一块表中查看所有滑块范围变量。我相信这就是您想要的
$scope.watchList = [$scope.item1, $scope.item2];
$scope.$watchCollection('watchList', function(newValues){...});
这样,您就可以在同一块表中查看所有滑块范围变量。我相信这就是您想要的
$scope.watchList = [$scope.item1, $scope.item2];
$scope.$watchCollection('watchList', function(newValues){...});
这样,您就可以在同一块表中查看所有滑块范围变量。我相信这就是您想要的
$scope.watchList = [$scope.item1, $scope.item2];
$scope.$watchCollection('watchList', function(newValues){...});
这样,您就可以在同一块表中查看所有滑块范围变量。我想出了三种不同的方法来实现计算值的双向绑定。我只为
assets
滑块编写了解决方案,而没有为roa
滑块编写解决方案,因为我assets
是一个基本总和,roa
是另外一个东西。(@flashpunk:如果你在这方面需要更多帮助,请解释。)这之所以困难的关键问题是,在javascript中,数字不是以精确的10进制格式表示的;当遇到这种不精确性损失时,angular将进入无限循环,根据不精确性引起的更改重新计算更改
换句话说,问题是数值计算是有损的,如果计算是无损的,这些问题就不会发生
这是我的第一个解决方案。它使用(脆弱的)锁定机制根据更改的值切换规范数据源。为了使这个解决方案更加健壮,我将创建一个角度模块,扩展范围
,以允许更高级、更复杂的观察者。如果我将来遇到这个问题,我可能会在github上启动一个项目;如果我这样做的话,我会修改这个答案
// Both of these functions can be replaced with library functions from lodash or underscore, etc.
var sum = function(array) { return array.reduce(function(total, next) { return total + (+next); }, 0) };
var closeTo = function(a, b, threshold) { return a == b || Math.abs(a - b) <= threshold; };
$scope.sliders = [
$scope.slide1 = {
assets: 10,
roa: 20
}, ... ];
$scope.mainSlide = {
assets: 0,
roa: 0
};
// you might want to make or look for a helper function to control this "locking"
// in a better fashion, that integrates and resets itself with the digest cycle
var modifiedMainAssets = false;
var modifiedCollectionAssets = false;
$scope.$watch(function() {
return sum($scope.sliders.map(function(slider) { return slider.assets; }))
}, function(totalAssets) {
if (modifiedCollectionAssets) { modifiedCollectionAssets = false; return; }
$scope.mainSlide.assets = totalAssets;
modifiedMainAssets = true;
});
$scope.$watch('mainSlide.assets', function(totalAssets, oldTotalAssets) {
if (modifiedMainAssets) { modifiedMainAssets = false; return; }
if (oldTotalAssets === null || closeTo(totalAssets, oldTotalAssets, 0.1)) { return; }
// NOTE: has issues with floating point math. either round & accept the failures,
// or use a library that supports a proper IEEE 854 decimal type
var incrementAmount = (totalAssets - oldTotalAssets) / $scope.sliders.length;
angular.forEach($scope.sliders, function(slider) { slider.assets += incrementAmount; });
modifiedCollectionAssets = true;
});
这可能是我首先应该提出的建议。有一个规范的数据源,它们是单独的滑块。对于主滑块,创建一个自定义滑块指令,该指令不具有ng模型,而是触发报告所做更改的事件。(您可以通过包装或分叉现有指令来执行此操作。)
修订版html:
Assets: <span ng-bind="mainSlide.assets"></span>
<button ng-click="modifyAll(1)">Up</button>
<button ng-click="modifyAll(-1)">Down</button>
资产:
向上的
向下
复习
这似乎是angular团队尚未解决的问题。基于事件的数据绑定系统(knockout、ember和backbone中使用的)将通过简单地不对特定的有损计算更改触发更改事件来解决这个问题;在angular的例子中,需要对摘要循环进行一些调整。我不知道我的前两个解决方案是否是米斯科或另一位有棱角的大师所建议的,但它们是有效的
现在,我更喜欢方法3。如果这不能让你满意,使用方法2,并清理它;但是使用无损十进制或分数表示,而不是内置的javascript数字类型(如此或) 我想出了三种不同的方法来实现计算值的双向绑定。我只为
assets
滑块编写了解决方案,而没有为roa
滑块编写解决方案,因为我assets
是一个基本总和,roa
是另外一个东西。(@flashpunk:如果你在这方面需要更多帮助,请解释。)这之所以困难的关键问题是,在javascript中,数字不是以精确的10进制格式表示的;当遇到这种不精确性损失时,angular将进入无限循环,根据不精确性引起的更改重新计算更改
换句话说,问题是数值计算是有损的,如果计算是无损的,这些问题就不会发生
这是我的第一个解决方案。它使用(脆弱的)锁定机制根据更改的值切换规范数据源。为了使这个解决方案更加健壮,我将创建一个角度模块,扩展范围
,以允许更高级、更复杂的观察者。如果我将来遇到这个问题,我可能会在github上启动一个项目;如果我这样做的话,我会修改这个答案
// Both of these functions can be replaced with library functions from lodash or underscore, etc.
var sum = function(array) { return array.reduce(function(total, next) { return total + (+next); }, 0) };
var closeTo = function(a, b, threshold) { return a == b || Math.abs(a - b) <= threshold; };
$scope.sliders = [
$scope.slide1 = {
assets: 10,
roa: 20
}, ... ];
$scope.mainSlide = {
assets: 0,
roa: 0
};
// you might want to make or look for a helper function to control this "locking"
// in a better fashion, that integrates and resets itself with the digest cycle
var modifiedMainAssets = false;
var modifiedCollectionAssets = false;
$scope.$watch(function() {
return sum($scope.sliders.map(function(slider) { return slider.assets; }))
}, function(totalAssets) {
if (modifiedCollectionAssets) { modifiedCollectionAssets = false; return; }
$scope.mainSlide.assets = totalAssets;
modifiedMainAssets = true;
});
$scope.$watch('mainSlide.assets', function(totalAssets, oldTotalAssets) {
if (modifiedMainAssets) { modifiedMainAssets = false; return; }
if (oldTotalAssets === null || closeTo(totalAssets, oldTotalAssets, 0.1)) { return; }
// NOTE: has issues with floating point math. either round & accept the failures,
// or use a library that supports a proper IEEE 854 decimal type
var incrementAmount = (totalAssets - oldTotalAssets) / $scope.sliders.length;
angular.forEach($scope.sliders, function(slider) { slider.assets += incrementAmount; });
modifiedCollectionAssets = true;
});
这可能是我首先应该提出的建议。有一个规范的数据源,它们是单独的滑块。对于主滑块,创建一个自定义滑块指令,该指令不具有ng模型,而是触发报告所做更改的事件。(您可以通过包装或分叉现有指令来执行此操作。)
修订版html:
Assets: <span ng-bind="mainSlide.assets"></span>
<button ng-click="modifyAll(1)">Up</button>
<button ng-click="modifyAll(-1)">Down</button>
资产:
向上的
向下
复习
这似乎是angular团队尚未解决的问题。基于事件的数据绑定系统(knockout、ember和backbone中使用的)将通过简单地不对特定的有损计算更改触发更改事件来解决这个问题;在angular的例子中,需要对摘要循环进行一些调整。我不知道我的前两个解决方案是否是米斯科或另一位有棱角的大师所建议的,但它们是有效的
现在,我更喜欢方法3。如果这不能让你满意,使用方法2,并清理它;但是使用无损十进制或分数表示,而不是内置的javascript数字类型(如此或) 我想出了三种不同的方法来实现计算值的双向绑定。我只为
assets
滑块编写了解决方案,而没有为roa
滑块编写解决方案,因为我assets
是一个基本总和,roa
是另外一个东西。(@flashpunk:如果你在这方面需要更多帮助,请解释。)这之所以困难的关键问题是,在javascript中,数字不是以精确的10进制格式表示的;当这种不精确的损失