46

在 knockout.js 中,我们可以对静态类使用 css 绑定

<div data-bind="css: {'translucent ': number() < 10}">static dynamic css classes</div>

动态的

<div data-bind="css: color">static dynamic css classes</div>

我试过http://jsfiddle.net/tT9PK/1/将它组合成类似的东西

css: {color, translucent: number() < 10}

同时获取动态类color和静态类translucent,但出现错误。有没有办法做到这一点?

4

9 回答 9

58

您可以按属性添加动态类css,然后按属性添加静态attr

<div data-bind="attr: { 'class': color }, css: { 'translucent': number() < 10 }">
  static dynamic css classes
</div>

确保将任何预定义的类添加到此绑定 attr: { 'class': color }

于 2014-02-03T13:29:38.807 回答
14

不久前,我通过将css绑定克隆为css2.

 ko.bindingHandlers['css2'] = ko.bindingHandlers.css;

通常,您不能在 data-bind 属性中两次使用相同的绑定处理程序,因此这允许我执行以下操作:

<div data-bind="css: color, css2: { 'translucent': number() < 10 }">static dynamic css classes</div>

我不能完全决定我是否仍然喜欢这个,或者@Aleksey 的答案,但如果你有多个动态类要添加,这可能是唯一的选择。

于 2014-09-30T09:08:20.547 回答
4

您最好的选择可能是不要将它们结合起来。而是使用视图模型的计算属性将它们组合成一个可以动态绑定的属性。这样,您还可以避免使用 number() < 10 绑定将逻辑放入视图中,无论如何这更干净。

像这样,例如:

viewModel.colorAndTrans = ko.computed(function () {
    var cssString = viewModel.color();
    if (viewModel.number() < 10) {
        cssString += " translucent"
    }
    return cssString;
});

请参阅此工作示例:http: //jsfiddle.net/tT9PK/4/

于 2013-10-08T19:21:34.333 回答
4

正确...为了进一步启动您,请查看此修改。

http://jsfiddle.net/Fv27b/2/

在这里,您会看到我们不仅组合了这些选项,而且还完全创建了我们自己的绑定……这不仅会导致此视图模型的可移植性更高,而且您可能拥有的任何视图模型都可以进行扩展。你的项目……所以你只需要写一次!

ko.bindingHandlers.colorAndTrans = {
    update: function(element, valAccessor) {
        var valdata = valAccessor();
        var cssString = valdata.color();
        if (valdata.transValue() < 10) cssString += " translucent";
        element.className = cssString;
    }
}

要调用它,您只需将其用作新的数据绑定属性,并且可以包含尽可能多(或尽可能少)的选项。在这种特定情况下,我可能刚刚提供了 $data,但是如果您想要一个可重用的选项,您需要更具体地说明您需要哪些数据类型作为参数,并且并非所有视图模型都可能具有相同的属性。

data-bind="colorAndTrans: { color: color, transValue: number }"

希望这不仅仅是回答你的问题!

于 2013-10-08T19:59:47.680 回答
2

如果您真的遇到复杂的样式情况,只需在计算属性中累积所有内容。您可以按照 Alex 提到的或更具可读性的方式进行操作:

vm.divStyle = ko.computed(function() {
        var styles = [];

        if (vm.isNested()) styles.push('nested');
        if (vm.isTabular()) styles.push('tabular');
        else styles.push('non-tabular');
        if (vm.color()) styles.push(vm.color());

        return styles.join(' ');
});

主要缺点是您将视图定义的一部分移动到视图模型中,这应该更加独立。另一种方法是将上述所有逻辑作为一个普通的 js 函数调用提供,并让 Knockout 对其进行评估。

于 2015-10-14T10:14:47.797 回答
1

还有几个选择:

与使用计算的建议类似,您可以内联表达式:

<div data-bind="css: [color(), (number() < 10 ? 'translucent' : 'notTranslucent')].join(' ')">static dynamic css classes</div>

作为特定于这种情况的自定义绑定处理程序的替代方案,您可以制作一个采用混合 css 规范数组并将它们传递给原始 css 处理程序的处理程序:

<div data-bind="cssArray: [color, {translucent: number() < 10}]">static dynamic css classes</div>

处理程序:

 ko.bindingHandlers.cssArray = {
    update: function (element, valueAccessor, allBindingsAccessor, data, context) {
        var arr = ko.unwrap(valueAccessor());
      for (var i=0; i<arr.length; ++i) {
        var wrapped = function () { return ko.unwrap(arr[i]) };
        ko.bindingHandlers.css.update(element, wrapped, allBindingsAccessor, data, context);
      }
    }
  }

小提琴演示

于 2015-12-22T12:49:14.510 回答
1

好问题,问题似乎是绑定css不认为混合两种,color(): color() != ''不起作用(会很好)。

我喜欢@Simon_waver 的回答方式,简单实用。

也许在提出问题的时候不支持(Idk),但当前的淘汰赛也结合了这些课程:data-bind="css: computed"

viewModel.computed = ko.pureComputed(function() {
   return viewModel.color() + (viewModel.number() < 10 ? ' translucent' : '');
});
于 2015-07-05T19:19:47.343 回答
1

通过计算属性名称(对于FF>34、Chrome、Safari>7.1 )有一个更优雅的解决方案:

<div data-bind="css: { [color]: true,'translucent': number() < 10 }">
    static dynamic css classes
</div>

color是具有字符串值的属性。

如果 的值color是可观察的,那么我们需要在可观察更新之前清除类名。如果我们不这样做,那么每次更改都会添加另一个类,而不是删除前一个类。这可以很容易地手动完成,但我为感兴趣的人编写了一个扩展器。

ko.extenders.css = function(target, value) {
  var beforeChange;
  var onChange;

  //add sub-observables to our observable
  target.show = ko.observable(true);

  beforeChange = function(oldValue){
    target.show(false);
  }
  onChange = function(newValue){
    target.show(true);
  }
  target.subscribe(beforeChange, null, "beforeChange");
  target.subscribe(onChange);
  return target;
};

使用此扩展器,您的 JavaScript 代码将如下所示:

function MyViewModel() {
    this.color = ko.observable("red").extend({ css: true });
    this.number = ko.observable(9)
};

你的标记会很简单:

<div data-bind="css: { [color()]: color.show(),'translucent': number() < 10 }">
    static dynamic css classes
</div>

我有一个演示这种技术的代码笔:http: //codepen.io/USIUX/pen/WryGZQ

我还提交了一个关于敲除的问题,希望有一天不需要自定义扩展器:https ://github.com/knockout/knockout/issues/1990

于 2016-01-29T21:53:43.187 回答
0

我会css在您的视图模型中创建绑定值。您可以定义一个computed返回对象或字符串的 a。

一些示例,使用 ES2015:

const App = function() {
  this.number = ko.observable(12);
  this.color = ko.observable("red");
  
  this.cssConfigObj = ko.pureComputed(() => ({
    "italic": this.number() > 10,
    [this.color()]: true
  }));
  
  this.cssConfigStr = ko.pureComputed(() => 
    `${this.color()} ${this.number() > 10 ? "italic" : ""}`
  );
};

ko.applyBindings(new App());
.monospaced {
  font-family: monospace;
}

.italic {
  font-style: italic;
}

.red {
  color: red; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div
  class="monospaced"
  data-bind="css: cssConfigObj"
>Hello world</div>

<div
  class="monospaced"
  data-bind="css: cssConfigStr"
>Hello world</div>

于 2018-10-30T10:16:31.337 回答