美文网首页
render + mixins 写法,进阶

render + mixins 写法,进阶

作者: 三省吾身_9862 | 来源:发表于2021-12-31 16:48 被阅读0次

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

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

    • mixins/page-base.js
    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>
        )
      }
    }
    
    • page.vue
    <script>
    import pageBase from '@/mixins/page-base.js'
    
    export default {
      mixins: [pageBase],
    }
    </script>
    

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

    1 查询条件

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


      页面的差异
    • mixins/page-params.js
    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>
        )
      }
    }
    
    • page.vue
    <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
    • page-search.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>
          )
        },
      }
    }
    
    • page-content.js
    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>
          )
        },
      }
    }
    
    • footer-pagination.js
    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
    • page-mixins.js
    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

    相关文章

      网友评论

          本文标题:render + mixins 写法,进阶

          本文链接:https://www.haomeiwen.com/subject/zfwgqrtx.html