基于elementUI封装了基础表单组件
开头先BB两句
elementUI
的表单组件,自带表单验证规则。虽然已经很方便了,但是我还是想封装一下。
通常用到的表单类型,主要包括:Radio 单选框,输入框,下拉框
。
我封装了一个基础组件。把这些表单数据,放在一个json对象
里面,传入封装好的基础组件。然后循环遍历,根据选项类型,展示输入框还是下拉框,等等。
项目中需要用到时,只需要安装,引入,配置json文件
即可。
封装好的组件,放在项目中的components
文件夹中,作为公共组件引入使用。
跟住,我又将整个基础表单的组件,发布到了npm
上面。
封装组件并发布到npm
那么,如何将封装好的组件,发布到npm上呢?
第一步,新建一个vue项目,使用简洁的webapck配置模板,就可以了。
vue init webpack-simple my-project
第二步,在src文件夹下,新建一个components文件夹,放入封装好的BasicForm组件。
第三步,在根目录下新建一个index.js文件。
Vue的插件必须提供一个公开方法 install,该方法会在你使用该插件,也就是 Vue.use(yourPlugin)时被调用。这样也就给 Vue全局注入了你的所有的组件。
import basicForm from './src/components/basicForm/index.vue';
//注册组件
basicForm.install = Vue => Vue.component(basicForm.name, basicForm);
export default basicForm;
第四步,修改配置文件 webpack.config.js entry和output属性
entry: process.env.NODE_ENV == 'development' ? './src/main.js' : './index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'basicForm.js',
library: 'basicForm', // 指定的就是你使用require时的模块名
libraryTarget: 'umd', // 指定输出格式
umdNamedDefine: true // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
},
第五步,修改 package.json 文件
//name就是发布后的包名
"name": "@orzr3/basic-form",
"private": false,
"main": "dist/basicForm.js",
第六步,提交发布
首先,要注册一个npm账号,官网链接在此:
传送门
PS
如果将镜像设置成了淘宝镜像,先设置回来,否则会报错
npm config set registry http://registry.npmjs.org
注册成功之后,登录npm账号,依次输入用户名,密码,邮箱
npm login
执行发布
npm publish
直接 npm publish 会报错,建议改为 npm publish --access=public
npm publish --access=public
发布成功之后,登录npm官网,点击头像,然后点击profile选项,可以看到已经发布的插件。
安装与使用
安装
npm i @orzr3/basic-form --save
引入
import BasicForm from '@orzr3/basic-form'
报错解决方案
vue报错:Module build failed: TypeError: this.getOptions is not a function
vue-cli构建项目使用sass报错
Module build failed: TypeError: this.getOptions is not a function
出现问题的原因是安装的sass-loader版本过高,选择安装较低版本的sass-loader即可。
npm install sass-loader@7.3.1 --save-dev
出现问题的原因是安装的sass版本过高,选择安装4.0+版本的sass即可。
npm install node-sass@4.14.1 --save-dev
参考文章
封装组件并发布到npm
传送门
示例代码
不知道我说清楚了没有,最后的最后,贴上安装使用的示例代码。
<template>
<div class="friends">
<div class="friend-main">
<h2>基础组件</h2>
<div class="info-box">
<basic-form
:ref="formModelObject.formName"
:formModel="formModelObject.formModel"
:refName="formModelObject.formName + 'RefName'"
:halfFormFlag="formModelObject.halfFormFlag"
defaultTextareaWidth="400px"
@submit="submitForm"
></basic-form>
<div class="btn-list">
<el-button type="primary" @click="submit">确认修改</el-button>
<el-button type="default" @click="reset">重新填写</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import BasicForm from '@orzr3/basic-form'
import { BasicInformationMixin } from "@/mixins/BasicInformationMixin";
export default {
name: "Friends",
mixins: [BasicInformationMixin],
components: {
BasicForm,
},
data() {
return {
url: {
edit: "/sys/user/updateBaseInfo",
},
};
},
methods: {
submit() {
this.$refs[this.formModelObject.formName].submit();
},
submitForm(object) {
const { refName, formData } = object;
formData.id = this.userInfo.id;
let key = this.active;
let httpurl = this.url.edit;
let method = "post";
this.$api.httpAction(httpurl, formData, method).then((res) => {
this.loading = false;
if (res.code == 200) {
} else {
this.$message.error(res.msg);
}
});
},
reset() {
this.$nextTick(() => {
this.$refs[this.formModelObject.formName].resetFields();
});
},
},
created() {
},
};
</script>
<style scoped>
</style>
mixins
文件夹下的BasicInformationMixin.js
文件
import {
validPhone,
validEmail,
validIDCard,
validPwd,
vaildRealName,
} from "@/utils/validate";
export const BasicInformationMixin = {
data() {
return {
formModelObject: {
formName: "backUp",
formModel: {
formList: [
{
value: "",
prop: "roleName",
label: "我的角色",
placeHolder: "",
disabled: true,
tips: "",
rules: {
value: [
{
required: false,
message: "",
trigger: "blur",
},
],
},
},
{
value: "",
prop: "loginName",
label: "登录帐号",
placeHolder: "",
disabled: true,
tips: "不可修改。一般用于后台登入名",
tipsColor: '#606266',
rules: {
value: [
{
required: false,
message: "",
trigger: "blur",
},
],
},
},
{
value: "",
prop: "userName",
label: "用户名",
placeHolder: "请输入用户名",
tips: "",
rules: {
value: [
{
required: true,
message: "请输入用户名",
trigger: "blur",
},
],
},
},
{
value: "",
prop: "sex",
label: "性别",
placeHolder: "",
tips: "",
type: "radio",
selectOptions: [
{
value: '0',
text: "男",
},
{
value: '1',
text: "女",
},
],
rules: {
value: [
{
required: true,
message: "请选择性别",
trigger: "blur",
},
],
},
},
{
value: "",
prop: "phone",
label: "手机",
placeHolder: "请输入您的手机号码",
tips: "",
rules: {
value: [
{
required: false,
trigger: "change",
validator: validPhone,
},
],
},
},
{
value: "",
prop: "email",
label: "邮箱",
placeHolder: "请输入您的邮箱",
tips: "",
rules: {
value: [
{
required: false,
trigger: "change",
validator: validEmail,
},
],
},
},
{
value: "",
prop: "remark",
label: "备注",
placeHolder: "请输入备注",
type: "textarea",
rules: {
value: [
{
required: false,
message: "请输入备注",
trigger: "blur",
},
],
},
},
],
},
halfFormFlag: false,
}
}
},
methods: {
},
}
utils
文件夹下的validate.js
文件
// 手机号验证2020年最新正则表达式
export const phoneReg = /^(13[0-9]|14[01456879]|15[0-3,5-9]|16[2567]|17[0-8]|18[0-9]|19[0-3,5-9])\d{8}$/
export const emailReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
export const idcardReg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
export const nameReg = /^([\u4e00-\u9fa5]{2,20}|[a-zA-Z.\s]{2,20})$/;
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* 邮箱
* @param {*} s
*/
export function isEmail(s) {
return /^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s)
}
/**
* 手机号码
* @param {*} s
*/
export function isMobile(s) {
return /^1[0-9]{10}$/.test(s)
}
/**
* 电话号码
* @param {*} s
*/
export function isPhone(s) {
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
}
/**
* URL地址
* @param {*} s
*/
export function isURL(s) {
return /^http[s]?:\/\/.*/.test(s)
}
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/**
* 验证邮箱输入
* @param {验证规则} rule
* @param {验证的值} value
* @param {回调函数} callback
*/
export function validPhoneOrEmail(rule, value, callback) {
if (rule.required && !value) {
return callback(new Error('请输入手机号/邮箱'));
}
if (value === '' || value === null) callback()
if (phoneReg.test(value) || emailReg.test(value)) {
callback()
} else {
callback(new Error('手机号/邮箱格式输入有误'))
}
}
export function validPhone(rule, value, callback) {
if (rule.required && !value) {
return callback(new Error('请输入手机号码'));
}
if (value === '' || value === null) callback()
if (phoneReg.test(value)) {
callback()
} else {
callback(new Error('手机号格式输入有误'))
}
}
export function validEmail(rule, value, callback) {
if (rule.required && !value) {
return callback(new Error('请输入邮箱'));
}
if (value === '' || value === null) callback()
if (emailReg.test(value)) {
callback()
} else {
callback(new Error('邮箱格式输入有误'))
}
}
export function validIDCard(rule, value, callback) {
if (rule.required && !value) {
return callback(new Error('请输入身份证号码'));
}
if (value === '' || value === null) callback()
if (idcardReg.test(value)) {
callback()
} else {
callback(new Error('身份证号填写有误'))
}
}
export function vaildRealName(rule, value, callback){
if (rule.required && !value) {
return callback(new Error('请输入真实姓名'));
}
if (value === '' || value === null) callback()
if (nameReg.test(value)) {
callback()
} else {
callback(new Error('真实姓名填写有误'))
}
}
/*
验证密码
*/
export function validPwd(rule, value, callback) {
if (rule.required && !value) {
return callback(new Error('请输入密码(密码需大于8位,由数字、字母和特殊符号组成)'));
}
if (value === '' || value === null) callback();
/* js正则校验密码,要求是8-16位 */
// let rules = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$/
let rules = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/;
if (rules.test(value)) {
callback()
} else {
callback(new Error('密码由8位数字、字母和特殊符号组成!'))
}
}
转载自:https://juejin.cn/post/7041096339085590535