首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >KnockoutJS的渐进式增强

KnockoutJS的渐进式增强
EN

Stack Overflow用户
提问于 2012-01-22 20:34:28
回答 5查看 2.7K关注 0票数 19

假设我们有如下数据

代码语言:javascript
复制
var data = {
  facets: [{
    name : "some name",
    values: [{
      value: "some value" 
    }]
  }]
};

我们可以很容易地将其表示为绑定到敲除模板的视图模型,如下所示:

代码语言:javascript
复制
<ul data-bind="foreach: facets">    
  <li>      
    <span data-bind="text: name"></span>
    <ul data-bind="foreach: values">            
      <li data-bind="text: value"></li>     
    </ul>
  </li>
</ul>

问题是,在使用渐进式增强时,我们如何实现相同的结果?这是通过最初在服务器端呈现模板,然后将淘汰模板和视图模型绑定到该呈现来实现的。

一个简单的服务器端模板如下所示:

代码语言:javascript
复制
<ul>    
  <li>      
    <span>some name</span>
    <ul>            
      <li>some value</li>       
    </ul>
  </li>
</ul>

我探索了几种不同的可能性:

  • 的第一步是创建一个淘空模板和一个服务器端模板,并通过解析服务器端模板的DOM来动态生成淘空视图模型。这样,当启用JavaScript时,只有Knockout模板可见,而如果禁用JavaScript,则只有服务器端模板可见。它们的样式可以使它们看起来完全相同。
  • 另一种方法是将facets数组中每个项目的绑定分别应用于该facet的现有DOM元素。但是,这仍然只有一层深,不适用于嵌套元素。

这两种方法似乎都不是很干净。另一种解决方案可能是编写一个自定义绑定来处理整个呈现过程,并在可能的情况下重用现有元素。

还有其他想法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-01-28 21:29:47

我在这里探索了几种方法,包括从第一个元素生成匿名模板,如下所述:

http://groups.google.com/group/knockoutjs/browse_thread/thread/3896a640583763d7

或者通过自定义绑定为数组的每个元素创建单独的绑定,例如

代码语言:javascript
复制
ko.bindingHandlers.prerenderedArray = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var binding = valueAccessor();              
        binding.firstTime = true;

        $(element).children().each(function(index, node) {                  
            var value = ko.utils.unwrapObservable(binding.value)[index];                        
            ko.applyBindings(value, node);
        }); 

        return { 'controlsDescendantBindings': true };              
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {             
        var binding = valueAccessor();
        if (binding.firstTime) {
            binding.firstTime = false;
            return;
        }               

        $(element).children().remove(); 
        ko.applyBindingsToNode(element, { template: { name: binding.template, foreach: binding.value }}, viewModel)
    }
};      

它对每个元素应用特定的绑定,然后在第一次更新时将内容替换为普通的foreach绑定。这种方法仍然意味着您仍然需要两个模板。这两种方法还涉及通过服务器呈现的JSON初始化状态。

我选择使用的当前方法(尽管可能会有变化)是将所有的Knockout模板放在脚本标记中,这样它们就永远不会在NoJS浏览器中呈现出来。NoJS模板在服务器端呈现为div的内容。一旦Knockout模板被呈现,div的内容将被script标记中的Knockout模板替换。您可以用相同/相似的方式设置它们的样式,以实现无缝转换,如果不能这样做,则可以通过CSS隐藏noJS模板。

最后,我得出结论,Knockout.js和渐进式增强并不能很好地协同工作,应该选择另一种,即使用更传统的方法(如直接jQuery DOM操作)构建需要渐进式增强的应用程序的某些部分。

票数 4
EN

Stack Overflow用户

发布于 2012-01-22 20:35:36

只需在服务器端模板中添加各种data-属性即可。如果JavaScript被禁用,它们不会受到影响,所以拥有它们根本不是问题。

票数 3
EN

Stack Overflow用户

发布于 2012-01-22 21:45:11

恐怕没有干净的方法可以做到这一点。就我个人而言,我在后端呈现页面,然后将完全相同的上下文数据传递到前端(序列化为JSON),并使用它设置Knockout。这意味着存在一些重复。也许将后端切换到node.js会简化这里的事情。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8961073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档