Vue实现拖拽穿梭框功能四种方式
一、使用原生js实现拖拽
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Lazyload</title>
<style>
.drag {
background-color: skyblue;
position: absolute;
line-height: 100px;
text-align: center;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<!-- left和top要写在行内样式里面 -->
<div class="drag" style="left: 0; top: 0">按住拖动</div>
<script src="./jquery-3.6.0.min.js"></script>
<script>
// 获取DOM元素
let dragDiv = document.getElementsByClassName('drag')[0]
// 鼠标按下事件 处理程序
let putDown = function (event) {
dragDiv.style.cursor = 'pointer'
let offsetX = parseInt(dragDiv.style.left) // 获取当前的x轴距离
let offsetY = parseInt(dragDiv.style.top) // 获取当前的y轴距离
let innerX = event.clientX - offsetX // 获取鼠标在方块内的x轴距
let innerY = event.clientY - offsetY // 获取鼠标在方块内的y轴距
// 按住鼠标时为div添加一个border
dragDiv.style.borderStyle = 'solid'
dragDiv.style.borderColor = 'red'
dragDiv.style.borderWidth = '3px'
// 鼠标移动的时候不停的修改div的left和top值
document.onmousemove = function (event) {
dragDiv.style.left = event.clientX - innerX + 'px'
dragDiv.style.top = event.clientY - innerY + 'px'
// 边界判断
if (parseInt(dragDiv.style.left) <= 0) {
dragDiv.style.left = '0px'
}
if (parseInt(dragDiv.style.top) <= 0) {
dragDiv.style.top = '0px'
}
if (
parseInt(dragDiv.style.left) >=
window.innerWidth - parseInt(dragDiv.style.width)
) {
dragDiv.style.left =
window.innerWidth - parseInt(dragDiv.style.width) + 'px'
}
if (
parseInt(dragDiv.style.top) >=
window.innerHeight - parseInt(dragDiv.style.height)
) {
dragDiv.style.top =
window.innerHeight - parseInt(dragDiv.style.height) + 'px'
}
}
// 鼠标抬起时,清除绑定在文档上的mousemove和mouseup事件
// 否则鼠标抬起后还可以继续拖拽方块
document.onmouseup = function () {
document.onmousemove = null
document.onmouseup = null
// 清除border
dragDiv.style.borderStyle = ''
dragDiv.style.borderColor = ''
dragDiv.style.borderWidth = ''
}
}
// 绑定鼠标按下事件
dragDiv.addEventListener('mousedown', putDown, false)
</script>
</body>
</html>
二、VUe使用js实现拖拽穿梭框
<template>
<div>
<h3 style="text-align: center">拖拽穿梭框</h3>
<div id="home" @mousemove="mousemove($event)">
<div class="tree-select-content">
<span
class="select-content"
:id="'mouse' + index"
v-for="(item, index) in leftData"
:key="item.id"
@mousedown="mousedown(index, 1)"
@mouseup="mouseup(item, 1, index)"
>
<span class="select-text">{{ item.label }}</span>
<span class="select-text-X" @click="handerClickX(item, index, 1)"
>X</span
>
</span>
</div>
<div class="tree-select-content">
<span
class="select-content"
:id="'deleteMouse' + index"
v-for="(item, index) in rightData"
:key="item.id"
@mousedown="mousedown(index, 2)"
@mouseup="mouseup(item, 2, index)"
>
<span class="select-text">{{ item.label }}</span>
<span class="select-text-X" @click="handerClickX(item, index, 2)"
>X</span
>
</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "home",
data() {
return {
leftData: [
{ label: "首页", id: 1 },
{ label: "咨询", id: 2 },
{ label: "生活", id: 3 },
{ label: "财富", id: 4 },
{ label: "我的", id: 5 },
],
rightData: [{ label: "世界", id: 6 }],
isMoveTrue: false,
isMove: false,
moveId: "",
};
},
mounted() {},
components: {},
methods: {
mousedown(index, val) {
this.isMoveTrue = true;
if (val == 1) {
this.moveId = "mouse" + index;
} else {
this.moveId = "deleteMouse" + index;
}
},
mousemove(event) {
if (this.isMoveTrue) {
this.isMove = true;
document.getElementById(this.moveId).style.position = "absolute";
document.getElementById(this.moveId).style.top = event.clientY + "px";
document.getElementById(this.moveId).style.left = event.clientX + "px";
document.getElementById(this.moveId).style.transform =
"translate(-50%,-50%)";
}
},
mouseup(item, val, index) {
if (!this.isMove) {
this.isMoveTrue = false;
this.moveId = "";
}
if (this.isMoveTrue && val == 2) {
this.$nextTick(() => {
this.rightData.splice(index, 1);
this.leftData.push(item);
});
} else if (this.isMoveTrue && val) {
this.leftData.splice(index, 1);
this.rightData.push(item);
}
document.getElementById(this.moveId).style.display = "none";
this.isMoveTrue = false;
this.isMove = false;
this.moveId = "";
},
handerClickX(item, index, val) {
if (val == 1) {
this.leftData.splice(index, 1);
this.rightData.push(item);
} else {
this.rightData.splice(index, 1);
this.leftData.push(item);
}
},
},
};
</script>
<style scoped>
#home {
display: flex;
justify-content: space-around;
}
.tree-select-content {
width: 40%;
height: 300px;
background: #f9faff;
border: 1px solid #dee0ec;
border-radius: 4px;
display: flex;
flex-wrap: wrap;
align-content: baseline;
}
.select-content {
width: max-content;
height: 20px;
padding: 1.6%;
border: 1px solid #d6dbed;
margin: 2% 1% 0;
background: #ffffff;
box-shadow: 0 0 8px 0 rgba(72, 119, 236, 0.1);
border-radius: 4px;
}
.select-content:hover span {
color: #4877ec;
}
.select-content:hover {
cursor: pointer;
background: #f8faff;
border: 1px solid #3e75f4;
}
.select-text {
font-size: 15px;
color: #2e2f36;
text-align: center;
font-weight: 400;
}
.select-text-X {
font-size: 15px;
color: #4877ec;
letter-spacing: 0;
font-weight: 400;
margin-left: 12px;
cursor: pointer;
}
</style>
效果图:

