jsx + element-ui 表单查询简单封装

前言
入职现在这家公司有几个月的时间了,前期主要做公司的业务,顺手给上一位前端老哥的代码做了一些优化,与其说是优化,其实这就是自己本身比较懒。写这篇文章的目的主要是记录一下自己根据项目的业务组成,对原有的重复代码(表单查询)进行封装,同时也为一些同学提供一下自己的封装思路。项目采用 Vue2 + element-ui + Jsx
安装JSX插件 Element-ui
install @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props babel-plugin-jsx-v-model element-ui -S
配置 .babelrc
{
  "plugins": ["transform-vue-jsx", "transform-runtime", "jsx-v-model"]
}
首先看一下Jsx代码是啥样的
 render() {
    return (
        //动态绑定样式
      <div class={ 1 + 1 === 2 ? 'active' : ''}>
        //循环生成多个元a素
        {[1,2,3].map(elment=> <a> {element} </a> )}
      </div>
    )
  }

关于 Jsx 的语法,可以自行去官网了解。

  • 看看需要封装的页面长什么样,这种很常规的查询表格页面,也是后台管理类项目中用得最多的,非常建议进行封装,为接下来的开发节省时间,同时也让项目不那么臃肿。

在这里插入图片描述
页面中包含两个部分,表单+表格,我们先将表单查询抽离出来做成一个组件。

表单组件封装分析
  1. 一个表单可能会包含的input、select、time等各种输入组件,所以输入类型可配置。
  2. 根据不同的输入类型,传入不同的参数。
  3. 提交查询时,后台提供的键名valueKey可配置。综合我们的最基本的配置参数长这样:
{
   type: 'input',
   label: '消息标题:',
   width: '200',
   placeholder: '请输入标题',
   valueKey: 'title'
}
表单组件内部具体实现
  • 结合上面的配置参数,编写组件代码QueryComponent.vue:
<script>
export default {
  name: "QueryComponent",
  //接收option
  props: {
    option: {
      type: Object,
      required: true
    }
  },
  data: () => ({
    queryData: {} //定义queryData用来保存表单输入后的键值对
  }),
  //渲染函数
  render() {
    return <div>{this.renderHtml(this.option)}</div>;
  },
  methods: {
    //接收参数,返回相应的Jsx
    renderHtml(option) {
      if (option.type === "input") {
        return (
          <el-form inline>
            <el-form-item label={option.label} label-position="right">
              <el-input
                style={{ width: option.width + "px" }}
                v-model={this.queryData[option.valueKey]}
                placeholder={option.placeholder}
              ></el-input>
            </el-form-item>
          </el-form>
        );
      }
    }
  }
};
</script>
  • 在页面引入组件
<template>
  <div>
    <QueryComponent :option="option" />
  </div>
</template>
<script>
import QueryComponent from "@/components/QueryComponent.vue";
export default {
  components: {
    QueryComponent
  },
  data: () => ({
    option: {
      type: "input",
      label: "消息标题:",
      width: "260",
      placeholder: "请输入标题",
      valueKey: "title"
    }
  })
};
</script>

到这里我们实现了一个input框的创建,效果:

在这里插入图片描述
显然,这样子实现肯定时满足不了我们的需求的,要考虑到表单查询一定是多个的,所以 option 参数应该是一个数组才合理:

<template>
  <div>
    <QueryComponent :options="options" @submit="submit" :reset="reset" />
  </div>
</template>
<script>
import QueryComponent from "@/components/QueryComponent.vue";
export default {
  components: {
    QueryComponent
  },
  data() {
    return {
      options: [
        {
          type: "input",
          label: "消息标题:",
          width: "260",
          placeholder: "请输入标题",
          valueKey: "title"
        },
        {
          type: "select",
          label: "消息类型:",
          width: "260",
          placeholder: "请选择类型",
          valueKey: "messageType",
          // select的options 一般是从后台获取的
          selectOptions: [
            {
              label: "系统消息1",
              value: "1"
            },
            {
              label: "系统消息2",
              value: "2"
            }
          ]
        }
      ]
    };
  },
  methods: {
    submit(queryData) {
      console.log("submit", queryData);
      //拿到queryData 进行查询
      // await this.$http.get("/api/message/query", {
      //   params: this.queryData
      // });
    },
    reset() {
      console.log("reset", this.queryData);
    }
  }
};
</script>

接下来在组件内部处理传进来的数组

<script>
export default {
  name: "QueryComponent",
  //接收option
  props: {
    options: {
      type: Array,
      default: () => []
    }
  },
  data: () => ({
    queryData: {}, //定义queryData用来保存表单输入后的键值对
    title: ""
  }),
  //渲染函数
  render() {
    return (
      // 遍历options 根据option的type属性来渲染不同的组件  再加两个按钮 一个查询 一个重置
      <div>
        <el-form inline>
          {this.options.map(option => this.renderHtml(option))}
          <el-form-item>
            <el-button type="primary" on-click={this.handleSubmit}>
              查询
            </el-button>
          </el-form-item>
          <el-form-item>
            <el-button on-click={this.handleReset}>重置</el-button>
          </el-form-item>
        </el-form>
      </div>
    );
  },
  methods: {
    //接收参数,返回相应的Jsx
    renderHtml(option) {
      // 对象配置(策略模式)实现不同输入框的渲染
      const renderResult = {
        input: () => (
          <el-form-item label={option.label} label-position="right">
            <el-input
              style={{ width: option.width + "px" }}
              v-model={this.queryData[option.valueKey]}
            ></el-input>
          </el-form-item>
        ),
        select: () => (
          <el-form-item label={option.label} label-position="right">
            <el-select
              style={{ width: option.width + "px" }}
              v-model={this.queryData[option.valueKey]}
            >
              {option.selectOptions.map(item => (
                <el-option label={item.label} value={item.value}></el-option>
              ))}
            </el-select>
          </el-form-item>
        )
      };
      return renderResult[option.type]();
    },
    // 点击查询按钮的时候触发父组件submit事件
    handleSubmit() {
      this.$emit("submit", this.queryData);
    },
    // 清空表单
    handleReset() {
      this.queryData = {};
      this.$emit("reset");
    }
  }
};
</script>

于是有了以下的渲染结果:
在这里插入图片描述

结语

其实到这里也只是在涉及到了jsx在vue当中的一些简单使用,写这篇文章也只是记录一下自己一开始的思路,这也只是自己做封装的时的一个最基本的骨架,在项目中肯定还会有很多东西需要扩展,要考虑到的东西还有挺多的,不过都可以以此为基础做扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值