手写el-table-column组件排序效果

需求

实现产品列表筛选条件排序,记得element-plus中的el-table-column实现了对表格数据排序的效果,不过俺现在做的是移动端页面,用的vant,vant没有类似的组件,于是打算手写一个。

思路

v-for遍历显示从父组件传来配置数据信息,flex一行进行显示,当点击上三角按钮时为升序,下三角为降序,再次点击时取消排序,当三角按钮被点击时,触发自定义事件sortOptionsChange,传递给父组件对应的prop(哪一栏)和state(升序、降序、不排序)信息,父组件接收到子组件传来的信息进行对应的后端请求

代码

子组件 table-column-sort.vue

<template>
  <div class="zc-table-column-sort">
    <div
      class="sort-option"
      v-for="(option, index) in sortOptionsOriginData"
      :key="option.name"
    >
      <!-- 排序条件名称 -->
      <span class="label">{{ option.label }}</span>
      <!-- 上三角 下三角 -->
      <span class="caret-wrapper">
        <i
          :class="{ 'ascending-active': option.state === SortType.ASCENDING }"
          class="ascending"
          @click="handleSortBtnClick(option.prop, index, SortType.ASCENDING)"
        ></i>
        <i
          :class="{ 'descending-active': option.state === SortType.DESCENDING }"
          class="descending"
          @click="handleSortBtnClick(option.prop, index, SortType.DESCENDING)"
        ></i>
      </span>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue"

export default defineComponent({
  props: {
    // 排序条件配置信息
    sortOptions: {
      type: Array,
      default: () => []
    }
  },
  emits: ["sortOptionsChange"], // 通知父组件排序配置改变
  setup(props, { emit }) {
    // 为了不违反单向数据流 新建一个排序配置数据
    const sortOptionsOriginData = ref(
      JSON.parse(JSON.stringify(props.sortOptions))
    )
    // 排序类型
    enum SortType {
      UNSORTED = 0,
      ASCENDING = 1,
      DESCENDING = 2
    }
    // 初始化 置state为0
    const originOptions = () => {
      sortOptionsOriginData.value.forEach((option: any) => {
        option["state"] = SortType.UNSORTED
      })
    }

    originOptions()

    // 排序按钮点击
    const handleSortBtnClick = (prop: string, index: number, state: number) => {
      // 再次点击则取消
      if (sortOptionsOriginData.value[index].state === state) {
        sortOptionsOriginData.value[index].state = SortType.UNSORTED
        emit("sortOptionsChange", prop, SortType.UNSORTED)
        return
      }

      originOptions()
      sortOptionsOriginData.value[index].state = state
      emit("sortOptionsChange", prop, state)
    }

    return {
      SortType,
      sortOptionsOriginData,
      handleSortBtnClick
    }
  }
})
</script>

<style lang="less" scoped>
.zc-table-column-sort {
  display: flex;
  .sort-option {
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    .label {
      font-size: 0.3077rem;
      color: #b8b8b8;
      padding-right: 0.1282rem;
    }
    .caret-wrapper {
      display: flex;
      flex-direction: column;
      align-items: center;
      // 升序上三角
      .ascending {
        border: 0.1282rem solid transparent;
        border-bottom-color: #a8abb2;
        margin-bottom: 0.0256rem;
      }
      // 降序下三角
      .descending {
        border: 0.1282rem solid transparent;
        border-top-color: #a8abb2;
        margin-top: 0.0256rem;
      }
      // 升序上三角点击样式
      .ascending-active {
        border-bottom-color: #91bef4;
      }
      // 降序下三角点击样式
      .descending-active {
        border-top-color: #91bef4;
      }
    }
  }
}
</style>

父组件 product-list.vue

<template>
  <div class="product-list">
    <zc-table-column-sort
      @sortOptionsChange="sortOptionsChange"
      :sortOptions="sortOptions"
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, computed, ref } from "vue"
import { useStore } from "vuex"
import ZcTableColumnSort from "@/base-ui/table-column-sort"
import { sortOptions } from "./config/sort.config"

export default defineComponent({
  components: {
    NavTitle,
    ZcTableColumnSort
  },
  setup() {
    const store = useStore()
    // 搜索产品列表的初始化条件
    const payload = ref({
      keyWords: "",
      initialAmount: -1,
      deadLine: -1,
      riskRating: "",
      selectType: "", // 排序字段名称
      state: 0, // 排序类型 0不排序 1升序 2降序
      curPage: 1,
      pageSize: 5
    })

    const sortOptionsChange = (prop: string, state: number) => {
      payload.value.selectType = prop
      payload.value.state = state
    }
    store.dispatch("product/getProductListAction", payload.value)
    const productList = computed(() => store.state.product.productList)

    return {
      productList,
      sortOptions,
      sortOptionsChange
    }
  }
})
</script>

<style lang="less" scoped></style>

排序条件配置信息 sort.config.ts

export const sortOptions = [
  {
    prop: "rateOfReturn",
    label: "七日年化%"
  },
  {
    prop: "rateOfComparative",
    label: "业绩比较%"
  },
  {
    prop: "initialAmount",
    label: "起购金额"
  },
  {
    prop: "deadLine",
    label: "有效期限"
  }
]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值