我怎样才能使 <dl> 的 <dd> 项最初通过 knockout 的自定义数据绑定隐藏起来?

How can I make the <dd> items of a <dl> to be initially hidden via knockout's custom databinding?

我创建了一个 <dl>,其中 <dd> 可以是 slideDown/slideUp 通过使用 knockout 的数据绑定点击相应的 <dt> . 我从关于 creating custom bindings 的教程中得出我的解决方案。

到目前为止,我设法连接了 一切 ,这样我就可以单击 <dt> 并切换 <dd>。计划是让 <dd>s 最初隐藏起来,但不知何故我无法做到这一点。

这是一个演示问题的简化示例:

HTML:

<dl data-bind="foreach: items">
    <dt data-bind="click: toggleDefinition">DT: Lorem ipsum</dt>
    <dd data-bind="slideVisible: definitionVisible, slideDuration: 300">DD: dolor sit amet</dd>    
</dl>

JavaScript:

ko.bindingHandlers.slideVisible = {
    init: function (element, valueAccessor) {
        var value = ko.unwrap(valueAccessor());
        $(element).toggle(value);
    },
    update: function (element, valueAccessor, allBindings) {
        var value = ko.unwrap(valueAccessor());
        var duration = allBindings.get('slideDuration') || 400;
        if (value) {
            $(element).slideUp(duration);
        } else {
            $(element).slideDown(duration);
        }
    }
};

var model = function(){
    var self = this;
    self.items = ko.observableArray([
        new item(),
        new item(),
        new item()
    ]);
};

var item = function(){
    var self = this;
    self.definitionVisible = ko.observable(false);
    self.toggleDefinition = function (e)
    {
        self.definitionVisible(!self.definitionVisible());
    };
};

ko.applyBindings(new model());

我尝试过的:

通过 CSS 隐藏 <dd>s 但它没有像我希望的那样工作(我没有注意到任何差异):

dd {
    display: none;
}

将以下 属性 设置为 true - 它部分起作用 - 它隐藏了 <dd>s 但你可以看到隐藏它们的动画是不可取的:

self.definitionVisible = ko.observable(true);

我也建一个working demo at jsfiddle

你知道我还可以尝试或更改什么以在我单击 <dt> 之前隐藏 <dd> 吗?

我不明白为什么调用 update 函数再次显示项目。我试图找到触发它的原因,但调用堆栈并没有太大帮助(一切都来自无法追踪的敲除)。

按照documentation:

中的描述正确触发了更新功能

Knockout will call the update callback initially when the binding is applied to an element and track any dependencies (observables/computeds) that you access

除此之外,您的处理程序无法正常工作,因为您在逻辑中遗漏了一些情况:您尝试 show/hide 基于当前值,但您应该检查以下内容:

  • 如果该元素当前处于隐藏状态且 definitionVisible 的新值为 true -> 则显示该元素
  • 如果该元素当前可见且 definitionVisible 的新值为 false -> 则隐藏该元素

将其翻译成您的代码:

update: function (element, valueAccessor, allBindings) {
    var value = ko.unwrap(valueAccessor());
    var duration = allBindings.get('slideDuration') || 400;
    if ($(element).css('display') != 'none' && !value) {
        $(element).slideUp(duration);
    }
    if ($(element).css('display') == 'none' && value) {
        $(element).slideDown(duration);
    }
}

演示 JSFiddle.