首页 > 解决方案 > 你可以将元素传递给 Vue 模板中的函数吗?

问题描述

我正在尝试根据元素的max-height数量以编程方式计算和设置元素的样式。我必须在四个单独的元素上执行此操作,每个元素都有不同数量的子元素,所以我不能只创建一个计算属性。我已经有了计算max-height函数中的逻辑,但是我无法将模板中的元素传递给函数。

我尝试了以下解决方案,但没有成功:

  1. <div ref="div1" :style="{ maxHeight: getMaxHeight($refs.div1) }"></div>
    这不起作用,因为$refs在我将它传递给函数时尚未定义。

  2. 试图传球this$event.target传球getMaxHeight()。这也不起作用,因为this它没有引用当前元素,并且没有事件,因为我不在v-on事件处理程序中。

我能想到的唯一其他解决方案是创建四个计算属性,每个都getMaxHeight()使用$ref. 如果可能的话,我想从模板中传递元素本身。有谁知道这样做的方法,或更优雅的方法来解决这个问题?

标签: javascriptvue.jsvuejs2

解决方案


我最终创建了一个建议的指令。它在以下情况下尝试扩展/压缩:

  • 被点击了
  • 它的类改变
  • 元素或其子元素更新


Vue组件:

<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
    }
});

推荐阅读