Javascript 如何在特定上下文中使用querySelectorAll
我正在用手风琴制作动画。我有多个定义列表(Javascript 如何在特定上下文中使用querySelectorAll,javascript,ecmascript-6,animateplus,Javascript,Ecmascript 6,Animateplus,我正在用手风琴制作动画。我有多个定义列表(dl),我希望将它们全部作为目标,而不仅仅是第一个 以下是相关代码: const accordion = { element: document.querySelector("dl"), translate: 0 } const buttons = Array.from( accordion.element.getElementsByTagName("button"), element => ({ element,
dl
),我希望将它们全部作为目标,而不仅仅是第一个
以下是相关代码:
const accordion = {
element: document.querySelector("dl"),
translate: 0
}
const buttons = Array.from(
accordion.element.getElementsByTagName("button"),
element => ({
element,
translate: 0
})
)
我试图转换为数组并使用扩展运算符[…document.queryselectoral(“dl”)]
,但没有成功
如何在此特定上下文中使用querySelectorAll
以所有dl
标记为目标
我的手风琴示例可在此处找到:
下面是使用数组更新的代码笔。从(document.querySelectorAll('dl')到文档中的每个
dl
:
由于现在有多个手风琴,我首先构建了一个手风琴数组,并修改了几乎所有的函数,将手风琴和按钮列表作为第一个参数
最后,您只需在accordion上迭代并执行与之前相同的逻辑,但对当前accordion及其按钮进行了参数化
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"
我希望我正确理解了你的问题,这对你有帮助
干杯。这个怎么样:
// 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);
}, []);
正如您对
.getElementsByTagName()
和Array.from()
@Andreas所做的一样,这是我在尝试时遇到的错误:undefined不是对象(计算'accordion.element.getElementsByTagName')
在const按钮下
。这应该是问题的一部分,而不仅仅是一条评论…@Andreas我也尝试过使用你的评论作为指导来修复它,但无法修复,你认为你可以修改代码笔使其工作吗?你会得到我的支持:-)@Andreas What Islam写道——你能发布一个有效的解决方案作为答案,这样我就可以接受并支持它。我尝试过,但出于某种原因,它对我不起作用。这是我得到的错误:accordion.element.getElementsByTagName不是函数。(在“accordion.element.getElementsByTagName(“按钮”)中,“accordion.element.getElementsByTagName”未定义)
您能把答案扩大一点吗?谢谢。@Tzar,它可能失败了,因为querySelectorAll
生成了一个列表元素集合,使accordion.element
成为一个没有getElementsByTagName
方法的数组。请参阅我的解决方案,处理从dl
s数组中收集按钮
元素的问题。@Tzar,我已经更新了答案并包含了解决方案的代码笔,它对两种手风琴都有效。嘿@jo_va,我发现了一个问题。转换现在不会应用于dl
s。如果你检查我的代码笔,你会看到当你点击一个按钮时,整个dl
向上移动了dd
的高度。在你的解决方案中,它保持不变。嗨@Tzar,我修改了代码笔,它现在工作了,我将编辑答案。