代码之家  ›  专栏  ›  技术社区  ›  Tzar

如何在特定上下文中使用queryselectorall

  •  1
  • Tzar  · 技术社区  · 6 年前

    我正在使用 Animate Plus 手风琴的动画。我有多个定义列表( dl )我想把他们都作为目标,而不仅仅是第一个。

    以下是相关代码:

    const accordion = {
      element: document.querySelector("dl"),
      translate: 0
    }
    
    const buttons = Array.from(
      accordion.element.getElementsByTagName("button"),
      element => ({
        element,
        translate: 0
      })
    )
    

    我试图转换成一个数组并使用扩散运算符 […document.querySelectorAll("dl")] 但没有成功。

    我如何使用 querySelectorAll 在这个特定的上下文中 动态链接库 标签?

    我的手风琴示例如下: https://codepen.io/anon/pen/QYwQqV

    2 回复  |  直到 6 年前
        1
  •  0
  •   jo_va    6 年前

    这是更新的 科德森 使用 Array.from(document.querySelectorAll('dl')) 瞄准每一个目标 dl 在文档中:

    https://codepen.io/jo_va/pen/OdVpbJ

    由于现在有多个手风琴,我首先构建了一个手风琴数组,修改了几乎所有的函数,以手风琴和按钮列表作为第一个参数。

    最后,您只需迭代手风琴并执行您拥有的相同逻辑,但要为当前手风琴及其按钮参数化。

    const accordions = Array.from(document.querySelectorAll("dl")).map(dl => ({
      element: dl,
      translate: 0
    }))
    
    const getButtons = accordion => Array.from(
        accordion.element.getElementsByTagName("button"),
        element => ({
            element,
            translate: 0
        })
    )
    
    const timing = {
        easing: "out-quartic",
        duration: 400
    }
    
    const clear = element =>
        Object.values(element.attributes).forEach(({ name }) =>
            element.removeAttribute(name)
        )
    
    const hide = async (accordion, buttons, collapsing) => {
        const objects = buttons.filter(({ translate }) => translate)
        const direction = "reverse"
        rotate(collapsing.previousElementSibling.lastElementChild, direction)
        slide(accordion, objects)
        await fold(collapsing, direction)
        clear(collapsing)
    }
    
    const show = (accordion, buttons, expanding) => {
        const button = expanding.previousElementSibling.lastElementChild
        const index = buttons.findIndex(({ element }) => element == button)
        const objects = buttons.slice(index + 1)
        const { height } = expanding.getBoundingClientRect()
        expanding.className = "open"
        rotate(button)
        slide(accordion, objects, height)
        fold(expanding)
    }
    
    const slide = (accordion, array, to = 0) => {
        center(accordion, to)
        animate({
            ...timing,
            elements: array.map(({ element }) => element.parentElement),
            transform(index) {
                const object = array[index]
                const from = object.translate
                object.translate = to
                return [`translateY(${from}px)`, to]
            }
        })
    }
    
    const center = (accordion, height) => {
        const from = accordion.translate
        const to = Math.round(-height / 2)
        accordion.translate = to
        animate({
            ...timing,
            elements: accordion.element,
            transform: [`translateY(${from}px)`, to]
        })
    }
    
    const fold = async (content, direction = "normal") =>
        await animate({
            ...timing,
            direction,
            elements: content,
            opacity: [0, 1],
            transform: ["scaleY(0)", 1]
        })
    
    const rotate = ({ lastElementChild: elements }, direction = "normal") =>
        animate({
            elements,
            direction,
            easing: "out-cubic",
            duration: 600,
            transform: ["rotate(0turn)", 0.5]
        })
    
    const toggle = (accordion, buttons) => async ({ target }) => {
        const collapsing = accordion.element.querySelector(".open")
        const expanding = target.parentElement.nextElementSibling
        if (collapsing) await hide(accordion, buttons, collapsing)
        if (collapsing != expanding) show(accordion, buttons, expanding)
    }
    
    accordions.forEach(accordion => {
      const buttons = getButtons(accordion)
      buttons.forEach(
        ({ element }) => element.addEventListener("click", toggle(accordion, buttons))
      )
    })
    
    import animate from "https://cdn.jsdelivr.net/npm/animateplus@2/animateplus.js"
    

    我希望我能正确理解你的问题,这对你有帮助。

    干杯。

        2
  •  0
  •   Val Geyvandov    6 年前

    这个怎么样?

    // collect all dl elements
    const accordion = {
      definitionLists: Array.from(document.querySelectorAll("dl")),
      translate: 0
    }
    
    // get all button elements inside of each dl in a single array
    const buttons = accordion.definitionLists.reduce((acc, dl) => {
      let currentDlButtons = Array.from(dl.getElementsByTagName("button"), 
       element => ({
         element,
         translate: 0
        }));
      return acc.concat(currentDlButtons);
    }, []);