20行代码封装一个可配置的(vue)table组件,够了吗?我觉得还行

组件需求

  • 传一个columns配置文件,即可生成对应的table
  • 传一个data即可渲染对应的数据
  • 可通过插槽的方式对数据进行二次处理

组件设计

  • columns是一个数组类型(必须)
  • columns里面每一项是一个对象(必须)
  • columns每个对象应该包含:

    • title(String):根据这个键生成的thead对应的th(必填)
    • dataIndex (String): 根据这个键渲染对象的数据(这个键跟data里面的键一一对应)(必填)
    • customRender(Boolean):根据这个键判断是否要分配一个对应的插槽(可选)
  • data是一个数组类型(必须)
  • data里面每一项是一个对象,里面的键必须跟上面的columns的dataIndex一一对应(必须)

期待的使用方式



  
  


期待的效果

效果

组件的实现(这里使用JXS)

首先根据上面的的需求,先定义两个props


props: {
    columns: {
      type: Array,
      required: true
    },
    data: {
      type: Array,
      default: () => []
    }
  }

接着根据传进来的columns的title生成对应的thead

// 根据配置生成thead
_renderHeader (h) {
  return h('thead', { class: 'y-header' }, [
    h('tr', { class: 'y-header-row' }, [
      this.columns.map(row => {
        return h('th', { class: ['y-header-column', 'y-table-left'] }, row.title)
      })
    ])
  ])
}

紧接着,根据columns的dataIndex结合data的键值对渲染对应的数据,再根据columns的customRender判断是否分配对应的插槽

// 根据配置生成tbody,再根据customRender分配作用域插槽
_renderBody (h) {
  return h('tbody', {}, [
    this.data.map(row => {
      return h('tr', { class: 'y-body-row' }, [
        this.columns.map(item => {
          return h('td', { class: 'y-body-column' }, item.customRender && this.$scopedSlots[item.dataIndex]
            ? this.$scopedSlots[item.dataIndex](row[item.dataIndex], {
              ...row
            }) : row[item.dataIndex])
        })
      ])
    })
  ])
}

这里生成的插槽是作用域插槽,有时候它是封装组件的神一样的存在,这里把当前的值传给插槽的第一参数,当前的行数据传给第二参数,所以外面就可以这样拿到数据

 

最后组装table,return 出去就OK了

// 组装table
  _renderTable (h) {
    return (
      
        {this._renderHeader(h)}
        {this._renderBody(h)}
      
) } render (h) { return ( this._renderTable(h) ) }

总结

到此,根据上面的需求已经实现了对应的可配置的table组件,比较核心的是上面两个生成方法(_renderHeader,_renderBody)大概也就20行,对于熟悉的JSX和作用域插槽的同学来说再容易不过了。
有兴趣的同学可以继续根据自己的需要拓展自己需要的table组件。

你可能感兴趣的:(javascript,vue.js,component,element-ui)