初识Vue,先封装一个翻页组件

271 阅读1分钟

经过前段时间webpack相关原理的浅析,从昨天开始学习到了Vue,由于本人做过开发,所以我不太喜欢把我当0基础的去看某些培训教育机构的学习视频,感觉有点不太适合我。所以就直接上手组件开发,边在开发的过程中,边学习、查阅官方文档。 怎么说呢,总的来说,感觉比纯看学习视频要记忆深刻 今天做了一个还算中等难度的组件——翻页组件,代码仅供参考,样式参考elementUI-pagination

实现效果

Snipaste_2021-12-14_16-55-54.png

代码如下

<template>
  <div class="pagination_container" v-show="totalPage > 1">
    <button @click="onPageChange(current - 1)" class="page_button" :class="{ disabled: current === 1 }">
      <Icon type="arrowLeft"></Icon>
    </button>
    <ul>
      <template v-for="numberObject of numberObjects">
        <li :key="numberObject.id" v-if="numberObject.type === 'number'" @click="onPageChange(numberObject.number)"
            :class="{ selected: current === numberObject.number }">
          {{ numberObject.number }}
        </li>
        <button
            @click="onPageChange(current - 1)"
            @mousemove="leftType = 'moreLeft'"
            @mouseleave="leftType = 'ellipsis'"
            :key="numberObject.id"
            v-else-if="numberObject.type === 'more' && numberObject.arrow === 'left'"
            class="page_button more">
          <Icon :type="numberObject.arrow === 'left' ? leftType : rightType"></Icon>
        </button>
        <button
            @click="onPageChange(current + 1)"
            @mousemove="rightType = 'moreRight'"
            @mouseleave="rightType = 'ellipsis'"
            :key="numberObject.id"
            v-else-if="numberObject.type === 'more' && numberObject.arrow === 'right'"
            class="page_button more">
          <Icon :type="rightType"></Icon>
        </button>
      </template>
    </ul>
    <button @click="onPageChange(current + 1)" class="page_button" :class="{ disabled: current === totalPage }">
      <Icon type="arrowRight"></Icon>
    </button>
  </div>
</template>

<script>
import Icon from "../Icon"; // icon是我自己做的图标,图标素材来源于iconfont

export default {
  name: "Pagination",
  components: {
    Icon
  },
  props: {
    // 总数据量
    total: {
      type: Number,
      require: true
    },

    // 当前页码
    current: {
      type: Number,
      require: false,
      default: 1
    },

    // 数字按钮页码显示的数量
    pageCount: {
      type: Number,
      require: false,
      default: 7,
      validator: function (value) {
        return value >= 7;
      }
    },

    // 每页显示条目数
    pageSize: {
      type: Number,
      require: false,
      default: 10
    }
  },
  data() {
    return {
      leftType: 'ellipsis',
      rightType: 'ellipsis'
    }
  },
  computed: {
    totalPage() {
      return Math.ceil(this.total / this.pageSize)
    },
    numberObjects() {
      const restPageCount = this.pageCount - 2;
      let min = this.current - Math.floor(restPageCount / 2);
      min = min < 2 ? 2 : min;
      let max = min + restPageCount - 1;
      max = max > this.totalPage ? this.totalPage : max;
      let leftDot = min > 2; // 计算出来显示的除1之外最小的数字大于2,显示左边的more
      let rightDot = max < this.totalPage - 1; // 计算出来显示的除totalPage之外最大的数小于totalPage-1,显示右边的more
      let numbers = [];
      numbers.push({
        type: 'number',
        number: 1,
        id: 1,
        arrow: 'none'
      });
      if (leftDot) {
        numbers.push({
          type: 'more',
          number: 0,
          id: 2,
          arrow: 'left',
        });
      }
      for (let i = min; i <= max; i++) {
        numbers.push({
          type: 'number',
          number: i,
          id: i + 1,
          arrow: 'none'
        });
      }
      if (rightDot) {
        numbers.push({
          type: 'more',
          number: 0,
          id: max + 2,
          arrow: 'right',
        });
      }
      if (max !== this.totalPage) {
        numbers.push({
          type: 'number',
          number: this.totalPage,
          id: max + 3,
          arrow: 'none',
        });
      }

      return numbers
    }
  },
  methods: {
    onPageChange(number) {
      if (number < 1 || number > this.totalPage) return;
      if (number === this.current) return;
      this.leftType = 'ellipsis'
      this.rightType = 'ellipsis'
      this.$emit('page-change', number)
    }
  },
}
</script>

<style lang="less" scoped>
@import "../../styles/variable.less";

.pagination_container {
  ul {
    margin: 0;
    padding: 0;
    display: inline-block;
  }

  .page_button, li {
    margin: 0 5px;
    background-color: @lightWhite;
    color: @gray;
    min-width: 30px;
    border-radius: 2px;
    cursor: pointer;
    height: 28px;
    line-height: 28px;
    font-size: 13px;
    box-sizing: border-box;
    vertical-align: top;
    border: none;
    text-align: center;
    user-select: none;
  }

  li {
    list-style: none;
    padding: 0 4px;
    display: inline-block;

    &.selected {
      background: @primary;
      color: @white;
    }

    &.more {
      font-weight: bolder;
    }
  }

  .page_button:hover,
  li:not(.selected):hover {
    color: @primary;
  }

  .page_button.disabled {
    color: @disabled;
    background-color: #fff;
    cursor: not-allowed;
  }
}

.iconfont {
  font-size: 12px;
}
</style>