【问题标题】:Why is my Accordion not working using HTML and Stimulusjs为什么我的手风琴不能使用 HTML 和 Stimulusjs
【发布时间】:2022-09-29 13:53:32
【问题描述】:

请帮助我制作这个手风琴工作我对 StimulusJS 不太熟悉。第一个手风琴工作正常,但其余手风琴没有响应。我在这里附上了代码的sn-p,请让我知道我做错了什么,谢谢。

script 标签包含stimulusjs 代码。请我很感激你的cmets。

<script src=\"https://cdn.tailwindcss.com\"></script>
<script type=\"module\">
    import { Application, Controller } from \"https://unpkg.com/@hotwired/stimulus/dist/stimulus.js\"
    window.Stimulus = Application.start()

    Stimulus.register(\"dropdown\", class extends Controller {
     static targets = [\"background\", \"drop\", \"expand\", \"button\"];
    static values = { accordionValue: Number };
    connect() {
        console.log(\"Drop Down connected\");
    }

    initialize() {
        this.isOpen = true;
    }

    onToggle = (e) => {
        Array.prototype.forEach.call(this.buttonTargets, function (element, index) {
            element.addEventListener(\"click\", function () {
                console.log(index)
            })
        })
        this.isOpen ? this.show() : this.hide();
        this.isOpen = !this.isOpen;
    };

    show() {
        this.dropTarget.className = \"block w-full text-base font-light pt-3\";
        this.backgroundTarget.className = \"bg-[#F0F0F0] mb-2 py-6 px-4\";
        this.expandTarget.innerHTML = \"-\";
        console.log(\"dropdown is active\");
    }

    hide() {
        this.dropTarget.className = \"hidden\";
        this.backgroundTarget.className = \"bg-white -mb-2 w-full py-6 px-4\";
        this.expandTarget.innerHTML = \"+\";
        console.log(\"dropdown is closed\");
    }
    })
  </script>

<div data-controller=\"dropdown\" class=\"w-full flex flex-col gap-12 md:flex-row sm:max-w-[400px] md:max-w-[450px] lg:max-w-[500px] text-[#868686]\">
  <div class=\"md:min-h-[450px] w-full mt-3\">
    <h4 class=\"text-4xl font-semibold px-4 pb-3\">FAQ\'s</h4>
    <div data-dropdown-target=\"background\" class=\" py-4 px-4\">
      <div data-action=\"click->dropdown#onToggle\" data-dropdown-target=\"button\" class=\"cursor-pointer flex justify-between items-center\">
        <h5 class=\"text-xl font-bold\">Waar hebben jullie nieuwe tuinen aangelegd? </h5><span data-dropdown-target=\"expand\" class=\"font-light text-[18px] self-start\">+</span>
      </div>

      <p data-dropdown-target=\"drop\" class=\"hidden\">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    </div>
    <div data-dropdown-target=\"background\" class=\" py-4 px-4\">
      <div data-action=\"click->dropdown#onToggle\" data-dropdown-target=\"button\" class=\"cursor-pointer flex justify-between items-center\">
        <h5 class=\"text-xl font-bold\">Waar moet een goede hovenier aan voldoen?</h5><span data-dropdown-target=\"expand\" class=\"font-light text-[18px] self-start\">+</span>
      </div>
      <p data-dropdown-target=\"drop\" class=\"hidden \">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    </div>
    <div data-dropdown-target=\"background\" class=\"py-4 px-4\">
      <div data-action=\"click->dropdown#onToggle\" data-dropdown-target=\"button\" class=\"cursor-pointer flex justify-between items-center\">
        <h5 class=\"text-xl font-bold\">Wat kost de aanleg van een nieuwe tuin? </h5><span data-dropdown-target=\"expand\" class=\"font-light text-[18px] self-start\">+</span>
      </div>
      <p data-dropdown-target=\"drop\" class=\"hidden\">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    </div>
    <div data-dropdown-target=\"background\" class=\"py-4 px-4\">
      <div data-action=\"click->dropdown#onToggle\" data-dropdown-target=\"button\" class=\"cursor-pointer flex justify-between items-center\">
        <h5 class=\"text-xl font-bold\">Zijn de afspraken vrijblijvend?</h5><span data-dropdown-target=\"expand\" class=\"font-light text-[18px] ml-auto self-start\">+</span>
      </div>
      <p data-dropdown-target=\"drop\" class=\"hidden\">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
    </div>
  </div>
</div>

    标签: stimulusjs stimulus-reflex


    【解决方案1】:

    首先 - 从 HTML 开始

    Stimulus 文档提供了一个很好的指南,其中一个关键原则是'Start with the HTML'

    所有现代浏览器都支持 HTML details 披露元素,您可以在 MDN 站点上找到非常可靠的文档。 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details

    使用 Tailwind,您可以走得很远,但您可能需要添加一个插件来针对 open attribute 设置样式。

    有关样式,请参阅

    如果没有 Tailwind,它可能会更容易一些,但这取决于你。

    在不编写任何 JavaScript 代码的情况下尽可能靠近,这是一个样式精美的单手风琴项目,无需额外代码即可打开和关闭。

    使用原生 HTML 元素的主要好处是

    • 需要维护的代码越少越好。
    • 迫使您考虑辅助功能和键盘控制,而不是滚动您自己的“按钮”,例如那些不是真正的按钮并破坏辅助功能的东西。
    • 可能足以保持原样继续前进,您可能不需要“打开时关闭其他人”功能,您可以继续进行项目中的其他事情。

    其次 - 用 Stimulus 填补样式空白

    • 您可能会发现您必须使用一些 JavaScript 来添加/删除某些类,请尽量避免这种情况,但如果您必须使用上面的代码方法就足够了。
    • 您可能希望使用刺激类方法https://stimulus.hotwired.dev/reference/css-classes 更明确地了解要在元素上使用哪些类

    最后 - 添加类似手风琴的行为

    • 假设您想要某种行为,例如Bootstrap accordion,其中展开一个项目将折叠任何其他已经打开的项目。
    • 下面是最简单的 JavaScript,它有一个手风琴控制器,当一个打开时关闭所有其他项目(目标)。
    • 当调用toggle 方法时,它会读取该事件的target,然后判断它是打开还是关闭。如果它正在打开,我们将遍历所有其他手风琴项目目标并关闭它们。
    import { Controller } from '@hotwired/stimulus';
    
    class AccordionController extends Controller {
      static targets = ['item'];
    
      toggle({ target }) {
        const isOpening = target.hasAttribute('open');
    
        if (isOpening) {
          // if opening - close the others
          this.itemTargets.forEach((item) => {
            if (item === target) return;
            item.removeAttribute('open');
          });
        }
      }
    }
    
    export default AccordionController;
    
    • 在 HTML 中,我们在外部容器上声明 data-controller="accordion"
    • 对于每个details 元素,我们添加两个属性:
      • data-accordion-target="item" - 这会将这个 details 元素限定为手风琴控制器的 this.itemTargets 数组。
      • data-action="toggle-&gt;accordion#toggle" - 这为details toggle 事件中的构建添加了一个事件侦听器,请注意此事件不会冒泡(与click 不同)因此我们需要在每个details 元素上使用它。
    <section class="prose m-5" data-controller="accordion">
      <h2>Multiple 'details' element into an accordion</h2>
      <details
        class="py-4 px-4"
        data-action="toggle->accordion#toggle"
        data-accordion-target="item"
        >
        <summary
          class="flex justify-between items-center text-xl font-bold
          cursor-pointer">
          Section A
        </summary>
        <div class="bg-[#F0F0F0] mb-2 py-6 px-4">
          Content
        </div>
      </details>
      <details
        class="py-4 px-4"
        data-action="toggle->accordion#toggle"
        data-accordion-target="item"
        >
        <summary
          class="flex justify-between items-center text-xl font-bold
          cursor-pointer">
          Section B
        </summary>
        <div class="bg-[#F0F0F0] mb-2 py-6 px-4">
          Content
        </div>
      </details>
      <details
        class="py-4 px-4"
        data-action="toggle->accordion#toggle"
        data-accordion-target="item"
        >
        <summary
          class="flex justify-between items-center text-xl font-bold
          cursor-pointer">
          Section C
        </summary>
        <div class="bg-[#F0F0F0] mb-2 py-6 px-4">
          Content
        </div>
      </details>
    </section>
    

    一般提示

    • 永远不要将div 用于可点击的东西,它只会让你很难过,始终使用buttontype="button"
    • 可访问性和details 元素存在一些细微差别,如果您的应用程序需要符合 AA 或更高标准,请确保您了解这些细微差别。

    【讨论】:

      【解决方案2】:

      How To - 使用 HTML5、CSS3 和最小 JS 的可折叠手风琴

      学习如何在网页上创建手风琴(可折叠内容)的基础知识:

      <!DOCTYPE html>
      <html>
      <head>
      <meta name="viewport" content="width=device-width, 
      initial-scale=1">
      <style>
      .accordion {
      background-color: #eee;
      color: #444;
      cursor: pointer;
      padding: 18px;
      width: 100%;
      border: none;
      text-align: left;
      outline: none;
      font-size: 15px;
      transition: 0.4s;
      }
      
      .active, .accordion:hover {
      background-color: #ccc; 
      }
      
      .panel {
      padding: 0 18px;
      display: none;
      background-color: white;
      overflow: hidden;
      }
      </style>
      </head>
      <body>
      
      <h2>Accordion</h2>
      
      <button class="accordion">Section 1</button>
      <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing 
      elit, sed do eiusmod tempor incididunt ut labore et dolore 
      magna aliqua. Ut enim ad minim veniam, quis nostrud 
      exercitation ullamco laboris nisi ut aliquip ex ea commodo 
      consequat.</p>
      </div>
      
      <button class="accordion">Section 2</button>
      <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing 
      elit, sed do eiusmod tempor incididunt ut labore et dolore 
      magna aliqua. Ut enim ad minim veniam, quis nostrud 
      exercitation ullamco laboris nisi ut aliquip ex ea commodo 
      consequat.</p>
      </div>
      
      <button class="accordion">Section 3</button>
      <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing 
      elit, sed do eiusmod tempor incididunt ut labore et dolore 
      magna aliqua. Ut enim ad minim veniam, quis nostrud 
      exercitation ullamco laboris nisi ut aliquip ex ea commodo 
      consequat.</p>
      </div>
      
      <script>
      var acc = document.getElementsByClassName("accordion");
      var i;
      
      for (i = 0; i < acc.length; i++) {
      acc[i].addEventListener("click", function() {
      this.classList.toggle("active");
      var panel = this.nextElementSibling;
      if (panel.style.display === "block") {
        panel.style.display = "none";
      } else {
        panel.style.display = "block";
      }
      });
      }
      </script>
      
      </body>
      </html>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-20
        • 1970-01-01
        • 2018-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-13
        • 1970-01-01
        相关资源
        最近更新 更多