我正在使用isolate scope(angular)和Jasmine测试框架测试一个指令。一切都工作正常,有一个奇怪的地方:如果我将$ scope上的变量类型从字符串更改为数字,Jasmine继续将其视为字符串,即使指令代码本身正确地将其视为数字。
我理解为什么这可能具有直观意义 - parm最初作为字符串插入,也许Angular有一些机制来确保它保持字符串。如果是的话,我不知道它在Angular源中的实现方式和位置(甚至可能是它)。
总之:为什么Jasmine会看到一个字符串而指令会看到一个数字?
这是我的代码:
标记
<pane id={{myId}}></pane>
指令
.directive('testPane', function () {
function thisController($scope) {
//$scope.id is string '1'
$scope.id = parseInt($scope.id);
//now it is number 1 (as expected)
console.log($scope.id);
};
return {
restrict: 'E',
transclude: true,
scope: { id: '@'},
controller: thisController,
link: function (scope, element, attrs, tabsController) {
},
templateUrl: 'test/test.html',
replace: true
};
})
Jasmine Spec
it("changes id from string to number", function () {
var element,
elementScope;
$rootScope.myId = 1;
element = $compile(html)($rootScope);
$timeout(function () {
businessTabScope = element.isolateScope();
$rootScope.$digest();
expect(elementScope.id).toBeDefined();
//id is text '1' instead of number 1. Why?
expect(elementScope.id).toEqual($rootScope.myId);
}, 0, false);
$timeout.flush();
});
答案 0 :(得分:1)
<强>问题强>
当您定义@
绑定时,Angular会为该属性创建一个观察者,以便在该属性稍后更改时更新本地属性的值。您可以在第7676行(Angular 1.3.15)找到该特定代码:
case '@':
attrs.$observe(attrName, function(value) {
isolateBindingContext[scopeName] = value;
});
...
现在让我们看看$observe
对id
所说的内容(强调我的):
观察插值属性。
观察者函数将在下一个$摘要期间调用一次 编译后。然后每当调用观察者时 插值变化。
在编译指令之后,即在执行控制器和链接函数之后,观察者保证被调用一次。并且由于您要为控制器函数中的id
属性分配一个新值,它会被覆盖回原始值 - 这是一个字符串,因为它是一个DOM属性。
<强>解决方案强>
根据您发布的代码,您似乎只关心.directive('testPane', function () {
return {
...
scope: {},
controller: function($scope, $attrs) {
$scope.id = parseInt($attrs.id, '10');
}
};
});
第一个值。要抓住它,您只需执行以下操作:
@
如果需要,您可以继续使用/recommendation/thetitle
绑定,但要确保转换后的值存储在作用域的另一个属性中,以便在编译指令或稍后编译时不会覆盖它。