![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3ebc18c322d3ccc53b206225d4115ef4.png)
效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/821439db54a0f55e6ff950d1e8e507c8.png)
PopperInput.vue文件
<template>
<div
class="popper-input"
ref="popperInputRef"
:style="{ top: `${top}px`, left: `${left}px` }"
>
<div class="arrow"></div>
<div class="create-action create-tag" :style="{ width: `${176}px` }">
<el-input
type="number"
v-model.trim="input"
size="small"
maxlength="10"
style="width: 100%"
></el-input>
<div class="btn">
<el-button type="text" size="mini" @click="handleConfirm"
>确定</el-button
>
<el-button type="text" size="mini" @click="handleHide">取消</el-button>
</div>
</div>
</div>
</template>
<script>
import PopperInput from "./index";
export default {
name: "PopperInput",
props: {
dom: {},
inputValue: {
type: String,
default: "",
},
},
data() {
return {
input: "",
top: 0,
left: 0,
};
},
watch: {
inputValue: {
immediate: true,
handler: function (newV) {
this.input = newV;
},
},
},
mounted() {
this.handlePosition();
window.addEventListener("scroll", this.handlePosition.bind(this), true);
},
methods: {
handleHide() {
PopperInput.hide();
},
handlePosition() {
const rect = this.dom.getBoundingClientRect();
const popperWidth = 200;
this.top = rect.top + rect.height + 10;
this.left = rect.left - popperWidth / 2 + rect.width / 2;
},
handleConfirm() {
PopperInput.confirm(this.input);
},
},
};
</script>
<style lang="scss" scoped>
.popper-input {
position: absolute;
top: 50%;
left: 50%;
background: #fff;
min-width: 150px;
border-radius: 4px;
border: 1px solid #ebeef5;
padding: 12px;
z-index: 2000;
color: #606266;
line-height: 1.4;
text-align: justify;
font-size: 14px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
word-break: break-all;
.arrow {
position: absolute;
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
border-top-width: 0;
border-bottom-color: #b5b5b5;
top: -6px;
left: 50%;
transform: translateX(-50%);
&::after {
display: block;
border-color: transparent;
border-style: solid;
content: " ";
border-width: 6px;
border-top-width: 0;
border-bottom-color: #fff;
transform: translateX(-50%);
}
}
}
.create-action {
display: flex;
align-items: center;
justify-content: center;
}
.create-tag {
width: 230px;
justify-content: flex-start;
.el-input {
width: 165px;
}
.btn {
display: flex;
flex-direction: row;
.el-button {
margin-left: 3px;
}
}
}
</style>
index.js
import Vue from 'vue';
import _PopperInput from "./PopperInput"
let defaultCallBack, popperInput
Vue.component(_PopperInput.name, _PopperInput)
const PopperInput = {
show: function (props, callback) {
if (!popperInput) {
const PopperInput = Vue.extend({
render(h) {
return h('popper-input', { props })
}
})
popperInput = new PopperInput()
this.vm = popperInput.$mount()
document.body.appendChild(this.vm.$el)
callback && (defaultCallBack = callback)
}
},
confirm: function (val) {
console.log(popperInput);
defaultCallBack(val)
},
hide: function () {
document.body.removeChild(this.vm.$el)
popperInput.$destroy()
popperInput = null
this.vm = null
}
}
export default PopperInput;
export { PopperInput };
在vue文件中使用
<template>
<button @click="handlePop($event)">弹窗</button>
</template>
<script>
import PopperInput from "@/components/public/PopperInput";
export defalut{
methods:{
handlePop(event){
PopperInput.show({
dom: event.target,
inputValue: "",
},
(value) => {
console.log(value);
}
);
}
}
}
</script>