• 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>

    父组件调用:

  • 相关阅读:
    点击按钮icon input同步获取焦点
    修改vue项目中 elementUI input样式
    vue $route 和$router的区别
    vue 路由 vue-router 模式 hash history
    vue 路由跳转
    git 合并某个提交 git cherry-pick
    请求传参 有特殊符号
    前端 组件库 ,js等
    ajax请求成功,返回了数据,但是跳到了error情况
    微信-公众号-网页授权开发
  • 原文地址:https://www.cnblogs.com/wisewrong/p/9052467.html
Copyright © 2020-2023  润新知