【问题标题】:Is there a way to set the page title by data-binding using Knockout.js?有没有办法通过使用 Knockout.js 进行数据绑定来设置页面标题?
【发布时间】:2012-01-28 19:10:27
【问题描述】:

我有一个带有 Title 属性的 viewModel。我想使用该属性设置页面标题。这是我已经尝试过的方法,但没有奏效:

<html>
   <head>
   <title data-bind="text: Title"></title>
</head>
<body>
   <span data-bind="text: Title"/> <!-- this displays the title properly -->
</body>

浏览器标题为空白/默认,而不是我的 Title 属性的值。

【问题讨论】:

  • 我不想继续编辑我的答案 - 有没有机会把它放在你的 html 标签上? &lt;html data-bind="attr: { title: Title }"&gt;
  • 另外,你能否将 ViewModel 上的 Title 属性绑定到更普通的东西,比如 span,并让它显示出来?
  • 我稍微更新了我的代码。是的,我可以在其他地方成功地对Title 进行数据绑定。只有页面标题不起作用。
  • @Adam,我在 html 元素上尝试了数据绑定,但也没有用。
  • 我更新了我的答案 - 我写的应该可以工作 - 我刚刚测试过。

标签: javascript html knockout.js


【解决方案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>

截图:

【讨论】:

  • @Byron - 抱歉 - 我有最后一个想法,然后我认为水库会干涸 :) --- 见编辑
  • @ByronSommardahl 如何传递 HTML 元素,而不仅仅是文档?类似document.getElementsByTagName("html")
  • 完美。我认为还有另一个问题。这绝对有效!谢谢。
  • 我在不向 元素添加 id 的情况下使用:ko.applyBindings(viewModel, document.getElementsByTagName('html')[0]) 希望可以简化您的工作回答。
  • 我使用了更通用的解决方案document.documentElement
【解决方案2】:

在我看来,这种情况需要一个可观察的订阅。

...
<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!");

};

编辑:作为对我之前回答的修正,我想提出以下内容。我之前的建议会奏效吗?是的,它工作得非常好。但是,视图模型本身内的 DOM 操作并不“完全”遵循 MVVM 范式。实际的“最佳”方法是创建一个自定义绑定,它在更新特定的 observable 时设置文档标题。

...
<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();
};

最后是我们闪亮的自定义绑定来“监听”对 observable 的更改(注意仅使用更新操作)

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()”通过 Knockout 视图模型创建“伪继承”。

【讨论】:

  • 为我工作!当您不想使用仅在少数特定情况下动态使用的 KO 标记污染页面标题时,这是一种特别方便的方法。
【解决方案3】:

您可以创建一个custom binding handler,在更新时设置document.title,然后将绑定添加到body 元素。

【讨论】:

  • 看看我上面链接到的页面上的最后一个例子,hasFocus 一个。很像这样,除了你不需要initupdate 会将document.title 设置为ko.utils.unwrapObservable(value),而不是在if 块中使用它。
【解决方案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);
    

    这对我很有效

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-27
      相关资源
      最近更新 更多