(资料图)

首先就是新建一个组件,名字就叫做​​PageTable​​,​​template​​里面很简单,放上表格和分页。既然表格默认带有分页,分页的数据就放在组件内部

<script>export default {  name: "PageTable",  data() {    return {      page: {        current: 1,        size: 10,        total: 0      },    }  },}</script>

之后开始思考一个问题,就是表格的数据是从父组件传进来,还是放在组件自身。如果放在父组件里面,那么分页的变化每次都要​​emit​​事件通知父组件,这样我们把分页和表格合在一起就失去了意义,所以表格的数据是要放在组件自身的。

表格数据放在自身,父组件就需要传进来一个获取数据的方法,就叫做​​fetchData​​吧,在组件内部调用这个方法,就可以获取数据了。这个方法是需要知道当前分页的,并且返回数据和总条数,由此就可以定义​​fetchData​​了

interface ResponseStructure {  data: any[];  total: any;}interface fetchData {  (current: number, size: number): Promise}

现在我们的组件已经变成了这个样子

<script>export default {  name: "PageTable",  props: {    fetchData: {      type: Function,      required: true    },  },  data() {    return {      page: {        current: 1,        size: 10,        total: 0      },      tableData: []    }  },  methods: {    search() {      this.page.current = 1      this.getTableData()    },    async getTableData() {      try {        const { current, size } = this.page        const { data, total } = await this.fetchData(current, size)        this.tableData = data        this.page.total = total      } catch (err) {        this.tableData = []        this.page.total = 0      }    },  }}</script>

表格一般都会带有搜索项,搜索参数等在父组件定义,并且逻辑写在​​fetchData​​里即可,组件内部只处理通用的逻辑。父组件里点击了搜索按钮,是要触发获取事件的,父组件可以通过​​$refs​​调用组件内部方法。目前我们定义了两个方法​​search​​与​​getTableData​​,点击搜索调用​​search​​就可以了,并且会自动重置分页,如果有不想重置分页的情况,可以调用​​getTableData​​。

目前为止,数据我们已经有了,但是并没有展示,因为element-ui的列信息(Table-column)是通过插槽的,我们使用​​slot​​接收一下就可以了

  

到了这里基本逻辑已经完成了,再进一步,一般我们的表格需要loading,loading应该由父组件自己决定如何使用,但是状态的改变由本组件处理,这里可以使用​​.sync​​修饰符,loading逻辑加在​​getTableData​​中即可

<script>export default {  props: {    loading: {      type: Boolean,      default: false,    },  },  methods: {    async getTableData() {      try {        const { current, size } = this.page        this.$emit("update:loading", true)        const { data, total } = await this.fetchData(current, size)        this.tableData = data        this.page.total = total      } catch (err) {        this.tableData = []        this.page.total = 0      } finally {        this.$emit("update:loading", false)      }    },  }}</script>

loading也加完了,功能就已经完成了,但是还存在一些问题,el-table有很多的Attributes、Events和Methods,Attributes和Events我们透传给el-table即可,Methods需要el-table的ref,如果父组件直接使用ref,获取的是组件外层的div,无法获取到el-table的ref,我们暴露一个方法抛出el-table的ref即可

<script>export default {  methods: {    getTableRef() {      return this.$refs.tableRef    }  }}</script>

至此,​​PageTable​​就写完了,完整代码如下

<script>export default {  name: "PageTable",  props: {    /**     * 获取表格数据的请求方法     * @param {Number} current 当前页数     * @param {Number} size 每页条数     * @param {Object} sort 排序     * @param {String} sort.orderBy 排序的key     * @param {("ascending"|"descending"|null)} sort.rule 排序的规则     */    fetchData: {      type: Function,      required: true    },    pageSizes: {      type: Array,      default: () => [ 10, 20, 50, 100, 150 ]    },    loading: {      type: Boolean,      default: false    },  },  data() {    return {      page: {        current: 1,        size: 10,        total: 0      },      tableData: [],      sort: {        orderBy: "",        rule: ""      }    }  },  created() {    this.getTableData()  },  methods: {    /** 搜索,可通过 $refs 调用此方法 */    search() {      this.page.current = 1      this.getTableData()    },    /** 获取表格数据,可通过 $refs 调用此方法 */    async getTableData() {      try {        const { current, size } = this.page        this.$emit("beforeFetch")        this.$emit("update:loading", true)        const { data, total } = await this.fetchData(current, size, this.sort)        this.$emit("fetched", data)        this.tableData = data        this.page.total = total      } catch (err) {        this.$emit("fetched", [])        this.tableData = []        this.page.total = 0      } finally {        this.$emit("update:loading", false)      }    },    /** 获取el-table的ref,可通过 $refs 调用此方法 */    getTableRef() {      return this.$refs.tableRef    },    sortChange({ prop, order }) {      this.sort = {        orderBy: prop,        rule: order || ""      }      this.getTableData()    }  }}</script>

推荐内容