vue2中使用element对话框组件实现拖拽
在上面的代码中,我们通过自定义指令实现了对话框的拖拽功能。下面我们将进行全局封装方便使用:新建directives文件夹里面创建draggable.js和index.jsdirectives文件夹主要存放全局的自定义指令draggable.js是我们封装的拖拽功能index.js为/统一注册指令,方便管理1.创建draggable.js// 拖拽指令bind(el) {// 获取弹窗头部元素//
·
在Vue2项目中,Element UI是一个非常流行的UI组件库,提供了丰富的组件来帮助开发者快速构建用户界面。本文将介绍如何在Vue2项目中使用Element UI的对话框组件(el-dialog
)实现拖拽功能。
目录
1. 项目结构
首先,确保你的项目中已经安装了Element UI。如果没有安装,可以通过以下命令进行安装:
npm install element-ui --save
然后在你的Vue项目中引入Element UI:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
2. 实现拖拽功能的对话框组件
接下来,我们将创建一个包含表格和对话框的组件,并在对话框中实现拖拽功能。
直接复制即可食用
<template>
<div>
<!-- 表格展示 -->
<el-table :data="tableData" style="width: 100%" border>
<!-- 表格列定义 -->
<el-table-column
prop="name"
label="名称"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
prop="standard"
label="标准值"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
prop="expected"
label="期望值"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
prop="experience"
label="经验值"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
prop="warning"
label="预警值"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
prop="emergency"
label="紧急值"
width="180"
header-align="center"
align="center"
></el-table-column>
<el-table-column
label="操作"
width="120"
header-align="center"
align="center"
>
<!-- 操作按钮 -->
<template slot-scope="scope">
<el-button @click="handleEdit(scope.row)" type="primary" size="small"
>编辑</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 可拖拽的弹窗 -->
<el-dialog
width="50%"
:visible.sync="dialogVisible"
title="编辑"
v-draggable
>
<!-- 表单 -->
<el-form
:model="editForm"
:rules="rules"
ref="editFormRef"
label-width="100px"
>
<!-- 表单项 -->
<el-form-item label="名称:">
<el-input v-model="editForm.name" disabled></el-input>
</el-form-item>
<el-form-item label="标准值:" prop="standard">
<el-input
v-model="editForm.standard"
placeholder="请输入标准值"
></el-input>
</el-form-item>
<el-form-item label="期望值:" prop="expected">
<el-input
v-model="editForm.expected"
placeholder="请输入期望值"
></el-input>
</el-form-item>
<el-form-item label="经验值:" prop="experience">
<el-input
v-model="editForm.experience"
placeholder="请输入经验值"
></el-input>
</el-form-item>
<el-form-item label="预警值:" prop="warning">
<el-input
v-model="editForm.warning"
placeholder="请输入预警值"
></el-input>
</el-form-item>
<el-form-item label="紧急值:" prop="emergency">
<el-input
v-model="editForm.emergency"
placeholder="请输入紧急值"
></el-input>
</el-form-item>
</el-form>
<!-- 弹窗底部按钮 -->
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSave">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
// 输入验证函数
const validateInput = (rule, value, callback) => {
const regex = /^([<>]=?|=)?\d+$/; // 允许的格式:符号和数字
if (value && !regex.test(value)) {
callback(new Error("输入格式不正确,只能包含符号和数字"));
} else {
callback();
}
};
return {
tableData: [], // 表格数据
dialogVisible: false, // 控制弹窗显示
editForm: {
name: "",
standard: "",
expected: "",
experience: "",
warning: "",
emergency: "",
}, // 表单数据
rules: {
standard: [{ validator: validateInput, trigger: "blur" }],
expected: [{ validator: validateInput, trigger: "blur" }],
experience: [{ validator: validateInput, trigger: "blur" }],
warning: [{ validator: validateInput, trigger: "blur" }],
emergency: [{ validator: validateInput, trigger: "blur" }],
}, // 表单验证规则
};
},
mounted() {
// 模拟后端返回的数据
const backendData = {
name: "项目2",
standard: {
original: ">100",
symbol: ">",
number: "100",
},
expected: {
original: "<100",
symbol: "<",
number: "100",
},
experience: {
original: "<100",
symbol: "<",
number: "100",
},
warning: {
original: "<100",
symbol: "<",
number: "100",
},
emergency: {
original: "<100",
symbol: "<",
number: "100",
},
};
// 格式化数据以便在表格中显示
this.tableData = [
{
name: backendData.name,
standard: backendData.standard.original,
expected: backendData.expected.original,
experience: backendData.experience.original,
warning: backendData.warning.original,
emergency: backendData.emergency.original,
},
];
},
methods: {
// 编辑按钮点击事件
handleEdit(row) {
this.editForm = { ...row };
this.dialogVisible = true;
},
// 保存按钮点击事件
handleSave() {
this.$refs.editFormRef.validate((valid) => {
if (valid) {
// 分离符号和数字,并添加原始内容字段
const result = {};
for (let key in this.editForm) {
const match = this.editForm[key].match(/^([<>]=?|=)?(\d+)$/);
if (match) {
result[key] = {
original: this.editForm[key],
symbol: match[1] || "",
number: match[2],
};
}
}
// 这里可以调用API传递数据给后端
console.log(result, "result");
this.dialogVisible = false;
} else {
console.log("表单验证失败");
return false;
}
});
},
},
directives: {
// 自定义指令:实现弹窗拖拽功能
draggable: {
// bind钩子函数在指令第一次绑定到元素时调用
bind(el) {
// 获取弹窗头部元素
const dialogHeaderEl = el.querySelector(".el-dialog__header");
// 获取整个弹窗元素
const dragDom = el.querySelector(".el-dialog");
// 设置鼠标样式为移动
dialogHeaderEl.style.cursor = "move";
// 监听鼠标按下事件
dialogHeaderEl.onmousedown = (e) => {
// 计算鼠标相对弹窗头部的偏移量
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取可视区域的宽高
const screenWidth = document.body.clientWidth;
const screenHeight = document.body.clientHeight;
// 获取弹窗的宽高
const dragDomWidth = dragDom.offsetWidth;
const dragDomHeight = dragDom.offsetHeight;
// 计算可移动范围的边界值
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight;
// 用于存储弹窗的位置信息
let styL, styT;
// 处理弹窗位置的百分比值转换为像素值
if (window.getComputedStyle(dragDom).left.includes("%")) {
// 如果位置使用百分比,转换为像素值
styL =
+document.body.clientWidth *
(+window.getComputedStyle(dragDom).left.replace(/%/g, "") / 100);
styT =
+document.body.clientHeight *
(+window.getComputedStyle(dragDom).top.replace(/%/g, "") / 100);
} else {
// 如果位置使用像素值,直接获取数值
styL = +window.getComputedStyle(dragDom).left.replace(/px/g, "");
styT = +window.getComputedStyle(dragDom).top.replace(/px/g, "");
}
// 监听鼠标移动事件
document.onmousemove = function (e) {
// 计算新的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
// 限制左右移动范围
if (-left > minDragDomLeft) {
left = -minDragDomLeft;
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
// 限制上下移动范围
if (-top > minDragDomTop) {
top = -minDragDomTop;
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 更新弹窗位置
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
// 监听鼠标松开事件
document.onmouseup = function () {
// 清除鼠标移动和松开事件的监听
document.onmousemove = null;
document.onmouseup = null;
};
};
},
},
},
};
</script>
<style>
/* 自定义样式 */
.el-table th {
background-color: #f5f7fa;
color: #333;
font-weight: bold;
}
.dialog-footer {
text-align: right;
}
</style>
3. 封装拖拽的全局自定义指令
在上面的代码中,我们通过自定义指令v-draggable
实现了对话框的拖拽功能。下面我们将进行全局封装方便使用:
新建directives文件夹里面创建draggable.js和index.js
directives文件夹主要存放全局的自定义指令
draggable.js是我们封装的拖拽功能
index.js为/统一注册指令,方便管理
3.1创建draggable.js
//src\directives\draggable.js
// 拖拽指令
export const draggable = {
bind(el) {
// 获取弹窗头部元素
const dialogHeaderEl = el.querySelector(".el-dialog__header");
// 获取整个弹窗元素
const dragDom = el.querySelector(".el-dialog");
// 设置鼠标样式为移动
dialogHeaderEl.style.cursor = "move";
// 监听鼠标按下事件
dialogHeaderEl.onmousedown = (e) => {
// 计算鼠标相对弹窗头部的偏移量
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取可视区域的宽高
const screenWidth = document.body.clientWidth;
const screenHeight = document.body.clientHeight;
// 获取弹窗的宽高
const dragDomWidth = dragDom.offsetWidth;
const dragDomHeight = dragDom.offsetHeight;
// 计算可移动范围的边界值
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight;
// 用于存储弹窗的位置信息
let styL, styT;
// 处理弹窗位置的百分比值转换为像素值
if (window.getComputedStyle(dragDom).left.includes("%")) {
styL =
+document.body.clientWidth *
(+window.getComputedStyle(dragDom).left.replace(/%/g, "") / 100);
styT =
+document.body.clientHeight *
(+window.getComputedStyle(dragDom).top.replace(/%/g, "") / 100);
} else {
styL = +window.getComputedStyle(dragDom).left.replace(/px/g, "");
styT = +window.getComputedStyle(dragDom).top.replace(/px/g, "");
}
// 监听鼠标移动事件
document.onmousemove = function (e) {
// 计算新的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
// 限制左右移动范围
if (-left > minDragDomLeft) {
left = -minDragDomLeft;
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
// 限制上下移动范围
if (-top > minDragDomTop) {
top = -minDragDomTop;
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 更新弹窗位置
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
// 监听鼠标松开事件
document.onmouseup = function () {
// 清除鼠标移动和松开事件的监听
document.onmousemove = null;
document.onmouseup = null;
};
};
},
};
3.2.创建index.js.
import { draggable } from './draggable'
// 统一注册指令
export default {
install(Vue) {
Vue.directive('draggable', draggable)
// 这里可以注册更多的全局指令
}
}
3.3.全局引用
3.4.使用方法
在需要使用的地方加上v-draggable即可
4. 总结
通过以上步骤,我们成功在Vue2项目中使用Element UI的对话框组件实现了拖拽功能。这个功能可以提升用户体验,特别是在需要频繁操作对话框的场景中。希望本文对你有所帮助!
更多推荐
所有评论(0)