zoukankan      html  css  js  c++  java
  • Vue + TypeScript + ElementUI 封装表头查询组件

    前段时间有朋友私信我 Vue + TypeScript 的问题,然后就打算写一篇 Vue + TypeScript 封装组件的文章

    正好公司项目中需要封装一个表头查询组件,就拿出来分享一下~

    组件的整体思路是通过一个 config 数组生成列表的头部表单:

    PS:配合《Vue 爬坑之路(九)—— 用正确的姿势封装组件》食用更佳

    一、组件设计

    这个组件由两部分组成:输入组件和按钮

    其中输入组件可以通过 v-for 循环渲染,并通过 v-if 来切换输入框 input 和下拉框 select

    每个输入组件都有各自的 v-model,可以在 config 传入对应的 code 来绑定对应的参数

    基于这些想法,组件的基本结构就出来了:

    由此可以设计出 config 的数据结构 data.ts:

    /*
     * data.ts
     *
     * 数据类型 - table-header 组件
     */
    
    export class SelectOptionItem {
      public value: String | Number;
      public label: String | Number;
    }
    
    export class HeaderConfigItem {
      public title: String;
      public code: String;
      public type?: 'select' | 'input';
      public options?: SelectOptionItem[]
    }

    二、内部逻辑

    整个组件需要传入两个必选参数:config 和 data

    data 是整个表头的数据对象,config 就是整个组件的配置项,由此渲染出头部结构

     然后还有“查询”和“清空”两个按钮

    这类公共组件不建议直接处理事件,所以通过 emit 将事件抛给父组件处理

    这里的 this._copy 是 data 的拷贝对象,在 mounted 的时候将 data 拷贝出来作为初始值,清空的时候再将这个初始值传回去

    这里会涉及到在子组件中对父组件传入的参数直接修改,所以需要用 sync 修饰符

    三、完整代码

    除了这些基本逻辑之外,我还添加了一个 size 用于控制整体的尺寸,然后基于自身的项目微调了样式,所以这部分仅做参考

    <template>
      <div class="table-header">
        <el-form :inline="true" :model="data" class="form--label-left" label-width="180px">
          <el-row :gutter="20">
            <el-col :span="8" v-for="item in config" :key="item.code">
              <el-form-item :label="item.title" class="table-header-item">
                <el-select v-if="item.type === 'select'" v-model="data[item.code]" :placeholder="`请输入${item.title}`" :size="size" clearable>
                  <el-option v-for="option in item.options" :key="option.value" :value="option.value" :label="option.label"></el-option>
                </el-select>
                <el-input v-else v-model="data[item.code]" :placeholder="`请输入${item.title}`" :size="size"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="8" class="table-header_button">
              <el-button :size="size" type="text" @click="reset">清空</el-button>
              <el-button :size="size" type="primary" icon="el-icon-search" @click="search">查询</el-button>
            </el-col>
          </el-row>
        </el-form>
      </div>
    </template>
    
    <script lang="ts">
      import { Component, Prop, Vue } from 'vue-property-decorator';
      import { HeaderConfigItem } from "./data.ts";
    
      @Component({})
      export default class TableHeader extends Vue {
        public _copy: Object = {}
        @Prop({ default: function () {
            return 'small'
          }})
        size: 'small' | 'mini' | 'medium'
    
        @Prop({})
        data: Object
    
        @Prop({default: []})
        config: HeaderConfigItem[]
    
        mounted() {
          this._copy = Object.assign({}, this.data)
        }
        // 查询
        search() {
          this.$emit('search', this.data)
        }
        // 清空
        reset() {
          this.$emit('update:data', Object.assign({}, this._copy))
          this.search()
        }
      }
    </script>
    
    <style lang="scss">
    .table-header {
      padding-top: 10px;
      .table-header_button {
        text-align: right;
        float: right;
        margin-bottom: 12px;
        line-height: 40px;
      }
      .table-header-item.el-form-item {
        width: 100%;
        display: flex;
        flex: auto;
        margin-bottom: 12px;
        .el-form-item__content, .el-select {
          width: 100%;
        }
      }
    }
    
    </style>

    父组件调用:

  • 相关阅读:
    HDU 2844 Coins(多重背包)
    HDU 4540 威威猫系列故事——打地鼠(DP)
    Codeforces Round #236 (Div. 2)
    FZU 2140 Forever 0.5
    HDU 1171 Big Event in HDU(DP)
    HDU 1160 FatMouse's Speed(DP)
    ZOJ 3490 String Successor
    ZOJ 3609 Modular Inverse
    ZOJ 3603 Draw Something Cheat
    ZOJ 3705 Applications
  • 原文地址:https://www.cnblogs.com/wisewrong/p/9052467.html
Copyright © 2011-2022 走看看