我怎样才能使 <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);
你知道我还可以尝试或更改什么以在我单击 <dt>
之前隐藏 <dd>
吗?
我不明白为什么调用 update
函数再次显示项目。我试图找到触发它的原因,但调用堆栈并没有太大帮助(一切都来自无法追踪的敲除)。
中的描述正确触发了更新功能
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.
我创建了一个 <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);
你知道我还可以尝试或更改什么以在我单击 <dt>
之前隐藏 <dd>
吗?
我不明白为什么调用 update
函数再次显示项目。我试图找到触发它的原因,但调用堆栈并没有太大帮助(一切都来自无法追踪的敲除)。
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.