在我的KncokoutJS ViewModel中,我有以下计算属性:
self.SelectedUserHasRoles = ko.computed(function () {
if (self.isLoaded()) {
return self.selectedUser().roles().length > 0;
}
return false;
});
在我的HTML中,我有以下内容:
<!-- ko if: isLoaded() -->
<!-- ko if: !SelectedUserHasRoles -->
<div>
<p>User has no Roles.</p>
</div>
<!-- /ko -->
<!-- ko if: SelectedUserHasRoles -->
<div class="roles-wrapper" data-bind="foreach: $root.selectedUser().roles()">
<div class="role-token" data-bind="text: Name"></div>
</div>
<!-- /ko -->
<!-- /ko -->
在我的代码中,我是这样说的:
来自AJAX调用的数据已完成加载( isLoaded为true ),然后对于当前选定的用户,检查并查看他/她是否有任何角色即可。 如果是,那么循环播放并显示它们,如果不是,则显示一些文字说'用户没有角色'。
除了显示User has no Roles
文字摘要外,所有内容似乎都有效。我不知道为什么没有显示!我将断点放入我的计算属性中,并且可以看到当我选择没有角色的用户时,表达式(在控制台窗口中)是假的,我在否定它,所以我应该看到那个文本片段!
我做错了什么?我创建了screencast以便于理解。
答案 0 :(得分:4)
如果要在绑定中否定可观察值或计算值,则必须明确调用它:
<!-- ko if: !SelectedUserHasRoles() -->
在if
绑定的情况下,还有ifnot
对应物:
<!-- ko ifnot: SelectedUserHasRoles -->
我认为理解为什么这是有用的,因为我发现它发生了很多。
您可以将data-bind属性视为以逗号分隔的键值对字符串。淘汰赛wraps each of the values in a function,称之为valueAccessor
。
基本上,你会来自:
data-bind="if: SelectedUserHasRoles"
到
{
"if": function() { return SelectedUserHasRoles }
}
SelectedUserHasRoles
是一个可观察的实例,其评估为 truthy 。当您使用!
否定此值时,它将始终为false
。
var myObs = ko.observable("anything");
var valueAccessor = function() { return myObs; };
var valueAccessorNeg = function() { return !myObs; };
console.log(valueAccessor()); // Returns the observable
console.log(valueAccessorNeg()); // Always prints false
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
valueAccessor函数被传递给绑定的init
方法。通常,它由calling检索,然后unwrapped检索。由于unwrap
实用程序不关心您是否将observable
或普通值传递给它,因此当您犯错时 。
var myObs = ko.observable(false);
var va1 = function() { return myObs; };
var va2 = function() { return !myObs; };
var va3 = function() { return !myObs(); };
console.log(ko.unwrap(va1())); // false
console.log(ko.unwrap(va2())); // always false
console.log(ko.unwrap(va3())); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
我希望这个小小的窥视可能会帮助你(和那些犯了这个错误的人)能够确定将来需要()
的时间。
答案 1 :(得分:1)
因为您没有绑定到变量而是绑定到表达式,所以需要在此处添加括号:
<!-- ko if: !SelectedUserHasRoles() -->
//^^ here
请参阅以下代码段
function CreateVM() {
var self = this;
this.isTrue = ko.observable(false);
this.selectedUser = ko.observable();
this.isLoaded = ko.observable();
self.SelectedUserHasRoles = ko.computed(function () {
if (self.isLoaded()) {
return self.selectedUser().roles().length > 0;
}
return false;
});
}
var vm = new CreateVM();
ko.applyBindings(vm);
var userWithRoles = { roles: ko.observableArray([1,2]) };
var userWithoutRoles = { roles: ko.observableArray([]) };
vm.selectedUser(userWithoutRoles);
vm.isLoaded(true);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko if: isLoaded() -->
<!-- ko if: !SelectedUserHasRoles() -->
<div>
<p>User has no Roles.</p>
</div>
<!-- /ko -->
<!-- ko if: SelectedUserHasRoles -->
<div class="roles-wrapper" data-bind="foreach: $root.selectedUser().roles()">
<div class="role-token" data-bind="text: $data"></div>
</div>
<!-- /ko -->
SelectedUserHasRoles: <span class="role-token" data-bind="text: SelectedUserHasRoles"></span>
<!-- /ko -->
有关详细信息,请参阅user3297291's answer。
答案 2 :(得分:0)
对isLoaded()进行两次相同的检查,实际上是
<!-- ko if: isLoaded() -->
<!-- ko if: !SelectedUserHasRoles -->
如果isLoaded()evalutes为false,则您的SelectedUserHasRoles()甚至不会被评估。