许久未见,最近遇到一个产品,他是第一次做产品。总是有一些反人类的设计。没错,就是标题上的拖拽集合,以及商品的左滑删除。这种功能放眼各大app我都没找到有用这种设计的,他口口声声说他用过会找给我看,我等了许久,或许是他忘记了吧。
遇到这种需求,我也尝试和他沟通,比如使用购物车来删除商品等等,换一些大家都能接受的逻辑,但是他有自己的想法,我只好选择尊重。
1.拖拽集合功能
拖拽集合功能我寻找很久后使用了一款大神写的拖拽插件,并对其进行了相应的适配,因为我这个需求不需要显示上的集合,在集合的时候是跳转页面,所以在使用上会有一些修改,但是总体上是类似的,一下是插件官网,大家可以参考:
注意:在开发的时候监听拖拽开始和结束事件的时候会提示报错,如果有这个建议大家自行解决或者采用和我一样的方式监听拖动过程等,这个因需求而异。最后附上代码:
javascript
<template>
<div id="app">
<h1>商品列表</h1>
<div class="container">
<div class="row">
<!-- @change="onDragEnd" @start="start" @end="onEnd" :move="onMove" delay="1000" -->
<div class="col-md-6">
<draggable v-model="leftItems" :group="group" delay="1000"
@change="onDragEnd" :move="onMove"
animation="300" dragClass="dragClass" ghostClass="ghostClass">
<!-- <u-swipe-action :show="item.show" :index="index"
v-for="(item, index) in leftItems" :key="item.id"
@click="click" @open="open"
:options="options"
> -->
<div class="item" v-for="(item, index) in leftItems" :key="item.id" >{{ item.name }}</div>
<!-- </u-swipe-action> -->
</draggable>
</div>
<div class="col-md-6">
<draggable v-model="rightItems" :group="group"
@change="onDragEnd" :move="onMove">
<div v-for="(item, index) in rightItems" :key="index" @longpress="aaa(index)" :class="['item',item.status==true?'shake':'']">{{ item.name }}</div>
</draggable>
</div>
</div>
</div>
</div>
</template>
<script>
import draggable from 'vuedraggable';
export default {
components: {
draggable
},
data() {
return {
disabled: false,
btnWidth: 180,
show: false,
options: [
{
text: '删除',
style: {
backgroundColor: '#dd524d'
}
}
],
timerId: null,//计时器id
group: {
name: "itxst",
pull: true, //可以拖出
put: true, //可以拖入
},
leftItems: [{
id: 1,
show: false,
status: false,
name: '商品1'
},
{
id: 2,
show: false,
status: false,
name: '商品2'
},
{
id: 3,
show: false,
status: false,
name: '商品3'
},
{
id: 4,
show: false,
status: false,
name: '商品4'
},
{
id: 5,
show: false,
status: false,
name: '商品5'
},
{
id: 6,
show: false,
status: false,
name: '商品6'
},
],
rightItems: [{
id: 1,
show: false,
status: false,
name: '商品1'
},
{
id: 2,
show: false,
status: false,
name: '商品2'
},
{
id: 3,
show: false,
status: false,
name: '商品3'
},
{
id: 4,
show: false,
status: false,
name: '商品4'
},
{
id: 5,
show: false,
status: false,
name: '商品5'
},
{
id: 6,
show: false,
status: false,
name: '商品6'
},
]
};
},
onLoad() {
},
methods: {
click(index) {
this.leftItems.splice(index, 1);
this.$u.toast(`删除了第${index}个cell`);
},
// 如果打开一个的时候,不需要关闭其他,则无需实现本方法
open(index) {
// 先将正在被操作的swipeAction标记为打开状态,否则由于props的特性限制,
// 原本为false,再次设置为false会无效
this.leftItems[index].show = true;
this.leftItems.map((val, idx) => {
if(index != idx) this.leftItems[idx].show = false;
})
},
start(e) {
console.log(e, 'kasihi ');
},
onEnd() {
console.log(e, '结束了 ');
},
onMove(e) { // keyi huanyuan
clearTimeout(this.timerId)
console.log('如果能监听到要在这里清楚计时器');
return this.canFormSet()
},
aaa(index) {
this.rightItems[index].status = true
this.timerId = setTimeout(() => {
this.rightItems[index].status = false
clearTimeout(this.timerId)
}, 500)
},
onDragEnd(event) {
console.log(event);
// if (event.newIndex !== event.oldIndex) {
// const movedItem = this.leftItems[event.oldIndex];
// this.leftItems.splice(event.oldIndex, 1);
// this.rightItems.push(movedItem);
// 判断是否可以形成集合跳转页面
if (this.canFormSet()) {
// 跳转到另一个页面的逻辑
console.log('路由去往新的页面');
// this.$router.push('/another-page');
} else {
// 如果不能形成集合,则复原
console.log('复原');
// this.rightItems.pop();
// this.leftItems.splice(event.newIndex, 0, movedItem);
}
console.log('6666');
clearTimeout(this.timerId)
// } else {
// console.log('else');
// // Revert the move if it's not a valid combination
// const movedItem = this.rightItems.pop();
// this.leftItems.splice(event.newIndex, 0, movedItem);
// }
},
canFormSet() {
// 如果可以形成集合,返回 true;否则返回 false
return false; // 示例中默认返回 true
}
}
};
</script>
<style scoped lang="scss">
.shake {
width: 100px;
height: 100px;
background-color: red;
transform-origin: center;
animation: shake .5s infinite ease-in-out;
}
@keyframes shake {
0%,
100% {
transform: rotate(-5deg);
/* transform: translate(-50%, -50%) rotate(-5deg); */
}
50% {
transform: rotate(5deg);
}
}
.ghostClass {
background-color: blue !important;
}
.chosenClass {
background-color: red !important;
opacity: 1 !important;
}
.dragClass {
background-color: blueviolet !important;
opacity: 1 !important;
box-shadow: none !important;
outline: none !important;
background-image: none !important;
}
.container {
width: 100%;
margin-top: 20px;
}
.row {
width: 100%;
display: flex;
}
.col-md-6 {
width: 100%;
// display: flex;
// flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
margin-left: 20px;
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
background-color: #f9f9f9;
}
</style>
2.一行多个商品滑动删除功能
上面的代码大家也看到了 我计划使用 u-swipe-action 来实现滑动删除功能,但是它只能一行滑动删除。所以我看了一下源码,然后有所顿悟,手搓了一个一行多个的删除效果代码,后期也会进行一些优化,废话不多说,代码给大家参考,希望能帮到你:
javascript
<template>
<view class="container">
<movable-area class="box-info"
v-for="(item, index) in items"
:key="index">
<movable-view
style="width: 140px; height: 100px; background-color: #aa55ff;"
:style="{widh}"
:x="index * 10"
:direction="'horizontal'"
:out-of-bounds="false"
>
<view class="product">
<view style="width: 100px;">{{item}}</view>
<view class="move" @click="removeShop">删除</view>
</view>
</movable-view>
</movable-area>
</view>
</template>
<script>
export default {
data() {
return {
items: ['商品1', '商品2']
};
},
methods: {
removeShop(index) {
alert('删除商品操作')
}
}
};
</script>
<style scoped lang="scss">
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
.box-info {
display: flex;
flex-wrap: wrap;
height: 100px;
width: 100px;
background-color: #55ff7f;
overflow: hidden;
margin: 20px;
.product {
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: #333;
.move{
background-color: #55aa00;
width: 40px;
height: 100px;
writing-mode: vertical-rl;
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
</style>