Knockout.js:使用多个按钮切换多个DOM元素的可见性

3
我有一个js fiddle(位于这里),我想用knockout.js模仿它。每个按钮都有一个对应的div标签。如果相应的div标签可见,则在单击按钮时应将其隐藏。否则,它应该显示出来。如果其他任何不相关的div可见,它们应该隐藏,然后显示相应的div。我如何使用knockout来模仿这个jQuery版本? knockout版本的js fiddle在此处。它可以工作,但仍然显得非常冗长。似乎应该有一种方法使其更加动态化并减少工作量。非常感谢您的帮助。
<style type="text/css">
    .text { background-color: lightgray; }
</style>

<script type="text/javascript">
    $(document).ready(function () {
        var viewModel = {
            showHide1: ko.observable(false),
            showHide2: ko.observable(false),
            showHide3: ko.observable(false),
            toggle1: function () {
                this.showHide1(true);
                this.showHide2(false);
                this.showHide3(false);
            },
            toggle2: function () {
                this.showHide1(false);
                this.showHide2(true);
                this.showHide3(false);
            },
            toggle3: function () {
                this.showHide1(false);
                this.showHide2(false);
                this.showHide3(true);
            }
        };

        ko.applyBindings(viewModel);
    });
</script>

<div id="text1" class="text" data-bind="if: showHide1">Text 1</div>
<div id="text2" class="text" data-bind="if: showHide2">Text 2</div>
<div id="text3" class="text" data-bind="if: showHide3">Text 3</div>
<br />
<br />
<button id="button1" type="button" data-bind="click: toggle1">Button 1</button>
<button id="button2" type="button" data-bind="click: toggle2">Button 2</button>
<button id="button3" type="button" data-bind="click: toggle3">Button 3</button>
3个回答

5
您可以使用动态模板名称与template绑定,例如:
<div class="text" data-bind="template: { 'if': current, name: current() }"></div>
<button type="button" data-bind="click: toggle1">Button 1</button>
<button type="button" data-bind="click: toggle2">Button 2</button>
<button type="button" data-bind="click: toggle3">Button 3</button>

<script id="text1" type="text/html">text 1</script>
<script id="text2" type="text/html">text 2</script>
<script id="text3" type="text/html">text 3</script>

使用以下视图模型:

var viewModel = {
    current: ko.observable(''),

    toggle1: function () {
        this.current("text1");
    },
    toggle2: function () {
        this.current("text2");
    },
    toggle3: function () {
        this.current("text3");
    },
};

ko.applyBindings(viewModel);

这里有一个例子:http://jsfiddle.net/rniemeyer/Zh9Qy/ 请注意,在KO 2.3中,您不必为选项“name”传递“current()”,而只需传递“current”,因为它现在将被正确地解封包。

3
我建议使用返回处理程序的函数。我发现这是编写健全的 Knockout 代码的基本方法。

基础

演示

我们可以将 HTML 简化为这个样子。它检查应该显示什么,然后通过按钮更改正在显示的内容。

<div id="text1" class="text" data-bind="if: showing() === '1'">Text 1</div>
<div id="text2" class="text" data-bind="if: showing() === '2'">Text 2</div>
<div id="text3" class="text" data-bind="if: showing() === '3'">Text 3</div>

<button id="button1" type="button" data-bind="click: show('1')">Button 1</button>
<button id="button2" type="button" data-bind="click: show('2')">Button 2</button>
<button id="button3" type="button" data-bind="click: show('3')">Button 3</button>

我们的 ViewModel 也被简化了。首先,我们将其转换为一个函数,以便更容易地扩展。我们的 showing 只是一个字符串值。show 是我们代码的主要部分。它返回一个设置 showing 的函数。
这样,我们可以将元素从 1、2 和 3 重命名为 main、about 和 contact,而无需触及 JavaScript。
ViewModel = function(){
    var self = this;

    self.showing = ko.observable('');
    self.show = function(what) {
        return function(){ self.showing(what); };
    }
};
ko.applyBindings(new ViewModel);

过渡动画

演示

要使用jQuery的滑入/滑出效果,我们可以使用KnockoutJS文档提供的代码。这是已删除注释的JavaScript代码:

ko.bindingHandlers.slideVisible = {
    update: function(element, valueAccessor, allBindingsAccessor) {
        var value = valueAccessor(), allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value); 
        var duration = allBindings.slideDuration || 400;
        if (valueUnwrapped == true) 
            $(element).slideDown(duration); // Make the element visible
        else
            $(element).slideUp(duration);   // Make the element invisible
    }
};

要将其放入HTML中,只需用slideVisible替换if绑定。

<div id="text1" class="text" data-bind="slideVisible: showing() === '1'">Text 1</div>
<div id="text2" class="text" data-bind="slideVisible: showing() === '2'">Text 2</div>
<div id="text3" class="text" data-bind="slideVisible: showing() === '3'">Text 3</div>

这是一个很棒的演示!你有什么想法可以在回答中使用jQuery的slideUp和slideDown函数吗? - Halcyon
@Halcyon,我添加了滑动过渡。 - Brigand

1
你可以创建一个viewModel,其中包含要显示的div的id。这个属性将根据你点击的按钮进行设置。
视图模型:
$(document).ready(function () {
    var ViewModel = function(){
        var self = this;
        self.onClick =function(data, event) {
           var element = event.target.id.replace('button', 'text');
           self.shownElement(element)
        };
        self.shownElement =ko.observable(null);

    };

    ko.applyBindings(new ViewModel());
});

视图:

<div id="text1" class="text" data-bind="visible: shownElement() == 'text1'">Text 1</div>
<div id="text2" class="text" data-bind="visible: shownElement() == 'text2'">Text 2</div>
<div id="text3" class="text" data-bind="visible: shownElement() == 'text3'">Text 3</div>
<br />
<br />
<button id="button1" type="button" data-bind="click: onClick">Button 1</button>
<button id="button2" type="button" data-bind="click: onClick">Button 2</button>
<button id="button3" type="button" data-bind="click: onClick">Button 3</button>

查看fiddle

希望这有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接