如何基于Vue 2.6与DevExtreme构建可复用组件以避免代码重复?
解决Vue2.6+DevExtreme图标与Tooltip的封装问题
问题背景
使用Vue 2.6和DevExtreme开发时,图标搭配Tooltip的逻辑存在大量重复(如控制显示状态的变量、鼠标事件),尝试封装v-icon-tooltip组件但未生效,需要实现可复用的图标+Tooltip组件。
现有重复代码(工作状态)
模板部分
<div> ... <template #icon> <i id="icon1" class="dx-icon-refresh icon-cursor" @click="getReferralLink" readonly @mouseenter="toggleDefault1" @mouseleave="toggleDefault1" /> <v-dx-tool-tip :visible="defaultVisible1" :hide-on-outside-click="false" target="#icon1">Get link</v-dx-tool-tip> <i id="icon2" class="dx-icon-copy icon-cursor" @click="copyReferralLink" readonly @mouseenter="toggleDefault2" @mouseleave="toggleDefault2" /> <v-dx-tool-tip :visible="defaultVisible2" :hide-on-outside-click="false" target="#icon2">Copy to clipboard</v-dx-tool-tip> </template> ... </div>
脚本部分
import { DxTooltip } from 'devextreme-vue/tooltip'; @Component({ components: { 'v-dx-tool-tip': DxTooltip, }, }) export default class ExtendedDetailAccountComponent extends mixins(CurrentUserMixin) { ... defaultVisible1 = false; defaultVisible2 = false; toggleDefault1() { this.defaultVisible1 = !this.defaultVisible1; } toggleDefault2() { this.defaultVisible2 = !this.defaultVisible2; } async getReferralLink() { // 业务逻辑 } copyReferralLink() { // 业务逻辑 } ... }
未成功的封装尝试
父组件使用代码
<div> ... <template #icon> <v-icon-tooltip :id="icon1" class="dx-icon-refresh icon-cursor" tooltipText="Get link" @click="getReferralLink" /> <v-icon-tooltip :id="icon2" class="dx-icon-copy icon-cursor" tooltipText="Copy to clipboard" @click="copyReferralLink" /> </template> </v-text-input> </div>
组件注册代码
import VIconTooltip from './v-icon-tooltip.vue'; @Component({ components: { VIconTooltip, }, }) export default class ExtendedDetailAccountComponent extends mixins(CurrentUserMixin) { ... async getReferralLink() { // 业务逻辑 } copyReferralLink() { // 业务逻辑 } ... }
待修正的v-icon-tooltip.vue组件
<template> <div> <i :id="id" v-bind="$attrs" readonly @mouseenter="toggle" @mouseleave="toggle" v-on="$listeners" /> <DxTooltip :visible="visible" :hide-on-outside-click="false" target="id">{{ tooltipText }}</DxTooltip> </div> </template> <script> import { DxTooltip } from 'devextreme-vue/tooltip'; export default { inheritAttrs: false, components: { DxTooltip, }, props: { id: { type: String }, tooltipText: { type: String }, }, data() { return { visible: false, } }, methods: { toggle() { this.visible = !this.visible; } } } </script>
修正后的组件实现
问题点分析
- Tooltip目标绑定错误:
DxTooltip的target属性需要带#前缀(CSS选择器格式),原代码直接写target="id"未绑定变量且缺少前缀。 - 属性绑定优先级问题:
readonly直接写在标签上会被v-bind="$attrs"覆盖,需要调整位置确保生效。 - id传参错误:父组件中
:id="icon1"会将icon1解析为变量,应改为字符串形式id="icon1"。
修正后的v-icon-tooltip.vue
<template> <div> <i :id="id" v-bind="$attrs" v-on="$listeners" readonly @mouseenter="toggle" @mouseleave="toggle" /> <DxTooltip :visible="visible" :hide-on-outside-click="false" :target="`#${id}`" > {{ tooltipText }} </DxTooltip> </div> </template> <script> import { DxTooltip } from 'devextreme-vue/tooltip'; export default { inheritAttrs: false, components: { DxTooltip, }, props: { id: { type: String, required: true // 强制传入id,避免绑定错误 }, tooltipText: { type: String, required: true }, }, data() { return { visible: false, } }, methods: { toggle() { this.visible = !this.visible; } } } </script>
修正后的父组件使用代码
<div> ... <template #icon> <v-icon-tooltip id="icon1" class="dx-icon-refresh icon-cursor" tooltipText="Get link" @click="getReferralLink" /> <v-icon-tooltip id="icon2" class="dx-icon-copy icon-cursor" tooltipText="Copy to clipboard" @click="copyReferralLink" /> </template> </v-text-input> </div>
效果说明
修正后组件可独立管理自身Tooltip的显示状态,父组件无需维护多个visible变量和toggle方法,完全复用图标+Tooltip的交互逻辑,代码简洁性和可维护性大幅提升。
内容的提问来源于stack exchange,提问作者tesicg
相关产品推荐
相关产品推荐

