ko.computed 属性,用于确定可见性不起作用



在我的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() 甚至不会被评估。

最新更新