如何针对特定屏幕尺寸使用 knockout 和 i18next?

How to use knockout and i18next for a specfic screen size?

我有一个 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"是:

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

此刻,在 front-end 我可以在桌面视图中看到以下内容:

我的任务是:

  1. 767 像素屏幕尺寸后,我只想显示 "Edit" 代替 "Edit Dependent Information"

  2. 此外,在320像素和767像素之间(这是移动视图),我只想要"Dependent Information"

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

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

如果绝对必要,您可以将其硬塞进淘汰赛,但我不确定是否值得麻烦。

在最简单的形式中,您可以订阅 resize 事件并将 window 宽度写入可观察对象:

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>

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

中的元素

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

  • 通过 observables isSmallisMediumisLarge
  • 跟踪 "width state"
  • 在视图模型中创建一组计算属性,将此状态考虑在内并进行相应更新

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

  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 中这样做...