将数组绑定到 Knockout 样式绑定

Bind an array to a Knockout style binding

我有一个 css 属性的 observableArray。元素是这样的:

[{ "--border-color": "red" //(colorName = observable - colorValue = observable) ... }]

我想避免使用 foreach 创建多个 <style> 标签。

我需要可以做这样的事情的东西:

data-bind="style: colorStyles"  //colorStyles = array mentioned above

有什么想法吗?

第 1 步:将属性数组合并到单个对象中

有很多方法可以做到这一点,其中我更喜欢使用 Object.assign 和扩展语法:

const mergedStyle = Object.assign({}, ...colorStyles);

对于其他(更多浏览器兼容)方式,google/search 对于 "Merging an array of objects"。

第 2 步:设置样式

从你的 属性 名字来看,你正在使用 custom css properties which, as far as I know, are not supported by the default style binding...

您可以编写一个快速自定义绑定,在内部使用 element.style.setProperty 来添加支持:

ko.bindingHandlers.varStyle = {
  init: (el, va) => {
    ko.computed(() => {
      Object.entries(ko.unwrap(va()))
        .forEach(([prop, val]) => {
          el.style.setProperty(prop, val);
        });
    });
  }
}

确保检查你的边缘情况。

演示:

第一个元素呈现常规的、未更改的 <div> 样式。第二个使用默认 style 绑定,无法更新自定义 属性。第三个元素使用自定义绑定,同时更新 colorbackground-color.

// Our style objects:
const allStyles = ko.observableArray([
  { "color": "white" },
  { "--my-color": "red" }
]);

const mergedStyle = ko.pureComputed(
  () => Object.assign({}, ...allStyles())
);

// Our custom binding
ko.bindingHandlers.varStyle = {
  init: (el, va) => {
    ko.computed(() => {
      Object.entries(ko.unwrap(va()))
        .forEach(([prop, val]) => {
          el.style.setProperty(prop, val);
        });
    });
  }
}

ko.applyBindings({
  myStyle: mergedStyle
});
div {
  --my-color: green;
  background: var(--my-color);

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="style: {}">Hello world</div>
<div data-bind="style: myStyle">Hello world</div>
<div data-bind="varStyle: myStyle">Hello world</div>