JS一些功能封装
Vue项目中一些功能封装src/utils/index.js// 返回context父实例componentNameconst findUpwardComponent = (context, componentName) => {let parent = context.$parentlet name = parent.$options.namewhile (pare...
·
js一些功能封装
- 将小数转化为百分比(保留四位小数,四舍五入)
- 保留小数点后两位四舍五入
- 全局通用的数据类型判断
- 复制文字
- canvas生成水印
- 下载文件
- 判断微信浏览器
- 判断手机为安卓还是苹果
- 微信环境下禁止分享
- 判断是否PC客户端
- 获取当前时间 (2020-03-28)
- 获取当前时间("2020-08-16 11:35:06")
- js将时间转换成时间戳
- js把时间戳转为为普通日期格式
- 出生日期计算年龄 24Y5M
- 根据生日返回周岁(24)
- 获取保险生效日期、截止日期
- 数字每千位加逗号
- 手机号码中间四位隐藏星号显示
- 获取URL链接参数
- 根据参数名称获取参数值
- 链接参数赋值到一个对象上
- 设置cookie
- 获取指定cookie
- 添加vconsole调试
- findUpwardComponent () 返回父组件
- findBrotherComponents() 返回兄弟组件
- findDownwardComponent() 返回子组件
- validator() 注册表单验证
- 推荐阅读
你越是认真生活,你的生活就会越美好!
将小数转化为百分比(保留四位小数,四舍五入)
function ChangeDecimalToPercentage(data) {
let data1 = (data*100).toFixed(4)+"%"
return data1
}
ChangeDecimalToPercentage(0.9823567) // '98.2357%'
保留小数点后两位四舍五入
function NumFilter (value) {
// 截取当前数据到小数点后两位
let realVal = parseFloat(value).toFixed(2)
return realVal
}
NumFilter(0.985) // '0.98'
NumFilter(0.984) // '0.98'
全局通用的数据类型判断
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1'); // 注意正则中间有个空格
}
/* 代码验证,需要注意大小写,哪些是typeof判断,哪些是toString判断?思考下 */
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null) // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined) // "undefined" typeof 直接返回
getType() // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g) //"RegExp" toString返回
复制文字
copy(input) {
// input 复制的文字
const cssText = 'position:fixed;pointer-events:none;z-index:-9999;opacity:0;'
const copyErrorMessage = 'Failed to copy value to clipboard. Unknown type.'
let value
if (typeof input !== 'string') try {
value = JSON.stringify(input)
} catch (e) {
throw copyErrorMessage
}
else value = input
const textarea = document.createElement('textarea')
textarea.value = value
textarea.setAttribute('readonly', '')
textarea.style.cssText = cssText
document.body.appendChild(textarea)
if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
textarea.contentEditable = true
textarea.readOnly = true
const range = document.createRange()
range.selectNodeContents(textarea)
const selection = window.getSelection()
selection.removeAllRanges()
selection.addRange(range)
textarea.setSelectionRange(0, 999999)
} else textarea.select()
let success = false
try {
success = document.execCommand('copy')
} catch (err) {
console.warn(err)
}
document.body.removeChild(textarea)
return success
}
canvas生成水印
// canvas 实现 watermark
function __canvasWM({
container = document.body,
width = '380px',
height = '110px',
textAlign = 'center',
textBaseline = 'middle',
// font = "14px microsoft yahei",
font = '15px PingFangSC-Regular, PingFang SC',
fillStyle = 'rgba(184, 184, 184, 0.3)',
content = '请勿外传',
// rotate = '-32',
rotate = '0',
zIndex = 10,
} = {}) {
var args = arguments[0]
var canvas = document.createElement('canvas')
canvas.setAttribute('width', width)
canvas.setAttribute('height', height)
var ctx = canvas.getContext('2d')
ctx.textAlign = textAlign
ctx.textAlign = textAlign
ctx.textBaseline = textBaseline
ctx.font = font
ctx.fillStyle = fillStyle
ctx.rotate((Math.PI / 180) * rotate)
ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2)
var base64Url = canvas.toDataURL()
const watermarkDiv = document.createElement('div')
watermarkDiv.setAttribute(
'style',
`
position:fixed;
top:-1100px;
left:0px;
min-width:5000px;
min-height:5000px;
z-index:${zIndex};
pointer-events:none;
background-repeat:repeat;
transform: rotate(-30deg);
background-image:url('${base64Url}')`
)
container.style.position = 'relative'
container.insertBefore(watermarkDiv, container.firstChild)
watermarkDiv.setAttribute('id', 'watermark')
}
__canvasWM({
content: `陈坚泓 前端开发工程师`,
})
效果如下
下载文件
// // 下载文件
// url: 文件地址
function downloadFile (url, fileName) {
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName) // 必须带后缀 例如: test.png
link.setAttribute('target', '_blank')
document.body.appendChild(link)
link.click()
}
判断微信浏览器
getWxClient() {
// 判断微信环境
var isMobile = /Android|webOS|iPhone|iPod|BlackBerry/i.test(
navigator.userAgent
)
var ua = navigator.userAgent.toLowerCase()
var isWx = !!/micromessenger/.test(ua)
return isMobile && isWx
},
getWxClient() // 如果是返回true 不是返回false
判断手机为安卓还是苹果
// 判断手机为安卓还是苹果
isAndroidOrIos() {
let u = navigator.userAgent
let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 // android终端
let isIos = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端
if (isAndroid) {
return 'Android'
} else if (isIos) {
return 'Ios'
}
}
微信环境下禁止分享
document.addEventListener('WeixinJSBridgeReady', (onBridgeReady) => {
// 通过下面这个API隐藏右上角按钮
// eslint-disable-next-line no-undef
WeixinJSBridge.call('hideOptionMenu')
})
判断是否PC客户端
export const isPC = () => {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
isPC() // 如果是返回true 不是返回false
获取当前时间 (2020-03-28)
getTime() {
let date = new Date()
let year = date.getFullYear()
let month = date.getMonth() + 1
let strDate = date.getDate()
if (month >= 1 && month <= 9) {
month = '0' + month
}
if (strDate >= 0 && strDate <= 9) {
strDate = '0' + strDate
}
let currentdate = `${year}-${month}-${strDate}`
return currentdate
}
// getTime() // 2020-03-28
获取当前时间(“2020-08-16 11:35:06”)
fixedTime(val) {
return val < 10 ? '0' + val : val
},
getFormatDate() {
var date = new Date()
var currentDate = date.getFullYear() + '-' + this.fixedTime(date.getMonth() + 1) + '-' + this.fixedTime(date.getDate()) + ' ' + this.fixedTime(date.getHours()) + ':' + this.fixedTime(date.getMinutes()) + ':' + this.fixedTime(date.getSeconds())
return currentDate
},
js将时间转换成时间戳
js获取当前时间戳的方法
// 第一种:获取的时间戳是把毫秒改成000显示,第二种和第三种是获取了当前毫秒的时间戳。
var timestamp1 = Date.parse(new Date());
// 或者
var timestamp2 = (new Date()).valueOf();
// 或者
var timestamp3 = new Date().getTime();
js获取制定时间戳的方法
// getTime()返回数值的单位是毫秒。
var oldTime = (new Date("2015/06/23 08:00:20")).getTime()/1000;
js把时间戳转为为普通日期格式
1.Date toLocaleString方法
function getLocalTime(nS) {
return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' ');
}
getLocalTime("1608628527") // "2020/12/22 下午5:15 "
parseInt() 函数可解析一个字符串,并返回一个整数。
js中时间操作单位是毫秒。
toLocaleString() 方法可根据本地时间把 Date 对象转换为字符串,并返回结果。
replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
replace(/:\d{1,2}$/,’ ')验证替换以:开始有一位或二位数字的结束字符串,就是秒;替换为空
出生日期计算年龄 24Y5M
getAge(‘1995-07-08’) 返回24Y5M
export const getAge = (str) => {
// str = '1995-07-08'
var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
if (r == null) return false
var d = new Date(r[1], r[3] - 1, r[4])
if (d.getFullYear() == r[1] && (d.getMonth() + 1) == r[3] && d.getDate() == r[4]) {
var date = new Date()
var Y = date.getFullYear() - r[1]
var M = date.getMonth() + 1 - r[3]
var D = date.getDate()
if (parseInt(D) - parseInt(r[4]) < 0) {
M--;
if (M < 0) {
Y--
M = 11
}
}
if (M < 0) {
Y--
M = 11
}
return (Y + "Y" + M + "M")
}
}
getAge('1995-07-08') // "24Y5M"(即24周岁5个月)
根据生日返回周岁(24)
// this.getAge(1995-07-08) 返回24 (2020-03-23)
getAge(birthday) {
// birthday = 1995-07-08
var returnAge
var birthdayArr = birthday.split('-')
var birthYear = birthdayArr[0]
var birthMonth = birthdayArr[1]
var birthDay = birthdayArr[2]
var d = new Date()
var nowYear = d.getFullYear()
var nowMonth = d.getMonth() + 1
var nowDay = d.getDate()
// 这里用了 === 号 要把类型都转为数字
if (+nowYear === +birthYear) {
returnAge = 0// 同年 则为0周岁
} else {
var ageDiff = nowYear - birthYear // 年之差
if (ageDiff > 0) {
// 这里用了 === 号 要把类型都转为数字
if (+nowMonth === +birthMonth) {
var dayDiff = nowDay - birthDay// 日之差
if (dayDiff < 0) {
returnAge = ageDiff - 1
} else {
returnAge = ageDiff
}
} else {
var monthDiff = nowMonth - birthMonth// 月之差
if (monthDiff < 0) {
returnAge = ageDiff - 1
} else {
returnAge = ageDiff
}
}
} else {
returnAge = -1// 返回-1 表示出生日期输入错误 晚于今天
}
}
return returnAge// 返回周岁年龄
}
获取保险生效日期、截止日期
getTime() {
// 获取保险生效日期 截止日期
let date = new Date()
let year = +date.getFullYear()
let month = +date.getMonth() + 1 // getMonth()返回值是 0(一月) 到 11(十二月) 之间的一个整数
let strDate = +date.getDate()
let maxDate
maxDate = new Date(year, month, 0).getDate()
if (strDate + 1 > maxDate) {
month += 1
strDate = 1
if (month > 12) {
year++
month = 1
strDate = 31
}
} else {
strDate += 1
}
// 个位数+0
if (strDate > 0 && strDate <= 9) {
strDate = '0' + strDate
}
if (month > 0 && month <= 9) {
month = '0' + month
}
this.startDate = `${year}-${month}-${strDate}`
if (+strDate === 1) {
if (month === 1) {
year--
month = 12
strDate = 31
} else {
month--
strDate = new Date(year, month, 0).getDate()
}
} else {
strDate--
}
year++
// 个位数+0
if (strDate > 0 && strDate <= 9) {
strDate = '0' + +strDate
}
if (month > 0 && month <= 9) {
month = '0' + +month
}
this.endDate = `${year}-${month}-${strDate}`
}
// getTime() 2020-04-07时调用
// startDate = 2020-04-08
// endDate = 2021-04-07
数字每千位加逗号
export const commafy = (num) => {
return num && num.toString()
.replace(/\d+/, function(s){
return s.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
})
}
commafy(19999999) // "19,999,999"
手机号码中间四位隐藏星号显示
export const hideMobile = (mobile) => {
return mobile.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2")
}
hideMobile('13049997092') // "130****7092"
获取URL链接参数
根据参数名称获取参数值
// name为参数名
getUrlParam(name) {
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
var result = window.location.search.substr(1).match(reg)
return result ? decodeURIComponent(result[2]) : null
}
链接参数赋值到一个对象上
const search = window.location.href.split('?')[1].split('&')
search.forEach(item => {
this.userInfo[item.split('=')[0]] = decodeURI(item.split('=')[1])
})
设置cookie
// 设置指定cookie
// name:cookie名称 value对应cookie的值 iDay有效期天数 如7表示7天
export const setCookie = (name, value, iDay) => {
let oDate = new Date()
if (iDay) {
oDate.setDate(oDate.getDate() + iDay)
} else {
console.log('iDay:' + iDay)
oDate = iDay
}
// 域名domain=.ybj.com .表示前面可以匹配所有 77.ybj.com 或者 75.ybj.com等都可以获取到该cookie
document.cookie = `${name}=${value};expires=${oDate};domain=.ybj.com;path=/`
}
获取指定cookie
// name:cookie名称
export const getCookie = (name) => {
let arr1 = document.cookie.split('; ')
let i = 0;
for (i = 0; i < arr1.length; i++) {
var arr2 = arr1[i].split('=')
if (arr2[0] == name) {
return arr2[1]
}
}
return ''
}
添加vconsole调试
<script language="javascript" type="text/javascript" src="//images.vrm.cn/9x/2020/09/08/vconsole.min.js"></script>
<script>
var vConsole = new VConsole();
</script>
findUpwardComponent () 返回父组件
findBrotherComponents() 返回兄弟组件
findDownwardComponent() 返回子组件
validator() 注册表单验证
src/utils/index.js
// 返回context父实例componentName
import Validator from './validator'
const findUpwardComponent = (context, componentName) => {
let parent = context.$parent
let name = parent.$options.name
while (parent && (!name || !name.includes(componentName))) {
parent = parent.$parent
if (parent) name = parent.$options.name
}
return parent
}
// 返回context的兄弟实例componentName
const findBrotherComponents = (ctx, componentName, exceptMe = true) => {
const $brothers = ctx.$parent.$children.filter(item => {
return item.$options.name && item.$options.name.includes(componentName)
})
const index = $brothers.findIndex(item => item._uid === ctx._uid)
if (exceptMe && index > -1) $brothers.splice(index, 1)
return $brothers
}
// 返回context的子实例componentName
const findDownwardComponent = (context, componentName) => {
const $children = context.$children
let bean = null
if ($children.length) {
for (const child of $children) {
const name = child.$options.name
if (name && name.includes(componentName)) {
bean = child
break
} else {
bean = findDownwardComponent(child, componentName)
if (bean) break
}
}
}
return bean
}
// 注册表单验证
const validator = (rules, form) => {
try {
Object.keys(rules).forEach(key => {
const value = rules[key]
value.pattern.split('&').forEach((pattern, index) => {
const result = new Validator({
value: form[key],
pattern,
message: value.message.split('&')[index]
}).test()
if (!result.valid) {
throw new Error(result.message)
}
})
})
return true
} catch (e) {
toast.info(e.message)
}
}
export {
findUpwardComponent,
findBrotherComponents,
findDownwardComponent,
validator
}
src/utils/validator.js
/* eslint-disable */
export default class Validator {
constructor(model) {
this.value = model.value
this.pattern = model.pattern
this.message = model.message || '验证失败'
this.valid = true
this.init()
}
init() {
switch (this.pattern) {
case 'mobile':
this.pattern = /^0?((13[0-9])|(14[0-9])|(15([0-3]|[5-9]))|(166)|(18[0-9])|(17[0-9])|(19[8-9]))[0-9]{8}$/
break
case 'idcard':
this.pattern = /^[1-9][0-9]{5}(19|20)[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9X]$/
break
case 'name':
this.pattern = /^[A-Za-z_\-\u4e00-\u9fa5]{2,20}$/
break
case 'email':
this.pattern = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
break
case 'birthday':
this.pattern = /^[1-9]\d{3}([-|\/|\.])?((0\d)|([1-9])|(1[0-2]))\1(([0|1|2]\d)|([1-9])|3[0-1])$/
break
case 'required':
this.pattern = cb => {
this.value ? cb() : cb(this.message)
}
break
default:
break
}
}
callback(message) {
this.valid = !message
this.message = message
}
test() {
if (typeof this.pattern === 'function') {
this.pattern(this.callback.bind(this))
} else {
this.valid = this.value ? this.pattern.test(this.value) : true
}
return { valid: this.valid, message: this.valid ? undefined : this.message }
}
}
调用
import {findUpwardComponent, findBrotherComponents, findDownwardComponent} from '@/utils/index'
console.log(findDownwardComponent(this, 'layer_0003'))
也可以这样调用
import * as utils from '@/utils/index'
console.log(utils.findDownwardComponent(this, 'layer'))
// utils.findDownwardComponent(this, 'layer') 相当于 当先实例的子实例layer 里面的this
// 也相当于通过$refs.layer获取到的一样
// 表单验证规则
let fields = [
{
label: '姓名',
prop: 'name',
other: { placeholder: '', sex: { visible: 1, type: 0, text: '男/女' } }
},
{
label: '生日',
prop: 'birthday',
other: { placeholder: '', maxAge: 50, minAge: 20, defaultAge: 30 }
},
{
label: '手机',
prop: 'mobile',
other: {
placeholder: '',
captcha: { type: 0, activityId: '', callback: { type: 'none' } }
}
},
{
label: '协议',
prop: 'agreecCall',
other: {
autoCheck: 1,
autoCheckAfterFinish: 1,
type: 0,
company: '',
product: '',
text:
'我已知晓并许可太平保险专线致电我沟通赠险领取事宜及<b>《服务协议》</b>'
}
}
]
const rules = fields.reduce((rules, field) => {
if (field.prop === 'name') {
rules.name = { pattern: 'required&name', message: `请输入您的${field.label}&姓名格式错误` }
field.other.sex.visible === 1 && (rules.sex = { 'pattern': 'required', 'message': '请选择性别' })
} else if (field.prop === 'birthday') {
rules.birthday = { pattern: 'required&birthday', message: `请选择您的${field.label}&生日格式错误` }
} else if (field.prop === 'mobile') {
rules.mobile = { pattern: 'required&mobile', message: `请输入您的${field.label}&手机号码格式错误` }
field.other.captcha.type === 1 && (rules.mobileCode = { 'pattern': 'required', 'message': '请输入验证码' })
} else if (field.prop === 'agreecCall') {
rules.agreecCall = { pattern: 'required', message: '请勾选服务协议' }
} else if (field.prop === 'email') {
rules.email = { pattern: 'required&email', message: `请输入您的${field.label}&邮箱格式错误` }
} else if (field.other.type === 'input') {
rules[field.prop] = { pattern: 'required', message: `请输入${field.label}` }
} else if (['select', 'radio'].includes(field.other.type)) {
rules[field.prop] = { pattern: 'required', message: `请选择${field.label}` }
}
return rules
},{})
const userInfo = {
agreecCall: 1
birthday: "1989-10-11"
id: "id"
mobile: "130****7092"
mobileCode: "943499"
name: "测试"
sex: 男
}
utils.validator(rules, userInfo) // 返回布尔值
rulesObject
推荐阅读
Vue源码学习完整目录
连点成线 - 前端成长之路
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强
更多推荐
已为社区贡献22条内容
所有评论(0)