Есть ли способ установить заголовок страницы путем привязки данных с помощью Knockout.js?
У меня есть viewModel с свойством Title
. Я хотел бы задать заголовок страницы, используя это свойство. Вот то, что я пробовал уже, что не сработало:
<html>
<head>
<title data-bind="text: Title"></title>
</head>
<body>
<span data-bind="text: Title"/> <!-- this displays the title properly -->
</body>
Заголовок браузера пуст/по умолчанию вместо значения моего свойства Title
.
Ответы
Ответ 1
Попробуйте указать html-элемент id
<html id="htmlTop" xmlns="http://www.w3.org/1999/xhtml">
и применяя к нему свой viewModel
ko.applyBindings(viewModel, document.getElementById("htmlTop"));
ИЗМЕНИТЬ
Это работает для меня; Я просто запустил эту страницу, и название получило название "Привет". Дважды проверьте свой код для опечаток.
<html id="htmlTop">
<head>
<title data-bind="text: title"></title>
<script type='text/javascript' src='jquery.min.js'></script>
<script type='text/javascript' src='knockout-1.2.1.js'></script>
<script type="text/javascript">
$(function () {
var viewModel = { title: "Hello" };
ko.applyBindings(viewModel, document.getElementById("htmlTop"));
});
</script>
</head>
<body>
</body>
</html>
Скриншот:
![enter image description here]()
Ответ 2
Вы можете создать настраиваемый обработчик привязки, который устанавливает document.title
при обновлении, а затем добавляет привязку к элементу body
.
Ответ 3
В моих глазах эта ситуация требует наблюдаемой подписки.
...
<title>{FALL BACK TEXT}</title>
...
Просмотр модели
ViewModel = function() {
var self = this;
self.PageTitle = ko.observable(null);
self.PageTitle.subscribe(function(newValue){ document.title = self.PageTitle() });
//change PageTitle to see your handy work in action
self.PageTitle("Hello World!");
};
EDIT:
Как поправка к моему предыдущему ответу, я хотел бы изложить следующее. Будет ли мое предыдущее предложение работать? Да, это работает очень хорошо. Однако манипуляция DOM в самой модели представления не "точно" соответствует парадигме MVVM. Фактическим "лучшим" подходом было бы создание пользовательской привязки, которая устанавливает заголовок документа для обновления определенного наблюдаемого.
...
<title data-bind="htmlDocumentTitle: PageTitle()">{FALLBACK TEXT}</title>
...
Просмотр модели
ViewModel = function() {
var self = this;
self.PageTitle = ko.observable(null);
self.init = function(){
self.PageTitle("My page title from an obersvable");
};
//init the viewmodel
self.init();
};
И, наконец, наша блестящая пользовательская привязка для "прослушивания" изменений наблюдаемого (обратите внимание на использование ТОЛЬКО действия обновления)
ko.bindingHandlers.htmlDocumentTitle = {
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var fallbackTitle = "My document title";
var title = ko.unwrap(valueAccessor());
if(!title || title == null && title == "")
title = fallbackTitle;
document.title = title;
}
};
На первый взгляд это решение может показаться менее масштабируемым, но имейте в виду, что мы можем создавать "псевдонаследование" с помощью моделей нокаут-просмотра с помощью "call()".
Ответ 4
Вы можете использовать подписку на нокаут:
function viewModel() {
var self = this;
self.title = ko.observable(null);
self.title.subscribe(function(newTitle) {
document.title = newTitle;
})
}
var vm = new viewModel();
ko.applyBindings(vm);
vm.title('Hello page');
Ответ 5
В соответствии с предложением @Douglas моим решением было добавить скрытый div
где-то в теле, связанном с вычисленным значением:
<div data-bind="text: currentPageTitle()"></div>
Затем в вычислении значения я устанавливаю document.title
:
self.currentPageTitle = ko.computed(function() {
document.title = self.Title();
return self.Title();
}, this);
Это отлично работает для меня