Skip to content

Instantly share code, notes, and snippets.

@Canace22
Created September 3, 2023 05:34
Show Gist options
  • Save Canace22/725f72b43d1b01cd8f89c79a5f512106 to your computer and use it in GitHub Desktop.
Save Canace22/725f72b43d1b01cd8f89c79a5f512106 to your computer and use it in GitHub Desktop.
element-plus popover trigger virtual trigger example
<template>
<dev-trigger-ref
v-for="item in 5"
ref="triggerRefWrap"
:popperRef="popperRef"
:tag="item + ''"
@click="getTag"
>
<el-button>click me</el-button>
</dev-trigger-ref>
<dev-trigger-dropdown
ref="popoverRefWrap"
:triggerRef="triggerRef"
:visible="expanded"
>
<span>some content</span>
</dev-trigger-dropdown>
</template>
<script setup>
import useSelect from './useSelect';
import DevTriggerRef from './TriggerRef.vue';
import DevTriggerDropdown from './TriggerDropdown.vue';
const useSelectAPI = useSelect();
const {
triggerRefWrap,
triggerRef,
popoverRefWrap,
popperRef,
expanded,
getTag
} = useSelectAPI;
</script>
<style scoped>
.trigger-wrap {
display: inline-block;
}
</style>
<template>
<el-popover
ref="popoverRef"
:virtual-ref="triggerRef"
trigger="click"
virtual-triggering
:visible="visible"
popper-class="popper-class"
>
<slot></slot>
</el-popover>
</template>
<script setup>
import { ref, computed, defineProps, defineExpose } from 'vue';
const props = defineProps({
triggerRef: {
type: Object
},
visible: {
type: Boolean
}
});
const popoverRef = ref();
const popperRef = computed(() => popoverRef.value?.popperRef?.contentRef);
const triggerRef = computed(() => props.triggerRef);
const visible = computed(() => props.visible);
defineExpose({
popperRef,
popoverRef
});
</script>
<style lang="scss" scoped>
.trigger-wrap {
display: inline-block;
}
:deep(.el-popover.el-popper) {
min-width: 200px !important;
}
:deep(.popper-class){
min-width: 200px !important;
}
</style>
<template>
<div
class="trigger-wrap"
:name="tag"
:ref="(el) => setRef(el)"
@click.stop="toggleMenu"
v-click-outside:[popperRef]="handleClickOutside"
>
<slot></slot>
</div>
</template>
<script setup>
import {
ref,
computed,
nextTick,
defineProps,
defineExpose,
reactive,
defineEmits
} from 'vue';
import { ClickOutside as vClickOutside } from 'element-plus';
const props = defineProps({
popperRef: {
type: Object
},
disabled: {
type: Boolean,
default: false
},
tag: {
type: String,
default: 'default'
}
});
const emits = defineEmits(['click']);
const tag = computed(() => props.tag);
const triggerRef = reactive({});
const setRef = (el) => {
if (el) {
triggerRef[tag.value] = el;
return `triggerRef_${tag.value}`;
}
};
const handleClickOutside = () => {
expanded.value = false;
};
const selectDisabled = computed(() => {
return props.disabled;
});
const expanded = ref(false);
const toggleMenu = () => {
if (!selectDisabled.value) {
emits('click', tag.value);
expanded.value = !expanded.value;
// return nextTick(() => {
// emits('click', tag.value);
// expanded.value = !expanded.value;
// });
}
};
defineExpose({
triggerRef,
tag,
expanded
});
</script>
<style scoped>
.trigger-wrap {
display: inline-block;
}
</style>
import { ref, computed, reactive } from 'vue';
const useSelect = () => {
const tag = ref('');
const getTag = (val) => {
tag.value = val;
};
const triggerRefWrap = ref();
const triggerRef = computed(() => {
return triggerRefWrap?.value?.find((v) => v.tag === tag.value)?.triggerRef[
tag.value
];
});
const popoverRefWrap = ref();
const popperRef = computed(() => {
return popoverRefWrap?.value?.popoverRef?.popperRef?.contentRef;
});
const expanded = computed(
() => triggerRefWrap?.value?.find((v) => v.tag === tag.value)?.expanded
);
const dropdownMenuVisible = computed(() => expanded.value);
return {
triggerRefWrap,
triggerRef,
popoverRefWrap,
popperRef,
expanded,
getTag,
dropdownMenuVisible
};
};
export default useSelect;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment