青岛网站建设华夏,沈阳室内设计公司排名,挖矿网站怎么做,做网站电话销售说辞组件库背景#xff1a;使用elementplusvue封装了一个通过表单组件。通过JSX对el-form下的el-input和el-button等表单进行统一封装#xff0c;最后达到#xff0c;通过数据即可一键生成页面表单的功能。
1.使用vite创建vue项目 npm create vitelatest elementplus-auto-form…组件库背景使用elementplusvue封装了一个通过表单组件。通过JSX对el-form下的el-input和el-button等表单进行统一封装最后达到通过数据即可一键生成页面表单的功能。
1.使用vite创建vue项目 npm create vitelatest elementplus-auto-form -- --template vue 2.项目目录
注意此处main.js入口文件只是当前项目入口文件组件库打包的入口文件还是封装Form表单组件下的index.js 3.封装TFrom.vue
表单表单校验JSX生成表单项
TForm.vue:
templateel-form refFormRef:classformBorder?form-border::modelmodelForm:ruleseditable ? rules : {}:inlineinline:label-positionlabelPosition:label-widthlabelWidthslot nameheader/slotel-row :gutterelRowGutterel-col v-for(item,index) in data:spanitem.span :keyindex!-- !item.isHidden为控制页面控件显示与否 --el-form-item v-if!item.isHidden :classisCustom?custom-form-item: :labelitem.label ? item.label : :propitem.prop:label-widthitem.labelWidthFormItem :formDatamodelForm:editableeditable:dataitem/FormItemFormItem v-ifitem.children :formDatamodelForm:editableeditable:clearablefalse:dataitem.children/FormItem/el-form-item/el-colel-col classbutton-list v-ifbtnList btnList.length:span24el-form-item :classisCustom?custom-form-item:div v-for(item,index) in btnList :keyindexFormButton :formDatamodelForm:editableeditable:dataitemon-clickonClick(item)/FormButton/div/el-form-item/el-colslot namefooter/slot/el-row/el-form
/templatescript setup
import { ref } from vue
import formItem from ./FormItem.jsx
import formButton from ./FormButton.jsx// 除data外其他都不是必传项
const prop defineProps({modelForm:{type: Object,require: true,},rules: {type: Object,default: {}},data: {type: Object,require: true,default: []},inline:{type: Boolean,default: true},labelWidth: {type: String,default: 120},labelPosition: {type: String,default: right},editable: {type: Boolean,default: true},colLayout: {type: Object,default(){return {xl: 5, //2K屏等lg: 8, //大屏幕如大桌面显示器md: 12, //中等屏幕如桌面显示器sm: 24, //小屏幕如平板xs: 24 //超小屏如手机}}},elRowGutter: {type: Number,default: 10},size: {type: String,default: default},btnList:{type: Object,default: []},formBorder:{type: Boolean,default: false},formRef:{type: String,default: formRef},customFormItem:{type: Boolean,default: false}})const FormItem formItem();
const FormButton formButton();const FormRef ref()
const isCustom ref(false);// 表单按钮
function onClick(data) {if (!data.onClick) returndata.onClick()
}// 表单校验
async function validate() {if (!FormRef.value) returnconst result await FormRef.value.validate()return result;
}// 清除表单验证
async function resetFields() {if(!FormRef.value) return await FormRef.value.resetFields();return await FormRef.value.resetFields()
}// 自定义el-form-item样式
if(prop.customFormItem){isCustom.value true;
}defineExpose({validate,resetFields,
})/script
style scoped
.button-list{display: flex;justify-content: center;
}.form-border {width: 94%;border: solid 2px rgba(219, 217, 217, 0.6);border-radius: 10px;margin-left: auto;margin-right: auto;padding: 20px;
}.custom-form-item {margin-bottom: 4px;margin-right: 12px;margin-left: 12px;
}
/style
FormItem.jsx:
import {ElInput,ElSelect,ElOption,ElButton} from element-plusimport { defineComponent } from vue// 普通显示
const Span (form, data) (span{data}/span)// 输入框
const Input (form, data) (ElInputv-model{form[data.field]}type{data.type}input-style{data.inputStyle}size{data.size}autocomplete{data.autocomplete}show-password{data.type password}clearableplaceholder{data.placeholder}autosize {{minRows: 3,maxRows: 4,}}{...data.props}/ElInput)
// 文本框
const Textarea (form, data) (ElInputv-model{form[data.field]}type{data.type}input-style{data.inputStyle}size{data.size}// 设置rows就不能设置自适应autosizerows{data.rows}clearable{data.clearable}placeholder{data.placeholder}{...data.props}{data.rows}/ElInput)const setLabelValue (_item, { optionsKey } {}) {return {label: optionsKey ? _item[optionsKey.label] : _item.label,value: optionsKey ? _item[optionsKey.value] : _item.value,}}// 选择框const Select (form, data) (ElSelectsize{data.size}v-model{form[data.field]}filterablestyle{data.style}clearable{data.clearable}placeholder{data.placeholder}{...data.props}{data.options.map((item) {return ElOption {...setLabelValue(item, data)} /})}/ElSelect)const Button (form, data) {ElButtontype{data.type}size{data.size}icon{data.icon}plain{data.plain}click{data.clickBtn}value{data.value}/ElButton}const setFormItem (form,data,editable,) {if (!form) return nullif (!editable) return Span(form, data)switch (data.type) {case input:return Input(form, data)case textarea:return Textarea(form, data)case password:return Input(form, data)// 输入框只能输入数字case number:return Input(form, data)case select:return Select(form, data)case date:case daterange:return Date(form, data)case time:return Time(form, data)case radio:return Radio(form, data)case checkbox:return Checkbox(form, data)case button:return Button(form, data)default:return null}}export default () defineComponent({props: {data: Object,formData: Object,editable: Boolean,},setup(props) {return () props.data? setFormItem(props.formData, props.data, props.editable): null},}) 按需引入elementplus
// element-plus按需导入
import AutoImport from unplugin-auto-import/vite
import Components from unplugin-vue-components/vite
import { ElementPlusResolver } from unplugin-vue-components/resolvers
import vueJsx from vitejs/plugin-vue-jsx
import path from path...plugins: [vue(),// 用到JSX语法vueJsx(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],resolve: {alias: {: path.resolve(__dirname, src)}},
...
通过install插件方式进行使用
import TForm from ./TForm.vue;export default {install (app) {// 在app上进行扩展app提供 component directive 函数// 如果要挂载原型 app.config.globalProperties 方式// TForm自定义即可app.component(TForm, TForm);}
}
4.打包配置
设置打包文件名包路径等
注意打包入口为index.js文件(需要使用导出install方法中的组件)而不是main.js文件main.js中引入index.js只是用于本地测试 build: {outDir: elementplus-auto-form, //输出文件名称lib: {entry: path.resolve(__dirname, ./src/package/index.js), //指定组件编译入口文件name: elementplus-auto-form,fileName: elementplus-auto-form,}, //库编译模式配置rollupOptions: {// 确保外部化处理那些你不想打包进库的依赖external: [vue],output: {// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量globals: {vue: Vue,},},}, }, npm run build进行打包 5.在打好的包下创建package.json文件
在package.json文件中对包版本等信息进行配置 {name: elementplus-auto-form,version: 1.0.0,description: 对elementplus的form表单进行封装达到根据数据一键生成表单功能,keywords: [elementplus,el-form,auto-form],main: elementplus-auto-form.js,scripts: {test: echo \Error: no test specified\ exit 1},author: xxx,license: ISC,private: false
}6.上传到npm仓库
在npm官网创建自己的账号并登录。在打包好的文件路径下使用npm login会跳转到npm官网进行登录登录完成后将镜像源改为npm官方npm config set registryhttps://registry.npmjs.org然后使用npm publish将包上传到npm仓库 7.从npm下载包并进行测试
将镜像切回到淘宝源 npm config set registry https://registry.npm.taobao.org 查看当前镜像源 npm config get registry 配置到淘宝镜像后首先会到淘宝镜像中下载没有则去npm官网进行下载
下载后node_modules下的包 8.代码中使用包elementplus-auto-form
//main.js
import elementplus-auto-form/style.css
import TForm from elementplus-auto-form; const app createApp(App);
app.use(router).use(TForm).mount(#app)
Form.vue页面使用
script setup
import { reactive } from vue
import cronjobConfig from ./cronjobConfig
const formItems cronjobConfig.value.formItems ? cronjobConfig.value.formItems : {};
const cronjobForm reactive({iffLength: 1793,keySize: ,dataFileName: ,wfdName: ,version:
})
/scripttemplatet-form refcronjobFormRef :btnListcronjobConfig.buttons :modelFormcronjobForm :formBordertrue:rulescronjobConfig.rules :dataformItemstemplate #headerb请输入转码程序生成条件/bbr /br //template/t-form
/template测试数据
import { DocumentDelete, Edit, Download } from element-plus/icons-vue
import { shallowRef ,ref } from vuelet checkNum (rule, value, callback) {// 函数用于检查其参数是否是非数字值,如果参数值为 NaN 或字符串、对象、undefined等非数字值则返回 true, 否则返回 false。if (isNaN(value)) {return callback(iffLength must be a number);}return callback();
}
let checkVersion (rule, value, callback) {let regex /^V(\d{2})[A-L]$/;if (regex.test(value)) {callback();return true;} else {callback(new Error(Version must be similar to V23G));return false;}
}const cronjobConfig ref({rules: {iffLength: [{ required: true, message: Please input iff length, trigger: blur },{ validator: checkNum, trigger: blur }],keySize: [{ required: true, message: Please select key size, trigger: change, }],dataFileName: [{required: true,message: Please input data filename,trigger: blur,}],wfdName: [{required: true,message: Please input wfd name,trigger: blur,}],version: [{ required: true, message: Please input version, trigger: blur },{ validator: checkVersion, trigger: blur }]},formItems: [{field: iffLength,prop: iffLength,label: iff length,placeholder: 1793,labelWidth: 150px,type: input,// size: small,span: 12,},{field: keySize,prop: keySize,type: select,label: key size,placeholder: select key size,// editable: true,// size: small,span: 12,options: [{ label: 6, value: 6 }, { label: 9, value: 9 }]},{field: dataFileName,prop: dataFileName,type: input,label: data filename,labelWidth: 150px,placeholder: data filename,// isHidden: false,span: 12,},{field: wfdName,prop: wfdName,type: input,label: WFD name,placeholder: WFD name,span: 12,},{field: version,prop: version,type: input,label: version,labelWidth: 150px,placeholder: version,span: 12,},],// 按钮buttons: [{name: 生成转码程序,title: generateCronjob,type: primary,size: default, //可以是defaultsmall,largeicon: shallowRef(Edit),// 按钮是否为朴素类型// plain: true,onClick: null}, {name: 重置,type: info,title: resetCronjob,size: default,icon: shallowRef(DocumentDelete),// plain: true,onClick: null},{name: 下载转码程序,type: success,title: downloadCronjob,size: default,icon: shallowRef(Download),isHidden: true,// plain: true,onClick: null}],ref: cronjobFormRef,labelWidth: 120px,labelPosition: right,inline: true,editable: true,// 单元列之间的间隔elRowGutter: 20,// size: small,// 是否需要form边框formBorder: true,colLayout: {xl: 5, //2K屏等lg: 8, //大屏幕如大桌面显示器md: 12, //中等屏幕如桌面显示器sm: 24, //小屏幕如平板xs: 24 //超小屏如手机}
});export default cronjobConfig;
9.测试效果