render + mixins 写法,进阶

2021-12-31  本文已影响0人  三省吾身_9862

继续上篇:render + mixins 写法,基础篇

把page.vue中所有常用的配置,提取到mixins中

export default {
  data() {
    return {
      // 查询条件
      searchParams: {
        keyword: ''
      },
      cloneParams: {},
      // 表格
      table: {
        loading: false,
        data: []
      },
      // 分页
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  created() {
    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查询
     */
    search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 获取数据
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get('/data/list.json').then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 改变分页页数
     * @param {Number} page 页数
     */
     changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改变每页条数
     * @param {Number} size 每页条数
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },
    
    /**
     * 编辑
     * @param {Object} row 操作的行数据
     */
    editItem(row) {
      console.log(row)
    },

    /**
     * 删除
     * @param {Object} row 操作的行数据
     */
    deleteItem(row) {
      console.log(row)
    },

    /**
     * 渲染查询条件
     */
    genPageSearch() {
      return (
        <header class="page-search">
          <es-row>
            {this.genSearchItems()}
            {this.genSearchBtns()}
          </es-row>
        </header>
      )
    },

    /**
     * 渲染 查询表单
     */
    genSearchItems() {
      return (
        <es-col span={8} class="form-item">
          <label>查询条件</label>
          <es-input vModel={this.searchParams.keyword} placeholder="请输入查询关键字" />
        </es-col>
      )
    },
    
    /**
     * 渲染 查询按钮
     */
    genSearchBtns() {
      return (
        <es-col span={8} class="form-item">
          <es-button type="primary" loading={this.table.loading} vOn:click={() => this.search()}>查询</es-button>
          <es-button vOn:click={() => this.reset()}>重置</es-button>
        </es-col>
      )
    },

    /**
     * 渲染 主内容区域
     */
    genPageContent() {
      return (
        <main class="page-content">
          {this.genTable()}
        </main>
      )
    },

    /**
     * 渲染 table区域
     */
    genTable() {
      return (
        <es-table data={this.table.data}>
          <es-table-column prop="name" label="姓名" />
          <es-table-column prop="phone" label="手机号" />
          <es-table-column prop="address" label="地址" />
          <es-table-column label="操作" width="140" 
          scopedSlots={{
            default: ({ row }) => (
              <div>
                <es-button size="mini" type="primary" plain vOn:click={() => this.editItem(row)}>编辑</es-button>
                <es-button size="mini" type="danger" vOn:click={() => this.deleteItem(row)}>删除</es-button>
              </div>
            ),
          }} />
      </es-table>
      )
    },

    /**
     * 渲染 底部分页
     */
     genFooterPagination() {
      return (
        <footer class="page-pagination">
          <es-pagination
            vOn:size-change={this.changeSize}
            vOn:current-change={this.changePage}
            current-page={this.pagination.page}
            page-sizes={[10, 20, 50, 100]}
            page-size={this.pagination.size}
            layout="total, sizes, prev, pager, next, jumper"
            total={this.pagination.total}
          />
        </footer>
      )
    },
  },

  render() {
    return (
      <div class="page-container">
        {/* 查询条件 */}
        {this.genPageSearch()}
        {/* 内容区域 */}
        {this.genPageContent()}
        {/* 底部分页 */}
        {this.genFooterPagination()}
      </div>
    )
  }
}
<script>
import pageBase from '@/mixins/page-base.js'

export default {
  mixins: [pageBase],
}
</script>

处理查询条件、自定义内容区域、table配置,每个页面的差异

1 查询条件

  1. 自定义内容区域
  2. table配置


    页面的差异
export default {
  data() {
    return {
      // 接口配置
      apis: {
        search: '/api/search',
        delete: '/api/delete'
      },
      // 查询配置
      searchColumns: [{
        key: 'keyword',
        value: '',
        label: '查询条件',
      }],
      // 查询条件
      searchParams: {},
      cloneParams: {},
      // 表格
      table: {
        loading: false,
        data: []
      },
      // 表格配置
      tableColumns: [{
        label: '姓名',
        key: 'name',
        props: {
          width: 140
        },
        render: (h, { row }) => {
          return <span>{row.name}</span>
        }
      }],
      // 分页
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  created() {
    let params = {}
    this.searchColumns.forEach(item => {
      params[item.key] = item.value;
    });
    this.searchParams = params;

    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查询
     */
    search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 获取数据
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get(this.apis.search).then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 改变分页页数
     * @param {Number} page 页数
     */
    changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改变每页条数
     * @param {Number} size 每页条数
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },

    /**
     * 编辑
     * @param {Object} row 操作的行数据
     */
    editItem(row) {
      console.log(row)
    },

    /**
     * 删除
     * @param {Object} row 操作的行数据
     */
    deleteItem(row) {
      console.log(this.apis.delete, row)
    },

    /**
     * 渲染查询条件
     */
    genPageSearch() {
      return (
        <header class="page-search">
          <es-row>
            {this.genSearchItems()}
            {this.genSearchBtns()}
          </es-row>
        </header>
      )
    },

    /**
     * 渲染 查询表单
     */
    genSearchItems() {
      return this.searchColumns.map(item => (
        <es-col span={8} class="form-item">
          <label>{item.label}</label>
          {item.render ? item.render(this.$createElement, item) : this.genSearchItem(item)}
        </es-col>
      ))
    },

    /**
     * 
     * @param {Object} item 查询条件,单个配置对象
     * @returns {vNode} 
     */
    genSearchItem(item) {
      switch (item.type) {
        case 'select':
          return <es-select vModel={this.searchParams[item.key]} props={item.props}>
            {item.props.options.map(opt => <es-option key={opt.value} label={opt.label} value={opt.value} />)}
          </es-select>
        default:
          return <es-input vModel={this.searchParams[item.key]} props={item.props} />
      }
    },

    /**
     * 渲染 查询按钮
     */
    genSearchBtns() {
      return (
        <es-col span={8} class="form-item">
          <es-button type="primary" loading={this.table.loading} vOn:click={() => this.search()}>查询</es-button>
          <es-button vOn:click={() => this.reset()}>重置</es-button>
        </es-col>
      )
    },

    /**
     * 渲染 主内容区域
     */
    genPageContent() {
      return (
        <main class="page-content">
          {this.genTable()}
        </main>
      )
    },

    /**
     * 渲染 table区域
     */
    genTable() {
      return (
        <es-table data={this.table.data}>
          {
            this.tableColumns.map(item => {
              if (item.render) {
                return <es-table-column label={item.label} props={item.props} scopedSlots={{
                  default: (props) => item.render(this.$createElement, props)
                }} />
              } else {
                return <es-table-column prop={item.key} label={item.label} props={item.props} />
              }
            })
          }
        </es-table>
      )
    },

    /**
     * 渲染 底部分页
     */
    genFooterPagination() {
      return (
        <footer class="page-pagination">
          <es-pagination
            vOn:size-change={this.changeSize}
            vOn:current-change={this.changePage}
            current-page={this.pagination.page}
            page-sizes={[10, 20, 50, 100]}
            page-size={this.pagination.size}
            layout="total, sizes, prev, pager, next, jumper"
            total={this.pagination.total}
          />
        </footer>
      )
    },
  },

  render() {
    return (
      <div class="page-container">
        {/* 查询条件 */}
        {this.genPageSearch()}
        {/* 内容区域 */}
        {this.genPageContent()}
        {/* 底部分页 */}
        {this.genFooterPagination()}
      </div>
    )
  }
}
<script>
import pageParams from '@/mixins/page-params.js'

export default {
  mixins: [pageParams],

  data() {
    return {
      // 接口配置
      apis: {
        search: '/data/list.json',
        delete: '/api/delete'
      },
      // 自定义 查询条件展示
      searchColumns: [
        {
          label: '姓名',
          key: 'name',
          value: '',
        },
        {
          label: '状态',
          key: 'status',
          value: true,
          type: 'select',
          props: {
            options: [
              { label: '开启', value: true },
              { label: '关闭', value: false },
            ],
          },
        }
      ],
      // 自定义 table配置展示
      tableColumns: [
        {
          label: '姓名',
          key: 'name',
        },
        {
          label: '状态',
          key: 'status'
        },
        {
          label: '操作',
          props: {
            width: 140
          },
          render: (h, { row }) => {
            return (
              <div>
                <es-button size="mini" type="primary" plain vOn:click={() => this.editItem(row)}>编辑</es-button>
                <es-button size="mini" vOn:click={() => this.checkDetail(row)}>详情</es-button>
              </div>
            )
          }
        }
      ],
    }
  },

  methods: {
    /**
     * 查看详情
     * @param {Object} row 操作的行数据
     */
    checkDetail(row) {
      console.log(row)
    }
  },

  render() {
    return (
      <div class="page-container">
        {/* 查询条件 */}
        {this.genPageSearch()}
        {/* 自定义 内容区域 展示*/}
        <main class="page-content">
          <div style="padding: 8px 0 0 8px"><es-button size="mini">更新全部状态</es-button></div>
          {this.genTable()}
        </main>
        {/* 底部分页 */}
        {this.genFooterPagination()}
      </div>
    )
  },
}
</script>

按页面版块拆分mixins,再按需拼装

说明:这里只是举例,可以拆分;这样拆分并不合理;拆分非常适合用于UI组件开发;

1. 拆分为 page-search.js 、 page-content.js 、footer-pagination.js
export default {
  data() {
    return {
      // 查询配置
      searchColumns: [{
        key: 'keyword',
        value: '',
        label: '查询条件',
      }],
      // 查询条件
      searchParams: {},
      cloneParams: {},
    }
  },

  created() {
    let params = {}
    this.searchColumns.forEach(item => {
      params[item.key] = item.value;
    });
    this.searchParams = params;

    this.cloneParams = JSON.parse(JSON.stringify(this.searchParams))
    this.search()
  },

  methods: {
    /**
     * 查询
     */
     search() {
      this.pagination.page = 1;
      this.getTableData();
    },

    /**
     * 获取数据
     */
    getTableData() {
      this.table.loading = true;
      this.$axios.get('/data/list.json').then(({ data }) => {
        this.table.loading = false;
        this.table.data = data.list;
        this.pagination.total = data.totalCount;
      }).catch(() => {
        this.table.loading = false;
      })
    },

    /**
     * 重置
     */
    reset() {
      this.searchParams = JSON.parse(JSON.stringify(this.cloneParams))
    },

    /**
     * 渲染查询条件
     */
     genPageSearch() {
      return (
        <header class="page-search">
          <es-row>
            {this.genSearchItems()}
            {this.genSearchBtns()}
          </es-row>
        </header>
      )
    },

    /**
     * 渲染 查询表单
     */
    genSearchItems() {
      return this.searchColumns.map(item => (
        <es-col span={8} class="form-item">
          <label>{item.label}</label>
          {item.render ? item.render(this.$createElement, item) : this.genSearchItem(item)}
        </es-col>
      ))
    },

    /**
     * 
     * @param {Object} item 查询条件,单个配置对象
     * @returns {vNode} 
     */
    genSearchItem(item) {
      switch (item.type) {
        case 'select':
          return <es-select vModel={this.searchParams[item.key]} props={item.props}>
            {item.props.options.map(opt => <es-option key={opt.value} label={opt.label} value={opt.value} />)}
          </es-select>
        default:
          return <es-input vModel={this.searchParams[item.key]} props={item.props} />
      }
    },

    /**
     * 渲染 查询按钮
     */
    genSearchBtns() {
      return (
        <es-col span={8} class="form-item">
          <es-button type="primary" loading={this.table.loading} vOn:click={() => this.search()}>查询</es-button>
          <es-button vOn:click={() => this.reset()}>重置</es-button>
        </es-col>
      )
    },
  }
}
export default {
  data() {
    return {
      // 表格
      table: {
        loading: false,
        data: []
      },
      // 表格配置
      tableColumns: [{
        label: '姓名',
        key: 'name',
        props: {
          width: 140
        },
        render: (h, { row }) => {
          return <span>{row.name}</span>
        }
      }],
    }
  },

  methods: {
    /**
     * 编辑
     * @param {Object} row 操作的行数据
     */
     editItem(row) {
      console.log(row)
    },

    /**
     * 删除
     * @param {Object} row 操作的行数据
     */
    deleteItem(row) {
      console.log(row)
    },
    
    /**
     * 渲染 主内容区域
     */
    genPageContent() {
      return (
        <main class="page-content">
          {this.genTable()}
        </main>
      )
    },

    /**
     * 渲染 table区域
     */
    genTable() {
      return (
        <es-table data={this.table.data}>
          {
            this.tableColumns.map(item => {
              if (item.render) {
                return <es-table-column label={item.label} props={item.props} scopedSlots={{
                  default: (props) => item.render(this.$createElement, props)
                }} />
              } else {
                return <es-table-column prop={item.key} label={item.label} props={item.props} />
              }
            })
          }
        </es-table>
      )
    },
  }
}
export default {
  data() {
    return {
      // 分页
      pagination: {
        page: 1,
        size: 20,
        total: 78
      }
    }
  },

  methods: {
    /**
     * 改变分页页数
     * @param {Number} page 页数
     */
     changePage(page) {
      this.pagination.page = page
      this.getTableData()
    },

    /**
     * 改变每页条数
     * @param {Number} size 每页条数
     */
    changeSize(size) {
      this.pagination.size = size
      this.changePage(1)
    },
    
    /**
     * 渲染 底部分页
     */
     genFooterPagination() {
      return (
        <footer class="page-pagination">
          <es-pagination
            vOn:size-change={this.changeSize}
            vOn:current-change={this.changePage}
            current-page={this.pagination.page}
            page-sizes={[10, 20, 50, 100]}
            page-size={this.pagination.size}
            layout="total, sizes, prev, pager, next, jumper"
            total={this.pagination.total}
          />
        </footer>
      )
    },
  }
}
2. 组装mixins
import pageSearch from './page-search'
import pageContent from './page-content'
import footerPagination from './footer-pagination'

export default {
  mixins: [
    pageSearch,
    pageContent,
    footerPagination
  ],

  render() {
    return (
      <div class="page-container">
        {/* 查询条件 */}
        {this.genPageSearch()}
        {/* 内容区域 */}
        {this.genPageContent()}
        {/* 底部分页 */}
        {this.genFooterPagination()}
      </div>
    )
  }
}
3. 引用mixins(嵌套引用)
<script>
import pageMixins from '@/mixins/page-mixins.js'

export default {
  mixins: [pageMixins],

  data() {
    return {
      // 接口配置
      apis: {
        search: '/data/list.json',
        delete: '/api/delete'
      },
      // 自定义 查询条件展示
      searchColumns: [
        {
          label: '姓名',
          key: 'name',
          value: '',
        },
        {
          label: '状态',
          key: 'status',
          value: true,
          type: 'select',
          props: {
            options: [
              { label: '开启', value: true },
              { label: '关闭', value: false },
            ],
          },
        }
      ],
      // 自定义 table配置展示
      tableColumns: [
        {
          label: '姓名',
          key: 'name',
        },
        {
          label: '状态',
          key: 'status'
        },
        {
          label: '操作',
          props: {
            width: 140
          },
          render: (h, { row }) => {
            return (
              <div>
                <es-button size="mini" type="primary" plain vOn:click={() => this.editItem(row)}>编辑</es-button>
                <es-button size="mini" vOn:click={() => this.checkDetail(row)}>详情</es-button>
              </div>
            )
          }
        }
      ],
    }
  },

  methods: {
    /**
     * 查看详情
     * @param {Object} row 操作的行数据
     */
    checkDetail(row) {
      console.log(row)
    }
  },

  render() {
    return (
      <div class="page-container">
        {/* 查询条件 */}
        {this.genPageSearch()}
        {/* 自定义 内容区域 展示*/}
        <main class="page-content">
          <div style="padding: 8px 0 0 8px"><es-button size="mini">更新全部状态</es-button></div>
          {this.genTable()}
        </main>
        {/* 底部分页 */}
        {this.genFooterPagination()}
      </div>
    )
  },
}
</script>

源码链接:https://gitee.com/wkp_mayun/render-mixins-senior

上一篇下一篇

猜你喜欢

热点阅读