阅读 301

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

前言

入职现在这家公司有几个月的时间了,前期主要做公司的业务,顺手给上一位前端老哥的代码做了一些优化,与其说是优化,其实这就是自己本身比较懒,至于上一个前端老哥代码写得咋样就不做讨论了,贴出来了我怕被找到被打,况且自己本身也是一个小菜鸟~,随心所欲的写代码并不是一件好事,也许你当时效率是拿捏了,可是到头来如果自己维护的话,大概率会感叹这*写的什么玩意。有点跑题了,写这篇文章的目的主要是记录一下自己根据项目的业务组成,对原有的重复代码(表单查询)进行封装,同时也为一些同学提供一下自己的封装思路。项目采用 Vue2 + element-ui + Jsx

安装JSX插件 Element-ui
npm 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的语法,可以自行去官网了解。

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

image-20220225130239123.png

页面中包含两个部分,表单+表格,我们先将表单查询抽离出来做成一个组件。

表单组件封装分析
  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框的创建,效果:

image-20220225162249343.png

显然,这样子实现肯定时满足不了我们的需求的,要考虑到表单查询一定是多个的,所以 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) {       // 这里不使用if else来判断 我怕太多了看不清代码 用对象配置(策略模式)实现不同输入框的渲染       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> 复制代码

于是有了以下的渲染结果:

image-20220226112640620.png

结语

其实到这里也只是在涉及到了jsx在vue当中的一些简单使用,写这篇文章也只是记录一下自己一开始的思路,这也只是自己做封装的时的一个最基本的骨架,在项目中肯定还会有很多东西需要扩展,比如说后台给你的数据永远不是你想要的,ui大婶动不动就给页面加朵花等等,要考虑到的东西还有挺多的,不过都可以以此为基础做扩展,最后如果大家觉得这样封装可行的话,接下来我会把表格的封装也整理一下。



作者:小小小小---柏
链接:https://juejin.cn/post/7068894386993659912


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