是否可以对布尔 ViewModel 属性的否定(“!”)可见的数据绑定?

Posted

技术标签:

【中文标题】是否可以对布尔 ViewModel 属性的否定(“!”)可见的数据绑定?【英文标题】:Is it possible to data-bind visible to the negation ("!") of a boolean ViewModel property? 【发布时间】:2012-04-24 06:16:55 【问题描述】:

我想在我的 ViewModel 上使用一个属性来切换要显示的图标,而无需创建单独的逆计算属性。这可能吗?

<tbody data-bind="foreach: periods">
  <tr>
    <td>
      <i class="icon-search" data-bind="visible: !charted, click: $parent.pie_it"></i>
      <i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>
    </td>
  </tr>
</tbody>

我的 ViewModel 有一个属性 period 是月份数组,如下所示:

var month = function() 
    this.charted = ko.observable(false);
;

【问题讨论】:

@Niko:这并不是一个重复的问题。您提到的问题的 OP 已经知道 可以对 observable 的否定进行数据绑定,但想知道为什么需要像函数一样调用它。这个问题的 OP 在这里首先不知道如何做到这一点,显然没有找到其他问题。我很高兴在这里找到了这个问题——这主要归功于它的描述性标题。 【参考方案1】:

在表达式中使用 observable 时,您需要将其作为函数访问,例如:

visible: !charted()

【讨论】:

也许我们应该做一个隐藏绑定:) 我们已经启用和禁用。 文档不同意这一点,还是我完全误解了这个页面:knockoutjs.com/documentation/css-binding.html 没关系,我猜“isSevere”不是可观察的,而是普通的旧属性,因此我很困惑。 使用 !charted 时,您将获得 ![Function]。 [Function] 是真实的, ![Function] 变为 false,如果您使用该语法,将始终为 false。 jsfiddle.net/datashaman/E58u2/3 他们实际上在v3.5.0 中添加了hidden 绑定【参考方案2】:

我同意 John Papa 的评论,即应该有一个内置的 hidden 绑定。专用的hidden 绑定有两个好处:

    更简单的语法,即。 hidden: charted 而不是 visible: !charted()。 资源更少,因为 Knockout 可以直接观察可观察的charted,而不是创建一个computed 来观察!charted()

不过,创建hidden 绑定很简单,如下所示:

ko.bindingHandlers.hidden = 
  update: function(element, valueAccessor) 
    ko.bindingHandlers.visible.update(element, function() 
      return !ko.utils.unwrapObservable(valueAccessor());
    );
  
;

你可以像内置的visible绑定一样使用它:

<i class="icon-search" data-bind="hidden: charted, click: $parent.pie_it"></i>
<i class="icon-remove" data-bind="visible: charted, click: $parent.pie_it"></i>

【讨论】:

这对我来说没有回报return !ko.utils.unwrapObservable(valueAccessor()); 谢谢@MehmetAtaş - 我根据您的评论更正了hidden 绑定。 (顺便说一句,我最初发布此内容时在我的项目中使用 CoffeeScript。当有意返回时,CoffeeScript 的语法并不明显。)【参考方案3】:

这有点令人困惑,你必须这样做

visible:!showMe()

原来如此

<span data-bind="visible:showMe">Show</span>
<span data-bind="visible:!showMe()">Hide</span>
<label><input type="checkbox" data-bind="checked:showMe"/>toggle</label>​

我的模型是

var myModel=
    showMe:ko.observable(true)

ko.applyBindings(myModel);    

​ 签到小提琴http://jsfiddle.net/khanSharp/bgdbm/

【讨论】:

【参考方案4】:

您可以使用我的switch/case 绑定,其中包括case.visiblecasenot.visible

<tbody data-bind="foreach: periods">
    <tr>
        <td data-bind="switch: true">
        <i class="icon-search" data-bind="case.visible: $else, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: charted, click: $parent.pie_it"></i>
        </td>
    </tr>
</tbody>

你也可以这样

        <i class="icon-search" data-bind="casenot.visible: charted, click: $parent.pie_it"></i>
        <i class="icon-remove" data-bind="case.visible: $else, click: $parent.pie_it"></i>

【讨论】:

我刚刚意识到这是一个老问题,但希望这对某人有用。【参考方案5】:

为了让绑定知道属性的变化,我复制了可见的绑定处理程序并将其反转:

ko.bindingHandlers.hidden = 
    update: function (element, valueAccessor) 
        var value = ko.utils.unwrapObservable(valueAccessor());
        var isCurrentlyHidden = !(element.style.display == "");
        if (value && !isCurrentlyHidden)
            element.style.display = "none";
        else if ((!value) && isCurrentlyHidden)
            element.style.display = "";
    
;

【讨论】:

【参考方案6】:

免责声明:此解决方案仅用于娱乐目的。

ko.extenders.not = function (target) 
    target.not = ko.computed(function () 
        return !target();
    );
;

self.foo = ko.observable(true).extend( not: null );

<div data-bind="text: foo"></div>     <!-- true -->
<div data-bind="text: foo.not"></div> <!-- false -->

<!-- unfortunately I can't think of a way to be able to use:
    text: foo...not
-->

【讨论】:

【参考方案7】:

关于如何使用布尔可观察对象的对立面,我遇到了同样的问题。我找到了一个简单的解决方案:

var ViewModel = function () 
var self = this;

// When program start, this is set to FALSE
self.isSearchContentValid = ko.observable(false);


self.gatherPlacesData = function () 

   // When user click a button, the value become TRUE
   self.isSearchContentValid(true);

;

现在在你的 HTML 上你应该这样做

<p data-bind = "visible:isSearchContentValid() === false"> Text 1</p>
<p data-bind = "visible:isSearchContentValid"> Text 2</p>

程序启动时,只有“Text1”可见,因为“false===false 为 TRUE”,而 Text2 不可见。

假设我们有一个按钮,它在点击事件时调用gatherPlacesData。现在 Text1 将不可见,因为“true === false is FALSE”并且 Text 2 仅可见。

另一种可能的解决方案是使用计算的 observable,但我认为对于一个如此简单的问题来说这是一个过于复杂的解决方案。

【讨论】:

【参考方案8】:

也可以像这样使用隐藏

 <div data-bind="hidden: isString">
                            <input type="text" class="form-control" data-bind="value: settingValue" />
                        </div>

【讨论】:

以上是关于是否可以对布尔 ViewModel 属性的否定(“!”)可见的数据绑定?的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin Forms - 否定布尔绑定值

将可见性属性(视图)与布尔属性(ViewModel)绑定

复选框不适用于布尔视图模型属性

为啥双重否定强制值成为布尔值?

否定一个布尔变量并将其分配给一个新变量[重复]

ViewModel 是不是支持嵌套模型?虚拟属性可以应用于 viewModel 吗?