在Angular中,一个关键特性是双向绑定,它使模型始终保持最新。但是,我有一种情况,我有一个本质上是模型的依赖属性。我的问题是如何实现它。我可以在视图中插入一个表达式来显示依赖于模型元素的计算,但我希望将该表达式指定为模型中的一个字段,这样其他表达式就可以使用该结果,并且所有内容都可以很好地更新。
一个简单的示例可能在模型中包含字段 a , b 和 c , c = a * b < / strong>即可。可以将{{a * b}}
添加到视图中,但是我更喜欢 c 的字段,以便我可以引用 c 其他表达式只需在我需要显示的视图中使用{{c}}
,只要 a 或 b 更新, c 就会更新。
我猜你可以看一下 a 和 b 并重新计算 c ,但似乎机器已经在Angular的某个地方了自动完成,因为它适用于视图中的表达式。如果我不提前知道表达式(并且我不会),我需要解析 c 的表达式来取出变量并设置监视所有这些......肯定和Angular有更好的方法。
可以做一些像将Angular表达式放入模型中的东西吗?
我知道这里存在危险 - 您可以创建一个自引用循环,但这样可以检测到可能会抛出错误。
答案 0 :(得分:1)
Knockout具有computeableObservable的概念,但angular没有这样的不同之处。但是你可以做类似下面的事情。当a发生变化时,它会自动改变c的值。请看下面的代码段。
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.a=5;
$scope.b=10;
$scope.c = function(){return $scope.a*$scope.b}
$scope.changea = function(){$scope.a = 25}
});
&#13;
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.13/angular.js" data-semver="1.3.13"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
{{c()}}
<input type="button" value="change a value to 25" ng-click="changea()" />
a = {{a}}
</body>
</html>
&#13;
答案 1 :(得分:1)
Kyle和Jenish在许多情况下提供了可能适当的答案,但在这方面仍存在细微差别
搜索&#39; Computed Property&#39; (感谢Jenish - 这是我需要的那个词)我发现可以消除parens(thanks to this article),但是我找不到能够挽救价值的解决方案只在需要时才更新。
可以在javascript中为对象添加属性,并且只定义一个getter,这本身就很棒,但更好,因为它适用于Angular系统。
请注意,在下面的代码段中,&#39; vars&#39; property仅用于为数学函数和我们为此特定示例向用户公开的变量提供上下文。只有Object.defineProperty(...)
对于这种一般方法至关重要。
var app = angular.module('tester', []);
app.controller('VariablesCtrl', function($scope) {
// Init context with Math for access to functions
$scope.vars = window.Math;
// Init variables
$scope.vars.a = 2;
$scope.vars.b = 3;
$scope.vars.c_expr = 'a * b';
$scope.vars.d_expr = 'pow(c , 2) + 10';
// Add dependent property to $scope for c and d, based on user input expressions
Object.defineProperty($scope.vars, 'c', {
get: function() {
return $scope.$eval($scope.vars.c_expr, $scope.vars);
}
});
Object.defineProperty($scope.vars, 'd', {
get: function() {
return $scope.$eval($scope.vars.d_expr, $scope.vars);
}
});
});
&#13;
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="tester">
<head>
<title>Angular Computed Properties</title>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="VariablesCtrl">
<p>
a:
<input type="number" ng-model="vars.a" />
</p>
<p>
b:
<input type="number" ng-model="vars.b" />
</p>
<p>
c (an expression):
<input type="text" ng-model="vars.c_expr" />
</p>
<p>
c: {{vars.c}}
</p>
<p>
d (an expression):
<input type="text" ng-model="vars.d_expr" />
</p>
<p>
d: {{vars.d}}
</p>
</div>
<script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.13/angular.js" data-semver="1.3.13"></script>
</body>
</html>
&#13;
答案 2 :(得分:1)
我认为第三种方式是真正的角度方式。
您可以对$ scope成员使用$ watch,以便在范围变量发生变化时获得回调。在最新的角度版本中,您可以在一个命令中查看变量组。
所以它会像
$scope.$watch('a', function(newValue, oldValue) {
$scope.c= newValue + $scope.b;
});
$scope.$watch('b', function(newValue, oldValue) {
$scope.c= newValue + $scope.a;
});