如何通过 KNOCKOUT 的自定义数据绑定使 <dl> 的 <dd> 项最初隐藏

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

本文关键字:dd 何通过 隐藏 dl 数据绑定 KNOCKOUT 自定义      更新时间:2023-09-26

>我创建了一个<dl>,通过使用 KNOCKOUT 的数据绑定单击相应的<dt>,可以slideDown/slideUp <dd>我从有关创建自定义绑定的教程中派生了我的解决方案。

到目前为止,我设法连接了所有内容,以便我可以单击<dt>并切换<dd>.计划是将<dd>最初隐藏起来,但不知何故我无法实现这一目标。

下面是演示该问题的简化示例:

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);

我还在jsfiddle上构建了一个工作演示

你知道我还能尝试或更改什么来隐藏<dd>直到我点击<dt>吗?

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

更新函数按照文档中所述正确触发:

当绑定应用于元素时,Knockout 最初将调用更新回调,并跟踪您访问的任何依赖项(可观察量/计算量)

除此之外,您的处理程序不起作用,因为您错过了逻辑中的一些情况:您尝试根据当前值显示/隐藏,但您应该检查以下内容:

  • 如果元素当前处于隐藏状态,并且新值 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。