【问题标题】:How to use knockout and i18next for a specfic screen size?如何为特定的屏幕尺寸使用敲除和 i18next?
【发布时间】:2017-04-22 16:02:24
【问题描述】:

我有一个 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文件“en-CA”的sn-ps为:

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

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

我的任务是:

  1. 屏幕尺寸达到 767 像素后,我只想显示“编辑”而不是“编辑相关信息”

  2. 另外,在 320 像素和 767 像素之间(即移动视图),我只想要“相关信息”

我可以通过 HTML 和 CSS 实现这一点,但我想知道如何通过 JS(knockout) 实现它。

【问题讨论】:

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


    【解决方案1】:

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

    在本例中,我做了两件事:(要测试,请按整页并调整大小)

    • 通过可观察对象isSmallisMediumisLarge 跟踪“宽度状态”
    • 在视图模型中创建一组计算属性,将这种状态考虑在内并进行相应更新

    在代码中,你可以看到两种做法:

    1. 在视图模型中根据宽度状态进行翻译
    2. 在视图中平移,根据宽度状态隐藏

    在这两种情况下,视图模型都包含从特定状态转换为特定字符串组合的逻辑。

    // 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());
    <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>

    我很想知道为什么你宁愿在 javascript 中而不是在 HTML + CSS 中这样做......

    【讨论】:

    • 不错,直到现在我才知道matchMedia
    • 为了进一步简化,可以在 t 函数中传递 { context: size } 作为选项,并使用 i18next i18next.com/context.html的上下文特征
    【解决方案2】:

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

    如果你绝对必须,你可以将它硬塞到淘汰赛中,但我不确定这是否值得麻烦。

    最简单的形式是订阅resize 事件并将窗口宽度写入可观察对象:

    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);
    <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>

    下一步可能是这样做:

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

    【讨论】:

      猜你喜欢
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2018-09-19
      相关资源
      最近更新 更多