Javascript 通过css绑定knockout.js将动态类和静态类结合起来

Javascript 通过css绑定knockout.js将动态类和静态类结合起来,javascript,knockout.js,Javascript,Knockout.js,在knockout.js中,我们可以对静态类使用css绑定 <div data-bind="css: {'translucent ': number() < 10}">static dynamic css classes</div> 静态动态css类 动态的 <div data-bind="css: color">static dynamic css classes</div> 静态动态css类 我试着把它组合成这样的东西 css:

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

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

<div data-bind="css: color">static dynamic css classes</div>
静态动态css类
我试着把它组合成这样的东西

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

同时获取动态类
颜色
和静态
半透明
,但我得到一个错误。有没有办法做到这一点?

你最好的办法可能是不要将它们结合起来。取而代之的是,使用视图模型的计算属性将它们组合成一个可以动态绑定的属性。通过这种方式,您还可以避免在视图中使用number()<10绑定来放置逻辑,这无论如何都是比较干净的

比如说:

viewModel.colorAndTrans = ko.computed(function () {
    var cssString = viewModel.color();
    if (viewModel.number() < 10) {
        cssString += " translucent"
    }
    return cssString;
});
viewModel.colorAndTrans=ko.computed(函数(){
var cssString=viewModel.color();
if(viewModel.number()<10){
cssString+=“半透明”
}
返回cssString;
});

请参阅此工作示例:

正确…要进一步启动您,请查看此修改

在这里,您将看到,我们不仅组合了选项,而且完全创建了我们自己的绑定…这不仅导致了此视图模型的可移植扩展,而且还导致了项目中可能有的任何视图模型的可移植扩展…因此您只需编写一次

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

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

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

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

静态动态css类

请确保将任何预定义类添加到此绑定
attr:{'class':color}
不久前,我通过将
css
绑定克隆为
css2
解决了这个问题

 ko.bindingHandlers['css2'] = ko.bindingHandlers.css;
通常情况下,不能在数据绑定属性中两次使用同一绑定处理程序,因此这允许我执行以下操作:

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

我不能确定我还是更喜欢这个,还是@Aleksey的答案,但如果你有多个动态类要添加,这可能是唯一的选择。

好问题,问题似乎是绑定
css
被认为不是这两种类型的混合,
color():color()!=”不起作用(如果可以的话)

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

可能在提出问题时不支持(Idk),但当前的淘汰也可以将这些类结合起来使用:
data bind=“css:computed”

viewModel.computed=ko.pureComputed(函数(){
返回viewModel.color()+(viewModel.number()<10?“半透明”:“”;
});

如果您真的遇到了复杂的样式设置问题,只需在computed属性中累积所有内容即可。您可以按照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(' ');
});
主要缺点是将视图定义的一部分移动到viewmodel中,而viewmodel应该更加独立。另一种方法是将上述所有逻辑作为简单的js函数调用提供,并让knockout对其进行评估。

还有几个选项:

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

<div data-bind="css: [color(), (number() < 10 ? 'translucent' : 'notTranslucent')].join(' ')">static dynamic css classes</div>
静态动态css类
作为特定于此情况的自定义绑定处理程序的替代方案,您可以创建一个接受混合css规范数组并将其传递给原始css处理程序的绑定处理程序:

<div data-bind="cssArray: [color, {translucent: number() < 10}]">static dynamic css classes</div>
静态动态css类
处理程序:

 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);
      }
    }
  }
ko.bindingHandlers.cssArray={
更新:函数(元素、valueAccessor、allBindingsAccessor、数据、上下文){
var arr=ko.unwrap(valueAccessor());

对于(var i=0;i

),通过计算属性名(for)可以更优雅地解决此问题:

使用此扩展器,您的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>

静态动态css类
我有一支代码笔来演示这种技术:


我还提交了一个关于knockout的问题,希望有一天不需要定制扩展程序:

我将在viewmodel中创建
css
绑定值。您可以定义一个
计算的
,返回对象或字符串

使用ES2015的一些示例:

const App=function(){
此数值=可观察的ko(12);
this.color=ko.可观察(“红色”);
this.cssConfigObj=ko.pureComputed(()=>({
“斜体”:此.number()>10,
[this.color()]:true
}));
this.cssConfigStr=ko.pureComputed(()=>
`${this.color()}${this.number()>10?“斜体”:“}`
);
};
ko.applyBindings(新应用程序());
。等距{
字体系列:monospace;
}
.斜体{
字体:斜体;
}
瑞德先生{
颜色:红色;
}

你好,世界

Hello world
我倾向于支持@Aleksey对此的回答,但这种方法是一种有趣的处理方法。这是有效的解决方案,是唯一有效的解决方案。请确保向该绑定添加任何预定义类(使用实际类属性添加的类).我认为答案中应该包含josh_bailey4
的评论,因为这是一件非常重要的事情,尤其是在编辑目标元素上已经有
class
属性的现有标记时。无论如何,这个答案似乎不适用于动态类名。如果“颜色”可观察到的更改在此,它将删除通过“css”绑定添加的任何类。参见示例:意识到此解决方案无法处理可观察到的更改为时已晚。无法撤消我的upvote。对我来说,这是成功的,很幸运此答案可用于OP。大多数情况下,这样做只会导致大量计算(思考列表)和耦合代码(更难测试)。
Aleksey
下面的答案,以及
josh_bailey4
的评论是一个更优雅的解决方案,我认为这应该是公认的答案,而不是这个答案。就我的2美分。@Mtz:
<div data-bind="css: { [color]: true,'translucent': number() < 10 }">
    static dynamic css classes
</div>
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;
};
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>