【发布时间】:2014-06-17 03:26:18
【问题描述】:
用例
我在一个页面上有一组控件,大约 60 多个。每个控件都会评估一个字符串表达式,以根据在表单本身中输入的数据来决定是否禁用该控件。表达式是由最终用户创建的,所以它可以是任何东西。
我遇到的问题是表单和评估相当复杂,并且会减慢 UI。最终代码将包含需要在作用域对象中查找数据的表达式,并将包含循环等...
演示
这是一个jsfiddle 来模拟我正在尝试改进的内容。它不是最终代码,因为该模块相当大。但是,这应该可以说明我正在尝试实现(或减少)什么。这个演示速度很快,因为表达式相当简单,但我希望能够减少调用函数is 的次数。
[edit] 我已经更新了演示,以尽可能多地包含最终生产代码的核心逻辑。这与将要完成的目标一样接近。
模板
<div ng-app ng-controller="ctrl">
<div ng-repeat="widget in widgets">
<label>Widget #{{$index}}
<input type="text" ng-model="widget.value"
ng-disabled="is(widget.expression)" />
</label>
</div>
</div>
控制器
var ctrl = function ($scope) {
$scope.widgets = [];
/** Core Logic Below Here **/
var getValueByName = function (name) {
for (i = 0, k = $scope.widgets.length; i < k; i++) {
if ($scope.widgets[i].name == name) {
return $scope.widgets[i].value;
}
}
return 0;
};
var replaceNameWithValue = function () {
var result = this.replace(/( |^)(widget_\d+?)( |$)/g, function ($0, $1, $2, $3) {
return parseInt(getValueByName($2), 10);
});
return result;
};
$scope.is = function (expression) {
console.log('firing');
try {
var exp = replaceNameWithValue.call(expression);
return $scope.$eval(exp);
} catch (e) {}
return false;
};
/** Logic to generate random test cases **/
var numWidgets = 60;
var operators = ['+', '-', '*'];
var comparators = ['===', '!==', '>', '<', '>=', '<='];
var getRandomInt = function (max) {
return Math.floor(Math.random() * max);
};
var makeExpression = function () {
var a = getRandomInt(numWidgets);
var b = getRandomInt(numWidgets);
var c = getRandomInt(20);
var op = operators[getRandomInt(operators.length)];
var cf = comparators[getRandomInt(comparators.length)];
return {
expression: ['widget_' + a, op, 'widget_' + b, cf, c].join(' ')
};
};
var makeRandomObject = function (index) {
var obj = makeExpression();
obj.name = "widget_" + index;
obj.value = 0;
return obj;
};
var preLoad = function (numWidgets) {
for (i = 0; i < numWidgets; i++) {
$scope.widgets.push(makeRandomObject(i));
}
};
preLoad(numWidgets);
};
问题
如何提高这些评估的性能?
解决方案?
我注意到评估是在 keyUp 事件上执行的。我怀疑我不能使用本机 ng-disabled 并且必须创建一个触发模糊事件的指令,但我想看看还有什么其他想法可用。
【问题讨论】:
-
使用 AngularJs 的最新 1.3 版本,您可以为 ng-model-options 设置 debounce 值,这将延迟模型更新(进而调用 ng-disabled)直到设定的时间段之后。 See this answer
-
@JoseM 在另一个 Fiddle 中的建议:jsfiddle.net/marcolepsy/rXuHd/1 这要简单得多,但我将原始答案留作另一种方法参考
标签: javascript angularjs