KnockoutJS:使用“with”和document.getElementById

时间:2014-05-07 07:37:47

标签: knockout.js getelementbyid

在KO中使用with会导致元素仅在data-bind的上下文可用时呈现。如果我有在页面加载上运行的脚本并且负责样式化HTML元素,那么如果我在数据绑定使用document.getElementById的元素上调用with,则会得到null。这是一些伪代码:

HTML:

<section data-bind="with: selectedView" id="sec">
    <span data-bind="text: title" id="span"></span>
</section>

运行onload的JS:

var PseudoViewModel = { ... };
ko.applyBindings(PseudoViewModel);

var x = document.getElementById("span"); // this is null

动态设计元素的最佳做法是什么?感谢。

2 个答案:

答案 0 :(得分:1)

如果您在元素存在时执行该代码(example),那么您正在做的工作应该有效。

在您的示例中,#sec是具有with绑定的元素。如果with绑定(示例中为#sec)的值为with,则selectedView将省略null后代元素或undefined.所以#sec将始终存在,而不是其中的范围。 (Example (原来这是问题代码中的错误,您打算定位span。)

  

动态设计元素的最佳做法是什么?

最佳做法是使用CSS而不是JavaScript代码来设置元素样式。可能与css绑定相结合,但不一定。

另一种选择是进行自定义绑定,将样式作为KO内容的一部分。自定义绑定在KO中很常见。由于KO知道它没有呈现元素,因此它不会对它运行自定义绑定,并且没有错误。

当然,如果您因为使用了withif而确实有可能存在或不存在的元素,请在使用之前测试它们是否存在:

var x = document.getElementById("span");
if (x) {
    // Do stuff here
}

但是,再次提出建议:

  1. 使用CSS而非JavaScript来设置元素样式(可能与css绑定一起应用于它的类);或

  2. 如果必须运行每个元素的代码,请使用自定义绑定(这里很棒的是你定义它们并重用它们);或

  3. 使用警卫(if (x) { ... }


  4. 这是一个自定义绑定的示例,如果绑定的值超过12个字符,则该元素的颜色为红色,否则为蓝色:

    ko.bindingHandlers.colorByLength = {
        update: function(element, valueAccessor/*, allBindings, viewModel, bindingContext*/) {
            var val = ko.unwrap(valueAccessor());
            element.style.color = (val && val.length > 12) ? "red" : "blue";
        }
    };      
    

    完整示例:Live Copy

    <!DOCTYPE html>
    <html>
    <head>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
    <meta charset=utf-8 />
    <title>Example Custom Binding</title>
    </head>
    <body>
    <section data-bind="with: selectedView" id="sec">
        <span data-bind="text: title, colorByLength: title" id="span"></span>
    </section>
    <section data-bind="with: anotherView" id="sec">
        <span data-bind="text: title, colorByLength: title" id="span"></span>
    </section>
    <section data-bind="with: nullView" id="sec">
        <span data-bind="text: title, colorByLength: title" id="span"></span>
    </section>
      <script>
        (function() {
          "use strict";
    
          // Custom binding
          ko.bindingHandlers.colorByLength = {
            update: function(element, valueAccessor/*, allBindings, viewModel, bindingContext*/) {
              var val = ko.unwrap(valueAccessor());
              element.style.color = (val && val.length > 12) ? "red" : "blue";
            }
          };      
    
          var PseudoViewModel = {
            // This one will be red
            selectedView: {
              title: "This is the title"
            },
    
            // This one will be blue
            anotherView: {
              title: "Short title"
            },
    
            // And of course, this one isn't rendered at all
            nullView: null
          };
          ko.applyBindings(PseudoViewModel);
    
        })();
      </script>
    </body>
    </html>
    

答案 1 :(得分:0)

如果在数据绑定上下文不可用时元素无法呈现所需的行为,那么您必须在JavaScript中防范:

function doThatThingOnPageLoad() {
  var elem = document.getElementById("sec");
  if (elem == null) return;

  continueDoingThatThingWith(elem);
}

您的JavaScript应该将此元素视为可选元素,因为它可能不存在。

相关问题