【问题标题】:How to get all css classes from html, through knockoutjs如何通过knockoutjs从html中获取所有css类
【发布时间】:2022-01-05 20:38:27
【问题描述】:

我在选择带有accordion 的所有类并将它们带入 knckoutjs 以对其进行操作时遇到问题。

点击此链接:https://wpbeaches.com/create-expandcollapse-faq-accordion-collapse-click/ 我设法创建了很好的可扩展对象(矩形),但它们“死了”,因为我使用的是 knockotjs,而不是 JS。 所以我的问题是如何使它工作? 第一步是由于某种原因我无法选择所有 accordion 类。这是我的代码:

define(['viewmodels/shell', 'durandal/services/logger', 'mediator-js', 'knockout', 'toastr'],
    function (shell, logger, mediator, ko, toastr) {
        var vm = {
            shell: shell,
            activate: activate,
            mediator: mediator
        }
            
        function activate() {
            var acc = jQuery.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 true;
        }

        return vm;
    });

我实际上尝试的是将上面链接中的 js 部分复制到我的解决方案中并使其工作(展开每个矩形..)

【问题讨论】:

  • 您不是“选择所有类”,而是选择具有特定类的所有元素
  • "因为我使用的是 knockoutjs,而不是 JS。" - KnockoutJS JavaScript...
  • activate 函数在哪里以及如何被调用?
  • 你是对的。它是名为 router.js 和 durandal.js 的插件的一部分,但这与此事无关。我可以通过调试看到它停止到要按类名获取所有元素的位置。
  • 脚本的宿主环境总是相关的,例如,如果脚本在 DOM 完全加载之前运行,那么querySelector 将无法按预期工作,并且脚本何时运行取决于其宿主 - 其他环境,如 ReactJS 和 Angular,具有某种形式的虚拟 DOM,这也打破了开发人员对 DOM API 的期望。

标签: javascript html twitter-bootstrap knockout.js


【解决方案1】:

我不太清楚您要做什么,但代码中的迹象表明您正在尝试做错事。

这是我能想到的使用 Knockout 和(为方便起见)jQuery 的最小手风琴类型的功能,直接从您提供的示例页面获取问题和答案。

您总是可以通过添加动画等变得更加复杂。但归根结底,它是关于跨元素列表管理单个 CSS 类。

ko.bindingHandlers.cssExclusive = {
  init: (element, valueAccessor) => {
    ko.applyBindingsToNode(element, {
      click: () => {
        var config = ko.unwrap(valueAccessor());
        $(element).closest(config.within).children().not(element).removeClass(config.class);
        $(element).toggleClass(config.class);
      }
    });
  }
};

const data = {
  sections: [
    {name: "FAQs", items: [
      {q: "What currency is the course charged in?", a: "The course is charged in Australian dollars."},
      {q: "What if the course doesn’t help me?", a: "If it doesn't help you I'll refund the purchase price in full."},
      {q: "When will the webinars take place?", a: "Depending on the mix of countries and time zones for people attending the webinars, I will pick a time that works best for most participants. All webinars will be recorded so you can listen to them again. The private Facebook group will obviously be available 24/7 and I’ll be monitoring and contributing to the discussion regularly."},
      {q: "What is the self-directed mentoring program?", a: "The self-directed mentoring program is designed to help you set-up and run an effective mentee-mentor relationship as part of the course."},
    ]}
  ]
};

ko.applyBindings(data);
.accordion {
  cursor: pointer;
}
.panel {
  display: none;
}
.accordion.active {
  color: blue;
}
.accordion.active + .panel {
  display: block;
  color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="foreach: sections">
  <h3 data-bind="text: name"></h3>
  <div data-bind="foreach: items">
    <p class="accordion" data-bind="cssExclusive: {class: 'active', within: 'div'}">
      <span data-bind="text: 'Q' + ($index() + 1) + '.'"></span>
      <span data-bind="text: q"></span>
    </p>
    <div class="panel">A. <span data-bind="text: a"></span></div>
  </div>
</div>

我不能说您将如何将它集成到您​​的示例代码中,但也许您可以从中汲取一些灵感。

核心功能是在点击元素时切换 CSS 类。为此,我制作了一个简单的custom binding,将the click binding 应用于所有问题。点击绑定负责在点击的问题上切换 active 类,并将其从同一容器中的所有其他问题中移除。

这甚至不需要视图模型上的“扩展”可观察对象之类的东西,因为它纯粹通过 DOM 中的 CSS 类来保持其状态。

【讨论】:

  • 它有效!我会接受你的正确回答。
  • @Tomalek 你也可以在这里查看我关于标题下拉菜单的类似问题:stackoverflow.com/questions/70080774/…我在这个问题上放了赏金。谢谢
  • @Stefan0309 很高兴听到。如果您将其从代码转储转换为minimal reproducible example,我会看看其他问题。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 2017-01-27
  • 1970-01-01
  • 2014-01-25
  • 2012-07-15
相关资源
最近更新 更多