import { provide,inject, computed, createVNode, defineComponent, render,reactive, onMounted, ref, onBeforeUnmount } from 'vue'
export const DropdownItem = defineComponent({
props:{
label: String,
icon: String,
},
emits: ['click'],
setup(props, { emit }){
// eslint-disable-next-line vue/no-setup-props-destructure
const { label,icon } = props
const hide: any = inject('hide')
return () =>
{
hide()
emit('click')
}}>
{label}
},
})
const DropdownComponent = defineComponent({
props:{
option:{ type:Object },
},
setup(props,ctx){
const state = reactive({
option:props.option,
isShow:false,
top:0,
left:0,
})
ctx.expose({
showDropdown(option){
state.option = option
state.isShow = true
const { top,left,height } = option.el.getBoundingClientRect()
state.top = top + height
state.left = left
},
})
provide('hide',()=>state.isShow = false)
const classes = computed(()=>[
'dropdown',
{
'dropdown-isShow': state.isShow,
},
])
const styles = computed(()=>({
top:state.top+'px',
left:state.left + 'px',
}))
const el = ref(null)
const onMousedownDocument = e=>{
if(!el.value.contains(e.target)){ // 如果点击的是dropdown内部 什么都不做
state.isShow = false
}
}
onMounted(()=>{
// 事件的传递行为是先捕获 在冒泡
// 之前为了阻止事件传播 我们给block 都增加了stopPropagation
document.body.addEventListener('mousedown', onMousedownDocument,true)
})
onBeforeUnmount(()=>{
document.body.removeEventListener('mousedown', onMousedownDocument)
})
return ()=>{
return
{state.option.content()}
}
},
})
let vm
export function $dropdown(option){
// element-plus中是有el-dialog组件
// 手动挂载组件 new SubComponent.$mount()
if(!vm){
const el = document.createElement('div')
vm = createVNode(DropdownComponent,{ option }) // 将组件渲染成虚拟节点
// 这里需要将el 渲染到我们的页面中
document.body.appendChild((render(vm,el),el)) // 渲染成真实节点扔到页面中
}
// 将组件渲染到这个el元素上
const { showDropdown } = vm.component.exposed
showDropdown(option) // 其他说明组件已经有了只需要显示出来即可
}