如何避免在相似的 Vue 组件中重复 props?

How can I avoid duplicating props across similar Vue components?

组件结构:

我的应用程序中有许多 button 组件,每个组件中都有不同的 icon(我已将这些 icons 放在它们自己的组件中,以便我可以使用它们别处)。我希望这些 icon 组件在父组件悬停时响应 hover 事件。

我有一个解决方案,但其中有重复。对于每个按钮(SettingsButtonHelpButton 等),我发现自己编写了 hover 代码以便将其传递给 icon 组件。有没有办法避免这种情况?

Click here 用于 JS fiddle 示例。

const { ref } = Vue;

const HelpIcon = {
    template: `<div :style="{ 'background': hover ? 'blue' : '' }"></div>`,

    props: {
        hover: {
            type: Boolean,
            required: true,
        },
    },
};

const BaseButton = {
    template: `
        <a href="/" @click.prevent>
            <slot name="icon" />

            <span>
                <slot name="text" />
            </span>
        </a>
    `,
};

const HelpButton = {
    components: { BaseButton, HelpIcon },

    // _every_ button has to have `mouseover`, `mouseleave` and `hover` ref
    template: `
        <BaseButton @mouseover="hover = true" @mouseleave="hover = false">
            <template #icon>
                <HelpIcon :hover="hover" />
            </template>

            <template #text>Help</template>
        </BaseButton>
    `,

    setup() {
        // _every_ button has this ref
        const hover = ref(false);
        return { hover };
    }
};

Vue.createApp({
    components: { HelpButton },
}).mount('#app');

您可以使用 mixin,例如:

const hoverable={
    props: {
        hover: {
            type: Boolean,
            required: true,
        },
    },   
}

然后将其添加到您的图标混合选项中:

const HelpIcon = {
    template: `<div :style="{ 'background': hover ? 'blue' : '' }"></div>`,
     mixins:[hoverable]
};

也尝试在 BaseButton 中注册事件处理程序,然后通过作用域插槽传递 hover :

const BaseButton = {
    template: `
        <a href="/" @click.prevent  @mouseover="hover = true" @mouseleave="hover = false">
            <slot name="icon" :hover="hover" />
          
            <span>
                <slot name="text" />
            </span>
        </a>
    `,
 setup() {
        const hover = ref(false);
        return { hover };
    }
};

然后 :

 <BaseButton >
            <template #icon="{hover}" >
                <HelpIcon :hover="hover" />
            </template>

            <template #text>Help</template>
 </BaseButton>

LIVE DEMO