You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过KnockoutJS获取HTML中accordion类并实现手风琴展开交互效果

问题根因

  • API混用错误:jQuery.getElementsByClassName是无效写法,getElementsByClassName是原生DOM文档对象的方法,jQuery选择类名元素的语法为$('.accordion')
  • 生命周期调用错误:Durandal框架的activate钩子触发时,关联的视图DOM还未被渲染插入到页面中,此时无论用什么选择器都无法获取到.accordion元素
  • 实现思路不符合KnockoutJS的MVVM设计规范:手动操作DOM绑定事件的方式,在动态渲染(比如foreach生成)的手风琴项场景下会完全失效

方案1:快速修复现有代码

将原有逻辑从activate钩子迁移到Durandal的attached钩子(DOM完成插入后触发),同时修正选择器写法:

define(['viewmodels/shell', 'durandal/services/logger', 'mediator-js', 'knockout', 'toastr', 'jquery'],
    function (shell, logger, mediator, ko, toastr, $) {
        var vm = {
            shell: shell,
            activate: activate,
            attached: attached, // 新增attached生命周期声明
            mediator: mediator
        }
            
        function activate() {
            return true;
        }

        // 原有逻辑移到此处
        function attached() {
            var acc = document.getElementsByClassName("accordion");
            var panel = document.getElementsByClassName('panel');

            for (var i = 0; i < acc.length; i++) {
                acc[i].onclick = function () {
                    var setClasses = !this.classList.contains('active');
                    setClass(acc, 'active', 'remove');
                    setClass(panel, 'show', 'remove');

                    if (setClasses) {
                        this.classList.toggle("active");
                        this.nextElementSibling.classList.toggle("show");
                    }
                }
            }

            function setClass(els, className, fnName) {
                for (var i = 0; i < els.length; i++) {
                    els[i].classList[fnName](className);
                }
            }
        }

        return vm;
    });

方案2:符合KnockoutJS规范的标准实现

无需手动操作DOM,通过数据驱动视图状态,适配动态生成的手风琴项场景:

  1. 视图模型新增状态管理:
var vm = {
    shell: shell,
    activate: activate,
    mediator: mediator,
    // 手风琴列表数据,根据你的业务场景替换实际内容
    accordionItems: ko.observableArray([
        {title: '标题1', content: '内容1'},
        {title: '标题2', content: '内容2'},
        {title: '标题3', content: '内容3'}
    ]),
    // 存储当前激活的手风琴索引,-1表示无激活项
    activeAccordionIndex: ko.observable(-1),
    // 点击切换逻辑
    toggleAccordion: function(index) {
        if(vm.activeAccordionIndex() === index) {
            vm.activeAccordionIndex(-1);
        } else {
            vm.activeAccordionIndex(index);
        }
    }
}
  1. 视图模板绑定逻辑:
<!-- ko foreach: accordionItems -->
<button class="accordion" 
        data-bind="text: title, 
                   css: {'active': $index() === $parent.activeAccordionIndex()},
                   click: () => $parent.toggleAccordion($index())">
</button>
<div class="panel" data-bind="css: {'show': $index() === $parent.activeAccordionIndex()}">
  <p data-bind="text: content"></p>
</div>
<!-- /ko -->

内容的提问来源于stack exchange,提问作者lonelydev101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:45:08