前言
入职现在这家公司有几个月的时间了,前期主要做公司的业务,顺手给上一位前端老哥的代码做了一些优化,与其说是优化,其实这就是自己本身比较懒。写这篇文章的目的主要是记录一下自己根据项目的业务组成,对原有的重复代码(表单查询)进行封装,同时也为一些同学提供一下自己的封装思路。项目采用 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之后,开始分析应该怎么封装。
-
看看需要封装的页面长什么样,这种很常规的查询表格页面,也是后台管理类项目中用得最多的,非常建议进行封装,为接下来的开发节省时间,同时也让项目不那么臃肿。
页面中包含两个部分,表单+表格,我们先将表单查询抽离出来做成一个组件。
表单组件封装分析
-
一个表单可能会包含的input、select、time等各种输入组件,所以输入类型可配置。
-
根据不同的输入类型,传入不同的参数。
-
提交查询时,后台提供的键名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当中的一些简单使用,写这篇文章也只是记录一下自己一开始的思路,这也只是自己做封装的时的一个最基本的骨架,在项目中肯定还会有很多东西需要扩展,要考虑到的东西还有挺多的,不过都可以以此为基础做扩展。