在我的KncokoutJS视图模型中,我有以下计算属性:
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
文本片段。我不知道为什么没有显示!我将断点放入我的计算属性中,可以看到当我选择没有角色的用户时,表达式(在控制台窗口中)为 false,我正在否定它,所以我应该看到该文本片段!
我做错了什么?我创建了一个截屏视频,以使事情更容易理解。
如果要否定绑定中的可观察值或计算值,必须显式调用它:
<!-- ko if: !SelectedUserHasRoles() -->
在if
绑定的情况下,还有ifnot
对应的:
<!-- ko ifnot: SelectedUserHasRoles -->
我认为理解为什么需要这样做很有用,因为我看到它发生了很多。
您可以将数据绑定属性视为以逗号分隔的键值对字符串。Knockout 将每个值包装在一个函数中,它称之为valueAccessor
。
从本质上讲,您将从:
data-bind="if: SelectedUserHasRoles"
自
{
"if": function() { return SelectedUserHasRoles }
}
SelectedUserHasRoles
是一个可观察的实例,其评估结果为真实。当您使用!
否定此值时,它将始终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>
值访问器函数传递给绑定的init
方法。通常,通过调用它来检索它,然后解包。由于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>
我希望这个小小的窥视可以帮助你(和其他犯了这个错误的人)能够确定将来什么时候需要()
。
因为绑定的不是变量,而是表达式,所以需要在此处添加括号:
<!-- 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 的答案。
实际上,您对isLoaded()进行了两次相同的检查
<!-- ko if: isLoaded() -->
<!-- ko if: !SelectedUserHasRoles -->
如果 isLoaded() 的计算结果为 false,则您的 SelectedUserHasRoles() 甚至不会被评估。