子组件:
1)设置滑动单元格的滑动样式:data_type用来表示是否已经将单元格滑至左侧,“1”为已滑动,“0”为复原。这里使用了动态绑定data_type属性方法,允许我们动态设置属性值,该值将基于组件的当前状态或数据
采用了css3的动画效果
2)开始触摸单元格时触发touchStart函数:记录滑动的初始位置
3)滑动结束时触发touchEnd函数:记录结束滑动时的位置,并结合初始位置计算滑动距离(距离自行设置),这里设置的当滑动距离大于20时出现删除按钮,若右滑动,恢复初始位置
4)点击删除按钮:采用$emit方法携带id,告知父组件删除对应id的单元格
6)点击单元格空白处取消滑动,即滑动复位:
父组件:
获取子组件传过来的id,通过foreach遍历查询对应id的单元格,再传给后端删除数据库里的对应id的数据:
子组件完整示例:
<template>
<!-- "touchstart" 当手指触摸屏幕时候触发 "touchend" 当手指从屏幕上离开的时候触发 "capture" 用于事件捕获-->
<view class="car">
<view
:data-type="this.data_type"
class="li_vessel"
@touchstart.capture="touchStart"
@touchend.capture="touchEnd"
@click="oneself"
>
<view>
<view class="ol-flex-class">
<view v-show="!submitOrder">
<checkbox-group @change="selectedChange">
<label>
<checkbox
class="selected"
color="#555555"
value="true"
:checked="flag1"
/> </label
></checkbox-group>
</view>
<!-- <image class="ol-left-image-class" :src="item.imageUrls ? getImageUrl(item.imageUrls[0]) : ''" mode="aspectFill"></image> -->
<image
mode="aspectFill"
class="ol-left-image-class"
:src="imageSrc"
/>
<view class="ol-center-class">
<view
class="name"
style="
letter-spacing: 5rpx;
font-size: 10px;
color: black;
font-family: Sans-serif;
padding-bottom: 3px;
"
>{{ title }}</view
>
<view
style="
display: flex;
color: #505050;
padding-bottom: 3px;
font-size: 10px;
"
>剩余 {{ remaining }} 斤</view
>
<view style="display: flex">
<view class="ol-op-class">¥{{ originalPrice }}</view>
<view style="margin-left: 10px; color: #2a9803"
>¥{{ presentPrice }}</view
>
</view>
</view>
<view class="ol-right-view" v-show="!submitOrder">
/*carNumber为自行编写的数字输入框组件*/
<carNumber
v-on:numberTransfer="getNum"
:code="code"
:min="1"
:value="number"
:max="remaining"
:flag2="flag1"
:allchecked2="allchecked_b"
@numberTransfer="getNumber($event, productId)"
></carNumber>
</view>
<!-- <view v-show="!submitOrder" style="color: red; transform: translateX(20px);" @click="Delete()">删除</view> -->
<view class="ol-right-view" v-show="submitOrder">
{{ number }}斤
</view>
</view>
</view>
<view class="deleteText" @click="removeGoods"
><img src="../../../static/deleteGoods.png"
/></view>
</view>
</view>
</template>
<script>
import config from "../../../../config.js";//接口请求封装函数,根据项目实际情况添加
import carNumber from "../../../components/unimall/uni-carNumber/uni-carNumber";
export default {
components: {
carNumber,
},
props: {
imageSrc: {
type: String,
default: "",
},
title: {
type: String,
default: "",
},
remaining: {
type: Number,
default: "",
},
originalPrice: {
type: Number,
default: 0,
},
presentPrice: {
type: Number,
default: 0,
},
number: {
type: Number,
default: 0,
},
submitOrder: {
type: Boolean,
default: false,
},
//商品id,子组件将商品勾选状态改变后,
//需通知父组件根据id修改父组件对应商品的勾选状态
productId: {
type: String,
default: "",
},
code: {
type: String,
default: "",
},
max: {
type: Number,
default: 0,
},
flag1: {
type: Boolean,
default: false,
},
allchecked1: {
type: Boolean,
default: false,
},
},
watch: {
flag1: {
handler(newVal) {
console.log("Selected items:", newVal);
},
deep: true,
},
},
data() {
return {
startX: 0, //滑动开始
endX: 0, //滑动结束
gNum: 0,
// flag_a: this.flag1,
allchecked_b: this.allchecked1,
originalMoney: 0,
discountMoney: 0,
data_type: "",
};
},
onLoad: function () {},
methods: {
getImageUrl(url) {
return config.PUBLIC_IMAGE_URL + url;
},
// // 向左滑动出现删除按钮时,点击商品信息区域取消删除
oneself() {
this.data_type = "0";
},
//滑动开始
touchStart(e) {
// 记录初始位置
this.startX = e.touches[0].clientX;
// console.log(this.startX);
},
//滑动结束
touchEnd(e) {
// 当前滑动的父级元素
// console.log(e);
let parentElement = e.currentTarget;
// 记录结束位置
this.endX = e.changedTouches[0].clientX;
// console.log(this.endX);
// 左滑大于20距离删除出现
if (parentElement.dataset.type == 0 && this.startX - this.endX > 20) {
parentElement.dataset.type = 1;
this.data_type = parentElement.dataset.type;
console.log(this.data_type);
}
// 右滑
if (parentElement.dataset.type == 1 && this.startX - this.endX < -20) {
//this.restSlide();
parentElement.dataset.type = 0;
this.data_type = parentElement.dataset.type;
console.log(this.data_type);
}
this.startX = 0;
this.endX = 0;
},
//判断当前是否有滑块处于滑动状态
checkSlide() {
let listItems = document.querySelectorAll(".li_vessel");
for (let i = 0; i < listItems.length; i++) {
if (listItems[i].dataset.type == 1) {
return true;
}
}
return false;
},
//复位滑动状态
restSlide() {
let listItems = document.querySelectorAll(".li_vessel");
// 复位
for (let i = 0; i < listItems.length; i++) {
listItems[i].dataset.type = 0;
}
},
//删除
removeGoods(item) {
uni.showModal({
title: "提示",
content: "是否删除",
success: (res) => {
if (res.confirm) {
this.$emit("removeGoods", this.productId);
console.log("确定删除");
} else if (res.cancel) {
console.log("用户点击取消");
}
},
});
// 复位
this.restSlide();
},
//获取商品数量
getNum(res) {
this.gNum = res;
},
getNumber(val, id) {
let num = val - 0,
productId = id;
this.$emit("getNumberEvent", { num, productId });
},
//只要复选框勾选状态发生变化,就会触发此处理函数
selectedChange(e) {
// this.flag1 = !this.flag1;
var item = this.flag1,
values = e.detail.value;
console.log("单选flag", this.flag1);
console.log("单选flag", Boolean(values[0]));
this.$emit("check-change", { id: this.productId, vl: Boolean(values[0]) });
},
},
};
</script>
<style lang="less">
::v-deep uni-checkbox .uni-checkbox-input{
border-radius: 50%
}
::v-deep uni-radio-group uni-label, uni-checkbox-group uni-label{
padding-right: 0;
}
.car {
background-color: rgb(252, 252, 252);
// box-shadow: 15px 15px 15px #727272;
/*超出部分隐藏*/
overflow: hidden;
margin: 5px;
border-radius: 10px;
}
.li_vessel {
/* 消除默认样式 */
// list-style: none;
// padding: 0;
// margin: 0;
/* 全部样式 0.2秒 缓动*/
position: relative;
// 左滑动画效果
-webkit-transition: all 0.2s;
transition: all 0.2s;
}
/* =0隐藏 */
.li_vessel[data-type="0"] {
transform: translate3d(0, 0, 0);
}
/* =1显示 */
.li_vessel[data-type="1"] {
/* -64px 设置的越大可以左滑的距离越远,最好与下面删除按钮的宽度以及定位的距离设置一样的值*/
transform: translate3d(-64px, 0, 0);
}
.ol-flex-class {
display: flex;
margin-left: 10px;
margin-right: 17px;
padding: 7px 0 7px 0;
height: fit-content;
align-items: center;
}
.ol-left-image-class {
// margin-top: 50px;
height: 90px;
width: 100%;
border-radius: 10px;
}
.ol-center-class {
margin-left: 10px;
}
.ol-center-class view {
font-size: 11px;
}
.ol-right-view {
margin-left: auto;
margin-top: auto;
margin-right: 0px;
font-size: small;
transform: translateX(10px);
}
.line-view {
width: 100%;
background-color: #ffffff;
margin-top: 10px;
margin-bottom: 30px;
}
.ol-op-class {
color: #505050;
text-decoration: line-through;
text-decoration-color: #ff0000;
}
.li_vessel .deleteText {
width: 64px;
height: 140px;
margin-top: -10px;
background: #ff6a6a;
font-size: 18px;
color: #fff;
text-align: center;
justify-content: center;
align-items: center;
position: absolute;
top: 0px;
right: -64px;
line-height: 200px;
img {
height: 60%;
width: 60%;
}
}
</style>