我正在尝试根据其具有的子代数以编程方式计算和设置元素的max-height
样式。我必须在四个单独的元素上执行此操作,每个元素具有不同数量的子代,所以我不能只创建一个计算属性。我已经具有在函数中计算max-height
的逻辑,但是我无法将模板中的元素传递到函数中。
我没有运气就尝试过以下解决方案:
<div ref="div1" :style="{ maxHeight: getMaxHeight($refs.div1) }"></div>
这没有用,因为在将$refs
传递给函数时尚未定义它。
尝试将this
或$event.target
传递给getMaxHeight()
。这也不起作用,因为this
没有引用当前元素,并且由于我不在v-on
事件处理程序中,所以没有事件。
我唯一想到的另一种解决方案是创建四个计算属性,每个属性都使用getMaxHeight()
调用$ref
,但是如果我可以通过使用不同参数调用的单个函数来处理它,那将是易于维护。如果可能的话,我想从模板传递元素本身。有人知道这样做的方法,还是一种解决问题的更优雅的方法?
答案 0 :(得分:1)
做出一个直接在div元素上操作的自定义指令可能是您的最佳选择。您可以创建一个指令组件,例如:
export default {
name: 'maxheight',
bind(el) {
const numberOfChildren = el.children.length;
// rest of your max height logic here
el.style.maxHeight = '100px';
}
}
然后只需确保将指令导入您计划使用的文件中,并将其添加到div元素中:
<div ref="div1" maxheight></div>
答案 1 :(得分:1)
我在Vue上学到的一个便宜的技巧是,如果模板中需要任何在挂载模板时未加载的内容,则只需在模板上放置v-if:
<template v-if="$refs">
<div ref="div1" :style="{ maxHeight: getMaxHeight($refs.div1) }"></div>
</template>
周围。乍一看可能很脏,但事实是,它可以完成工作,而不会增加额外的代码和时间,并避免了错误。
此外,您的expandable
函数的代码长度略有改进:
const expandable = el => el.style.maxHeight =
( el.classList.contains('expanded') ?
el.children.map(c=>c.scrollHeight).reduce((h1,h2)=>h1+h2)
: 0 ) + 'px';
答案 2 :(得分:0)
我最终创建了一条建议的指令。它会在以下情况下尝试扩展/压缩:
<button @click="toggleAccordion($event.currentTarget.nextElementSibling)"></button>
<div @click="toggleAccordion($event.currentTarget)" v-accordion-toggle>
<myComponent v-for="data in dataList" :data="data"></myComponent>
</div>
.....
private toggleAccordion(elem: HTMLElement): void {
elem.classList.toggle("expanded");
}
Accordion.ts
const expandable = (el: HTMLElement) => el.style.maxHeight = (el.classList.contains("expanded") ?
[...el.children].map(c => c.scrollHeight).reduce((h1, h2) => h1 + h2) : "0") + "px";
Vue.directive("accordion-toggle", {
bind: (el: HTMLElement, binding: any, vnode: any) => {
el.onclick = ($event: any) => {
expandable($event.currentTarget) ; // When the element is clicked
};
// If the classes on the elem change, like another button adding .expanded class
const observer = new MutationObserver(() => expandable(el));
observer.observe(el, {
attributes: true,
attributeFilter: ["class"],
});
},
componentUpdated: (el: HTMLElement) => {
expandable(el); // When the component (or its children) update
}
});