开头先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位数字、字母和特殊符号组成!'))}
}
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取