Knockout js:有条件地绑定title属性
Knockout js: Conditionally bind title attribute
我在屏幕顶部有几个选项卡,可以将用户导航到程序的几个部分。
如果程序的那部分有用户的紧急通知,现在应该突出显示其中一个选项卡。
我在#main-header 中添加了一个 'notifications' 属性,这是整个顶部的 ID div。
只有 css 项正在相应更改,到目前为止还不错。
但是,只有在有任何用户通知时,我才需要在标题属性中添加文本。
如果有任何通知,每 10 分钟检查一次。
这个顶部菜单是在循环中创建的,在 html 中看起来像这样:
<ul id="navigationMenuTop" class="nav navbar-nav" data-bind="foreach: getRoutes">
<li data-bind="css: { active: isActive() }, attr: { title: hash === '#url/location' ? setNotificationTitle : '' }">
<a data-bind="attr: { href: hash }, html: displayName"></a>
在视图模型中:
var self = this;
self.setNotificationTitle = ko.computed(function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
return "NotificationAlert";
} else {
return "";
}
});
这是在以下帮助下创建的:Knockout.js: conditionally bind title attribute of div
问题是使用 setNotificationTitle 导致我在顶部根本看不到标签。
当我在 html 中简单地对文本进行硬编码时,就会显示顶部菜单并且工具提示有效。
我错过了什么?
编辑:
现在的视图如下所示:
<ul id="navigationMenuTop" class="nav navbar-nav" data-bind="foreach: getRoutes">
<li data-bind="css: { active: isActive() }, attr: { title: hash === '#url/location' ? notificationTitle : '' }">
<a data-bind="attr: { href: hash }, html: displayName"></a>
和视图模型:
var self = this;
self.notificationTitle = ko.observable("");
self.setNotificationTitle = ko.computed(function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
self.notificationTitle("NotificationAlert");
} else {
self.notificationTitle("");
}
});
每当检查是否有任何通知时,都会调用 setNotificationTitle。
这也给了我同样的结果。
编辑:
不确定它是否重要,但在视图模型的底部它 returns NavigationViewModel 喜欢
return NavigationViewModel;
将其更改为我在 knockout js 文档中看到的内容
return NavigationViewModel = {
notificationTitle: this.notificationTitle
};
由于 notificationTitle 未定义,导致我在浏览器中出现系统内容错误...
问题是您正在使用和更新 DOM 来存储状态。当您修改该状态时,Knockout 无法知道。
假设您的页面上有一个元素:
<div id="stateEl" data-state="1">...</div>
您可以编写一个可以正常工作的敲除测试绑定:
<div data-bind="text: document.getElementById('stateEl').dataset.state"></div>
当您调用 ko.applyBindings
.
时,此元素将在页面上呈现“1”
但是,如果您在 调用 ko.applyBindings
之后更改第一个元素的属性 ,knockout 的文本绑定将不会更新。数据绑定依赖于 ko.observable
属性; Knockout 没有订阅 DOM.
更改的机制
所以每当你这样做时:
document.getElementById("stateEl").dataset.state = 2;
剔除元素仍将呈现“1”。
可能的解决方案
有许多可能的解决方案,有些比其他的更激进。我将按照个人喜好的顺序列出一些:
- 仅坚持 knockout.js。 不要通过 jQuery 或任何其他 javascript 代码 直接访问或修改 DOM。即:运行 您通过 knockout 视图模型定期更新并使用在 knockout 中运行良好的模式来共享您要显示的数据。
- 确保外部世界可以访问您的视图模型实例,并确保更新代码通知它任何新信息。
- 在您的视图模型中实施额外的定时更新,每隔 x 秒从 DOM 读取一次
这是第二种解决方案的示例:
// Viewmodel
const vm = {
notificationCount: ko.observable(0)
}
// Apply bindings
ko.applyBindings(vm, document.getElementById("app"));
// Periodic updates
let i = 0;
setInterval(() => {
const newCount = i++;
// Update the attribute
const header = document.getElementById("header");
header.dataset.count = newCount;
// Update the knockout vm explicitly
vm.notificationCount(header.dataset.count);
}, 500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- HTML not bound to knockout -->
<div id="header" data-count="0"></div>
<!-- HTML bound to a viewmodel in knockout -->
<div id="app" data-bind="text: notificationCount"></div>
最终通过添加这个 observable 和这个在检查是否有任何通知时调用的函数解决了这个问题。
self.notificationTitle = ko.observable("");
self.setNotificationTitle = function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
self.notificationTitle("NotificationAlert");
} else {
self.notificationTitle("");
}
};
并像这样添加:
<li data-bind="css: { active: (isActive() }, attr: { title: $parent.notificationTitle }">
我在屏幕顶部有几个选项卡,可以将用户导航到程序的几个部分。 如果程序的那部分有用户的紧急通知,现在应该突出显示其中一个选项卡。
我在#main-header 中添加了一个 'notifications' 属性,这是整个顶部的 ID div。
只有 css 项正在相应更改,到目前为止还不错。
但是,只有在有任何用户通知时,我才需要在标题属性中添加文本。 如果有任何通知,每 10 分钟检查一次。
这个顶部菜单是在循环中创建的,在 html 中看起来像这样:
<ul id="navigationMenuTop" class="nav navbar-nav" data-bind="foreach: getRoutes">
<li data-bind="css: { active: isActive() }, attr: { title: hash === '#url/location' ? setNotificationTitle : '' }">
<a data-bind="attr: { href: hash }, html: displayName"></a>
在视图模型中:
var self = this;
self.setNotificationTitle = ko.computed(function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
return "NotificationAlert";
} else {
return "";
}
});
这是在以下帮助下创建的:Knockout.js: conditionally bind title attribute of div
问题是使用 setNotificationTitle 导致我在顶部根本看不到标签。 当我在 html 中简单地对文本进行硬编码时,就会显示顶部菜单并且工具提示有效。
我错过了什么?
编辑: 现在的视图如下所示:
<ul id="navigationMenuTop" class="nav navbar-nav" data-bind="foreach: getRoutes">
<li data-bind="css: { active: isActive() }, attr: { title: hash === '#url/location' ? notificationTitle : '' }">
<a data-bind="attr: { href: hash }, html: displayName"></a>
和视图模型:
var self = this;
self.notificationTitle = ko.observable("");
self.setNotificationTitle = ko.computed(function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
self.notificationTitle("NotificationAlert");
} else {
self.notificationTitle("");
}
});
每当检查是否有任何通知时,都会调用 setNotificationTitle。 这也给了我同样的结果。
编辑: 不确定它是否重要,但在视图模型的底部它 returns NavigationViewModel 喜欢
return NavigationViewModel;
将其更改为我在 knockout js 文档中看到的内容
return NavigationViewModel = {
notificationTitle: this.notificationTitle
};
由于 notificationTitle 未定义,导致我在浏览器中出现系统内容错误...
问题是您正在使用和更新 DOM 来存储状态。当您修改该状态时,Knockout 无法知道。
假设您的页面上有一个元素:
<div id="stateEl" data-state="1">...</div>
您可以编写一个可以正常工作的敲除测试绑定:
<div data-bind="text: document.getElementById('stateEl').dataset.state"></div>
当您调用 ko.applyBindings
.
但是,如果您在 调用 ko.applyBindings
之后更改第一个元素的属性 ,knockout 的文本绑定将不会更新。数据绑定依赖于 ko.observable
属性; Knockout 没有订阅 DOM.
所以每当你这样做时:
document.getElementById("stateEl").dataset.state = 2;
剔除元素仍将呈现“1”。
可能的解决方案
有许多可能的解决方案,有些比其他的更激进。我将按照个人喜好的顺序列出一些:
- 仅坚持 knockout.js。 不要通过 jQuery 或任何其他 javascript 代码 直接访问或修改 DOM。即:运行 您通过 knockout 视图模型定期更新并使用在 knockout 中运行良好的模式来共享您要显示的数据。
- 确保外部世界可以访问您的视图模型实例,并确保更新代码通知它任何新信息。
- 在您的视图模型中实施额外的定时更新,每隔 x 秒从 DOM 读取一次
这是第二种解决方案的示例:
// Viewmodel
const vm = {
notificationCount: ko.observable(0)
}
// Apply bindings
ko.applyBindings(vm, document.getElementById("app"));
// Periodic updates
let i = 0;
setInterval(() => {
const newCount = i++;
// Update the attribute
const header = document.getElementById("header");
header.dataset.count = newCount;
// Update the knockout vm explicitly
vm.notificationCount(header.dataset.count);
}, 500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- HTML not bound to knockout -->
<div id="header" data-count="0"></div>
<!-- HTML bound to a viewmodel in knockout -->
<div id="app" data-bind="text: notificationCount"></div>
最终通过添加这个 observable 和这个在检查是否有任何通知时调用的函数解决了这个问题。
self.notificationTitle = ko.observable("");
self.setNotificationTitle = function () {
var attr = $("#main-header").attr("notifications");
if (typeof attr !== 'undefined' && attr !== false) {
self.notificationTitle("NotificationAlert");
} else {
self.notificationTitle("");
}
};
并像这样添加:
<li data-bind="css: { active: (isActive() }, attr: { title: $parent.notificationTitle }">