三、Vue 拖拽组件 vuedraggable
vuedraggable 是标准的组件式封装,并且将可拖动元素放进了 transition-group 上面,过渡动画都比较好。
使用方式:
yarn add vuedraggable
import vuedraggable from 'vuedraggable';
在使用的时候,可以通过 v-model 来双向绑定本地 data,如果需要更新或者是触发父组件监听的事件,可以在 updated() 中去 emit。
案例:
<template>
<div>
<div>{{ drag ? "拖拽中" : "拖拽停止" }}</div>
<!--使用draggable组件-->
<draggable
v-model="myArray"
chosenClass="chosen"
forceFallback="true"
group="people"
animation="1000"
@start="onStart"
@end="onEnd"
>
<transition-group>
<div class="item" v-for="element in myArray" :key="element.id">
{{ element.name }}
</div>
</transition-group>
</draggable>
<div class="color-list">
<div
class="color-item"
v-for="color in colors"
v-dragging="{ item: color, list: colors, group: 'color' }"
:key="color.text"
>
{{ color.text }}
</div>
</div>
</div>
</template>
<style scoped>
/*被拖拽对象的样式*/
.item {
padding: 6px;
background-color: #fdfdfd;
border: solid 1px #eee;
margin-bottom: 10px;
cursor: move;
}
/*选中样式*/
.chosen {
border: solid 1px #3089dc !important;
}
</style>
<script>
//导入draggable组件
import draggable from "vuedraggable";
export default {
//注册draggable组件
components: {
draggable,
},
data() {
return {
drag: false,
//定义要被拖拽对象的数组
myArray: [
{ people: "cn", id: 10, name: "www.itxst.com" },
{ people: "cn", id: 20, name: "www.baidu.com" },
{ people: "cn", id: 30, name: "www.taobao.com" },
{ people: "us", id: 40, name: "www.yahoo.com" },
],
colors: [
{
text: "Aquamarine",
},
{
text: "Hotpink",
},
{
text: "Gold",
},
{
text: "Crimson",
},
{
text: "Blueviolet",
},
{
text: "Lightblue",
},
{
text: "Cornflowerblue",
},
{
text: "Skyblue",
},
{
text: "Burlywood",
},
],
};
},
methods: {
//开始拖拽事件
onStart() {
this.drag = true;
},
//拖拽结束事件
onEnd() {
this.drag = false;
},
},
};
</script>
四、Awe-dnd指令封装
vue-dragging 的 npm 包的名字是 awe-dnd ,并不是 vue-dragging,这个库的特点是封装了 v-dragging 全局指令,然后通过全局指令去数据绑定等。
相比及 vuedraggable 来说, awe-dnd 是没有双向绑定(这里没有双向绑定并不是很严谨,准确的来说没有暴露双向绑定的方式),因此提供了事件,在拖拽结束的时候用来更新列表(不需要手动更新列表,其实内部是实现了双向绑定的)或者是去触发父组件监听的事件。
安装依赖:
npm install awe-dnd --save
yarn add awe-and
main.js
import VueDND from 'awe-dnd'
Vue.use(VueDND)
案例:
<template>
<div>
<div class="color-list">
<div
class="color-item"
v-for="color in colors"
v-dragging="{ item: color, list: colors, group: 'color' }"
:key="color.text"
>
{{ color.text }}
</div>
</div>
</div>
</template>
<style scoped>
/*被拖拽对象的样式*/
.item {
padding: 6px;
background-color: #fdfdfd;
border: solid 1px #eee;
margin-bottom: 10px;
cursor: move;
}
/*选中样式*/
.chosen {
border: solid 1px #3089dc !important;
}
</style>
<script>
export default {
data() {
return {
drag: false,
colors: [
{
text: "Aquamarine",
},
{
text: "Hotpink",
},
{
text: "Gold",
},
{
text: "Crimson",
},
{
text: "Blueviolet",
},
{
text: "Lightblue",
},
{
text: "Cornflowerblue",
},
{
text: "Skyblue",
},
{
text: "Burlywood",
},
],
};
},
methods: {},
};
</script>
Vue实现拖拽穿梭框功能四种方式的更多相关文章
- ASP.NET MVC之下拉框绑定四种方式(十)
前言 上两节我们讲了文件上传的问题,关于这个上传的问题还未结束,我也在花时间做做分割大文件处理以及显示进度的问题,到时完成的话再发表,为了不耽误学习MVC其他内容的计划,我们今天开始好好讲讲关于MVC ...
- [HTML]HTML隐藏文本框的四种方式
.<input type="hidden" value=""></input>对所有的文本框都起作用(隐藏域,多用于存数据) .< ...
- elementUI 弹出框添加可自定义拖拽和拉伸功能,并处理边界问题
开发完后台管理系统的弹出框模块,被添加拖拽和拉伸功能,看了很多网上成熟的帖子引到项目里总有一点问题,下面是根据自己的需求实现的步骤: 首先在vue项目中创建一个js文件eg:dialog.js imp ...
- 基于Vue实现拖拽效果
参考地址:基于Vue实现拖拽效果 参考链接中讲的比较详细,我只使用了其中自定义指令的方法.整体代码如下: <template> <!-- 卡片 --> <div clas ...
- Javascript实现鼠标框选元素后拖拽被框选的元素
之前需要做一个框选元素后拖拽被框选中的元素功能,在网上找资料做了一些修改,基本达到了需要的效果,希望对也需要实现框选后拖拽元素功能的人有用. 页面加载后效果 框选后的内容可以拖拽,如下图: 代码下载
- 基于jquery-ui及bootstrap的可拖拽模态框
可直接使用代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- Vue2 实现时空穿梭框功能模块
前言 这篇文章主要是分享一个时空穿梭框功能,也就是我们平时用的选择功能.勾选了的项就会进入到另一个框中. 时空穿梭框之旅 示例演示: 这个时空穿梭框实现了: 1.可以全选.反选 2.没有选中时,不可以 ...
- vue使用element Transfer 穿梭框实现ajax请求数据和自定义查询
vue使用element Transfer 穿梭框实现ajax请求数据和自定义查询 基于element Transfer http://element-cn.eleme.io/#/zh-CN/comp ...
- Android 仿微信朋友圈发表图片拖拽和删除功能
朋友圈实现原理 我们使用 Android Device Monitor 来分析朋友圈发布图片的界面实现原理.如果需要分析其他应用的界面实现也是采用这种方法哦. 打开 Android Device Mo ...
随机推荐
- 中国顶级程序员,从金山WPS走出来,自研了“表格编程”神器
程序员的圈子里有很多如明星般闪耀的牛人! 有中国"第一代程序员"--求伯君,有在微信获得巨大成功的张小龙,有图灵奖获得者姚期智,有商业巨子张一鸣,更有开源影响力人物--章亦春. 章 ...
- HashSet集合的介绍和哈希值
java.util.Set接口 extends Collection接口 Set接口的特点: 1.不允许存储重复的元素 2.没有索引,没有带索引的方法,也不能使用普通的for循环遍历 java.uti ...
- Möbius 反演注记
目录 基本理论基础 数论函数 线性筛 Mobius 反演 Dirichlet 卷积 数论分块 / 整除分块 拆函数 时间复杂度分析 基本形式 GCD 形 万能 Prod 的莫比乌斯反演 正常例题 YY ...
- 安卓手机如何无线连接adb?
一般情况,大家adb调试手机,都是通过数据线的,但这样又是不太方便,所以我们可以通过WLAN来adb. 我的是华为手机,进入:设置-关于手机,连续点击版本号,唤出开发者模式.然后去返回设置-系统和更新 ...
- 流量如何才能变现?实际测试谷歌广告联盟(Google Adsense)的广告效果以及如何优化相关代码
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_150 2010年,谷歌正式退出中国市场,无数人扼腕叹息,如今十年过去了,谷歌还有两条重要的业务线并没有完全退出,一个是页面统计业务 ...
- lamp平台构建
目录 lamp平台构建 安装httpd 安装mysql 安装php 配置apache 启用代理模块 配置虚拟主机 启用代理模块 验证 lamp平台构建 环境说明: 系统平台 IP 需要安装的服务 ce ...
- 9. 利用Docker快速构建MGR | 深入浅出MGR
目录 1.安装Docker 2.拉取GreatSQL镜像,并创建容器 2.1 拉取镜像 2.2 创建新容器 2.3 容器管理 3.构建MGR集群 3.1 创建专用子网 3.2 创建3个新容器 3.3 ...
- Kafka部署安装
一.环境准备 1.jdk 8+ 2.zookeeper 3.kafka 说明:在kafka较新版本中已经集成了zookeeper,所以不用单独安装zookeeper,只需要在kafka文件目录中启动z ...
- java的stream让我灵光一现
说实话,我是一个到了退役也没有搞明白C++的istream和ostream的. 刚开始的时候我把<iostream>直接拆解成ios和tream 真,果粉暴露 退役之后划水,倒是从java ...
- Java SE 10 新增特性
Java SE 10 新增特性 作者:Grey 原文地址:Java SE 10 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...