23

我要从 Knockout 转到 Angular,但我遇到了一些问题。我假设我必须做一些非角度类型的事情。

http://jsfiddle.net/LostInDaJungle/BxELP/

I linked to jsfiddle so I didn't have to include my code here
Stack Overflow will not let me post my question without a code block.

这是一个非常基本的小提琴,概述了我的两个主要问题......

问题1:val1和val2被初始化为3和4,正确加起来为7。但是,如果您更改文本框中的任何一个值,则新值将被视为字符串,我会得到连接而不是加法。将 val1 更改为 4,当它应该是 8 时你得到 44。解决这种行为的最佳方法是什么?

问题 2:计算字段。我可以通过使用 {{val1 + val2}} 之类的大括号来获得计算字段,并在基础模型更改时自动更新计算字段,但这是完全不可接受的。在我成熟的应用程序中,我们生成了一个在整个过程中多次使用的“成本”,并且每次都必须进行成本计算是一种痛苦。更不用说当这个计算发生变化时,我现在有一项令人羡慕的任务,即找到 15 个使用成本计算的不同地方并将它们全部更新。

此外,如果我尝试使用大括号将 ng-model="cost" 放在输入上,则大括号不起作用。因此,我没有什么可以作为约束成本的方式。

http://jsfiddle.net/LostInDaJungle/QNVwe/

这个例子更像我想要的结构。但是,与 ko.observable 不同的是,计算字段不会在生成它们的值更改时更新。每个人都强加给我的样板解决方案是编写一堆 ng-change 处理程序......但这太糟糕了。如果宽度变化改变了成本并改变了回报计算,等等......它很快就会变成一团糟。

就将逻辑与表示分离而言,这两种方法都失败了。方法一将我的业务逻辑嵌入到我的 HTML 中。方法二在我的代码中放置了一大堆 ng-change 处理程序,这与必须用普通的 HTML 编写一大堆 onChange 处理程序没有太大区别。如果我必须做一堆 ng-change 处理程序,我会尽快在 Javascript 中做一个 onChange 处理程序,因为我至少可以在我的表示层之外声明它们。

这是相同的淘汰版:

http://jsfiddle.net/LostInDaJungle/eka4S/2/

这更像我所期望的......除了我的输入上的数据绑定,所有程序逻辑都很好地包含在视图模型中。此外,由于我的可计算是一个 Javascript 函数,我不必为如何确保我的两个值是数字而挠头。

所以....

计算变量:有没有办法观察基础变量并自动更新计算量?无需将我的程序逻辑隐藏在我的 HTML 中?

有什么好方法可以防止我的数字变成字符串吗?

谢谢您的帮助。

仅供参考,也发布到 Google 群组:https ://groups.google.com/forum/#!topic/angular/0dfnDTaj8tw

4

7 回答 7

31

对于计算字段,将方法添加到您的控制器。. .

$scope.cost = function() { return $scope.val1 + $scope.val2 };

然后直接绑定到它。当其组成值发生变化时,它将知道何时需要重新计算。

<div>{{cost()}}</div>
于 2013-06-18T16:10:18.620 回答
13

好的,

几个小时后,我想我有了答案。

使用 $scope.$watch。

$scope.$watch('(height * width) * 40', function(v) {$scope.cost = v;});

或者

$scope.$watch('height + width', function() {$scope.cost = (Number(height) * Number(width)) * 40;});

这会自动更新监视变量的任何可计算值。它给了我一种方法来处理这些,而不必住在花括号里。

此外,计算值可以被重用和跟踪以进行级联更新:

$scope.$watch('height * width', function(v) {$scope.dim = v;});
$scope.$watch('dim * 40', function(v) {$scope.cost = v;});

因此,如果高度和/或宽度发生变化,则会更新 dim,并且由于 dim 已更改,因此会更新成本。

于 2013-06-18T17:27:08.100 回答
6

我将您的第三个输入更改为:

<input type="text" value="{{val1 * 1 + val2}}" />

这导致 Angular.js 将值视为数字,而不是字符串。

这是小提琴我从这里收集了答案。

于 2013-06-18T16:22:59.190 回答
2

关于问题1:

如果可能,您应该使用 input type="number"。这将负责正确解析数字。即使您使用较旧的浏览器,角度也会将它们格式化为数字。

关于问题2:

如果您只需要在屏幕上显示纯文本,那么您的答案是好的 Jason。但是,如果您想将带有模型的输入绑定到任意表达式,则需要其他内容。

我编写了一个指令,您可以使用它来将 ng-model 绑定到您想要的任何表达式。每当表达式更改时,模型都会设置为新值。

module.directive('boundModel', function() {
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ngModel) {
      scope.$watch(attrs.boundModel, function(newValue, oldValue) {
        if(newValue != oldValue) {
          ngModel.$setViewValue(newValue);
          ngModel.$render();
        }
      });
    }
  };
})

您可以像这样在模板中使用它:

<input type="text" ng-model="total" bound-model="value1 + value2">

或者像这样:

<input type="text" ng-model="total" bound-model="cost()">

其中 cost() 是作用域的一个简单函数,如下所示:

$scope.cost = function() { return $scope.val1 + $scope.val2 };

好消息是您继续使用模型进行输入,并且不必动态更新 value 属性,这在 angular 中效果不佳。

于 2015-05-06T12:46:02.520 回答
0

你可以绑定到一个函数

function CTRL ($scope) {
$scope.val1 = 3;
$scope.val2 = 4;
$scope.sum = function(){
   return ($scope.val1 *1 + $scope.val2 *1);
};

}

它的工作方式与绑定表达式的工作方式相同,但在更复杂的情况下,我们需要函数

于 2014-05-31T14:18:25.837 回答
0

我是 AngularJS 的新手,但我认为可以使用 $parse:

http://docs.angularjs.org/api/ng/service/ $parse

如果您将表达式作为字符串,这很有趣。您可以使用属性路径,并且可以动态生成该字符串。如果您在编译时不知道表达式,这很有效,很像 eval() 但可能更快,也许更安全(?)。

这是一个例子:

function Ctrl($scope,$parse) {
  var expression = 'model.val1 + model.val2';//could be dynamically created
  $scope.model = {
    val1: 0,
    val2: 0,
    total: function() { 
        return ($parse(expression))($scope); 
    }
  };
}
于 2014-04-15T19:56:54.547 回答
0

在我看来,通过 $scope 变量提供的 $watch 函数最适合这项工作。

$scope.$watch(function(scope) { return scope.data.myVar },
              function(newValue, oldValue) {
                  document.getElementById("myElement").innerHTML =
                      "" + newValue + "";
              }
             );

$watch 函数接受一个:值函数和一个监听器函数

上面的例子取自这篇很棒的文章:http ://tutorials.jenkov.com/angularjs/watch-digest-apply.html

通读后,我学到了很多东西,并且能够实现我正在寻找的解决方案。

于 2015-09-03T07:35:11.837 回答