如何使用knockout和i18next作为特定的屏幕尺寸?

时间:2016-12-07 16:06:16

标签: javascript css knockout.js media-queries i18next

我有一个HTML:

<div class="inter">
    <!-- ko if:emprel_id -->
    <!-- ko i18n:'dependents.editDependent' --><!-- /ko -->
    <!-- /ko -->


    <!-- ko if:emprel_id -->
    <!-- ko i18n:'dependents.DependentInformation' --><!-- /ko -->
    <!-- /ko -->
</div>

JS文件的片段&#34; en-CA&#34;是:

"dependents.editDependent": "Edit",
"dependents.DependentInformation": "Dependent Information",

此时,在前端我可以在桌面视图中看到以下内容: enter image description here

我的任务是:

  1. 屏幕尺寸为767像素后,我只想要&#34;编辑&#34;代替&#34;编辑依赖信息&#34;

  2. 此外,在320像素和767像素之间(这是移动视图),我只想要&#34;依赖信息&#34;

  3. 我可以实现这个彻底的HTML和CSS,但我想知道如何通过JS(淘汰赛)实现它。

2 个答案:

答案 0 :(得分:1)

您可以使用matchMedia使observable州保持最新状态。然后,您可以在计算属性中使用此状态,该属性可以翻译文本,也可以隐藏DOM中的元素。

在这个例子中,我做了两件事:(要测试,按完整页面并调整大小)

  • 跟踪宽度状态&#34;通过可观察的isSmallisMediumisLarge
  • 在视图模型中创建一组计算属性,将此状态考虑在内并相应地更新

在代码中,您可以看到两种方法:

  1. 基于宽度状态
  2. 在viewmodel中进行翻译
  3. 在视图中翻译,根据宽度状态隐藏
  4. 在两种情况下,viewmodel都保存从特定状态转换为特定字符串组合的逻辑。

    &#13;
    &#13;
    // Keep track of state
    var small = window.matchMedia("(max-width: 320px)");
    var medium = window.matchMedia("(min-width: 321px) and (max-width: 768px)");
    var large = window.matchMedia("(min-width: 769px)");
    
    var isSmall = ko.observable(small.matches);
    var isMedium = ko.observable(medium.matches);
    var isLarge = ko.observable(large.matches);
    
    var onChange = function() {
      isSmall(small.matches);
      isMedium(medium.matches);
      isLarge(large.matches);
    }
    
    small.addListener(onChange);
    medium.addListener(onChange);
    large.addListener(onChange);
    
    // VM
    function ViewModel() {
      // For option 1
      this.translatedLabel = ko.pureComputed(function() {
        if (isSmall()) return i18nextko.t("dependents.editDependent");
        if (isMedium()) return i18nextko.t("dependents.DependentInformation");
        if (isLarge()) return i18nextko.t("dependents.editDependent") +
          " " + i18nextko.t("dependents.DependentInformation");
      }, this);
      
      // For option 2
      this.showLeft = ko.pureComputed(function() {
        return !isMedium();
      }, this);
      this.showRight = ko.pureComputed(function() {
        return !isSmall();
      }, this);
    }
    
    
    
    // Mock
    var i18nextko = {
      t: function(key) {
        switch (key) {
            case "dependents.editDependent":
              return "Edit";
            case "dependents.DependentInformation":
              return "Dependent Information";
        }
      }
    };
    
    ko.bindingHandlers.i18n = {
       init: function(e, valueAccessor) {
         e.innerText = i18nextko.t(valueAccessor());
       },
    }
    
    ko.applyBindings(new ViewModel());
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    <h2>Via computed</h2>
    <div data-bind="text: translatedLabel"></div>
    
    <h2>Via visible binding</h2>
    <span data-bind="i18n: 'dependents.editDependent', visible: showLeft"></span>
    <span data-bind="i18n: 'dependents.DependentInformation', visible: showRight"></span>
    &#13;
    &#13;
    &#13;

    我很想知道为什么你宁愿用javascript而不是HTML + CSS呢...

答案 1 :(得分:0)

响应式布局最好通过CSS实现。

如果绝对必要的话,你可以将其淘汰出局,但我不确定它是否值得这么麻烦。

使用最简单的形式,您可以订阅resize事件并将窗口宽度写入可观察量:

&#13;
&#13;
function Demo() {
  var self = this;
  self.windowWidth = ko.observable(window.innerWidth);
  self.isWideLayout = ko.computed(function () {
    return self.windowWidth() >= 767;
  });
}

var vm = new Demo();

ko.utils.registerEventHandler(window, 'resize', function () {
  vm.windowWidth(window.innerWidth); // or whatever value you want to use
})

ko.applyBindings(vm);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div data-bind="text: windowWidth"></div>
<div>wide layout? <span data-bind="text: isWideLayout"></span></div>
&#13;
&#13;
&#13;

下一步可能是做这样的事情:

<div class="inter">
    <!-- ko if:emprel_id -->
    <!-- ko i18n: $root.isWideLayout() ? 'string1' : 'string2' --><!-- /ko -->
    <!-- /ko -->
</div>