uni-app+Vue2+vue.js+css3实现滑动删除效果

子组件:

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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值