【问题标题】:Handling multiple page-level binding providers处理多个页面级绑定提供程序
【发布时间】:2012-10-13 20:24:46
【问题描述】:

这是我的场景。

我想创建一个单独的 KnockoutJS 绑定提供程序来处理我的页面上的翻译,它将读取页面加载时出现或页面加载后创建的任何元素的 data-alias 属性(可能在渲染的子模板中创建通过敲除)并检索别名的翻译并将它们应用为元素的文本。我仍然希望能够独立调用ko.applyBindings(model, element); 来处理页面的data-bind 属性,但我想单独调用ko.applyBindings,以便可以将翻译应用于data-alias 属性。有谁知道我如何支持两者并让他们独立行事?

这是一个流程应该如何进行的示例。

HTML 标记/模板:

<fieldset>
    <legend data-alias="SomeTitle"></legend>
    <div class="row-container">
        <div class="control-group">
            <label class="control-label" data-alias="LabelAlias"></label>
            <div class="controls">
                <input type="text" data-bind="value: SomeObservable" />
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" data-alias="AnotherLabelAlias"></label>
            <div class="controls">
                <input type="text" data-bind="value: AnotherObservable" />
            </div>
        </div>
    </div>
</fieldset>

在页面加载时,将调用通过绑定提供程序为数据别名应用绑定:

<script type="text/javascript">
    $(function() {
        // Lets assume translations is a dictionary of alias to translation
        // that is loaded with the page synchronously
        ko.applyBindings(translations); 
    });
</script>

同样在页面加载时,会有一个服务调用来检索页面所需的数据,并在检索时将绑定应用于数据:

<script type="text/javascript">
    $(function() {
        $.ajax({...}) // Omitted for brevity
            .done(function(data) {
                var viewModel = new my.namespace.SomeViewModel(data);
                ko.applyBindings(viewModel);
            });
    });
</script>

预期效果:

  • 页面加载完毕。
  • 已应用翻译。
  • 启动服务调用以检索数据。
  • 服务调用返回。
  • 将数据转换为视图模型并绑定到页面(并保留翻译)。

【问题讨论】:

  • 对于当前的 KO 实例,您一次只能激活一个绑定提供程序。一种想法是创建一个绑定提供程序,它封装了真正的绑定提供程序,但公开了一个“模式”来确定要查找的内容。然后,您可以在进行翻译绑定时设置此模式。
  • 是的,这可能行得通。有机会我会调查的。
  • 所以你的第一个页面加载调用获取翻译绑定,然后第二个调用获取这些绑定的结果来获取翻译?
  • 第二次调用独立于第一次调用。我只希望第一个调用与页面同步,第二个调用是异步的。
  • 您不能将这些合并到一个视图模型中吗?并且在应用翻译时,只需使用一些空数据初始化viewModel(调用my.namespace.SomeViewModel)。然后用您的 ajax 调用填充这个空白部分。无需多次致电ko.applyBindings

标签: javascript knockout.js


【解决方案1】:

对从服务调用返回的数据使用敲除。

但是不要对翻译使用敲除 - 你想要在那里做的事情可以在没有敲除这样的框架的情况下处理。以下是你可以做到的:

var translations = {};
translations["LabelAlias"] = "Bonjour";
translations["AnotherLabelAlias"] = "Au Revoir";

$("[data-alias]").each(function(index, element){
    var aliasName = element.getAttribute("data-alias");
    var aliasValue = translations[aliasName];
    $(element).text(aliasValue);
});    ​

这是一个有效的小提琴:http://jsfiddle.net/qjGwR/

更新 您提到您已经动态加载了要翻译的内容。不是问题!我已经更新了小提琴 - http://jsfiddle.net/qjGwR/1/

function translate(translations, selector) {
  if (selector == null) { selector = ''; }
  $(selector + " [data-alias]").each(function(index, element){
    var aliasName = element.getAttribute("data-alias");
    var aliasValue = translations[aliasName];
    $(element).text(aliasValue);
  });
}

translate(helloTranslations);

// Add something to the DOM
var moreContent = '<label class="control-label" data-alias="ThirdLabelAlias">Three</label><div class="controls"><input type="text" data-bind="value: somethingElse" /></div>'

$('#moreContent').html(moreContent);
translate(helloTranslations, '#moreContent');​

我们将翻译行为移动到一个方法中,传入我们想要应用的翻译,并告诉它我们想要翻译 DOM 的哪一部分。

【讨论】:

  • 是的,我原本就想走那条路。然而,该路由的唯一问题是,并非页面的所有 DOM 元素都是在页面加载时创建的。我们使用嵌套的、递归定义的模板,这些模板也可以在用户加载页面后进行修改。因此,虽然该路由适用于初始页面加载,但加载后在页面上创建的任何 DOM 元素都不会被本地化。
  • 查看更新以了解如何处理动态加载的内容。
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 2018-06-12
相关资源
最近更新 更多