uview-next
Version:
基于uView UI 2.0,110+高质量组件库,支持vue2和vue3,支持鸿蒙,支持多语言,搭配便捷工具助力,让开发更得心应手
203 lines (185 loc) • 6.17 kB
JavaScript
export function isValidUrl(url) {
return isOnlineUrl(url) || isDataUrl(url);
}
export function isOnlineUrl(url) {
return /(ht|f)tp(s?):\/\/([^ \\/]*\.)+[^ \\/]*(:[0-9]+)?\/?/.test(url);
}
export function isDataUrl(url) {
return /data:image\/(\w+);base64,(.*)/.test(url);
}
/**
* 深度对比两个对象是否一致
* from: https://github.com/epoberezkin/fast-deep-equal
* @param {Object} a 对象a
* @param {Object} b 对象b
* @return {Boolean} 是否相同
*/
/* eslint-disable */
export function equal(a, b) {
if (a === b) {
return true;
}
if (a && b && typeof a == 'object' && typeof b == 'object') {
var arrA = Array.isArray(a);
var arrB = Array.isArray(b);
var i;
var length;
var key;
if (arrA && arrB) {
length = a.length;
if (length != b.length) {
return false;
}
for (i = length; i-- !== 0; ) {
if (!equal(a[i], b[i])) {
return false;
}
}
return true;
}
if (arrA != arrB) {
return false;
}
var dateA = a instanceof Date;
var dateB = b instanceof Date;
if (dateA != dateB) {
return false;
}
if (dateA && dateB) {
return a.getTime() == b.getTime();
}
var regexpA = a instanceof RegExp;
var regexpB = b instanceof RegExp;
if (regexpA != regexpB) {
return false;
}
if (regexpA && regexpB) {
return a.toString() == b.toString();
}
var keys = Object.keys(a);
length = keys.length;
if (length !== Object.keys(b).length) {
return false;
}
for (i = length; i-- !== 0; ) {
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) {
return false;
}
}
for (i = length; i-- !== 0; ) {
key = keys[i];
if (!equal(a[key], b[key])) {
return false;
}
}
return true;
}
return a !== a && b !== b;
}
/**
* 简单的四则运算计算函数
* @param {String} expression 数学表达式字符串
* @return {Number} 计算结果
*/
export function calc(expression) {
try {
// 移除所有空格
expression = expression.replace(/\s/g, '');
// 简单的四则运算实现
const tokens = expression.match(/(\d+\.?\d*|\+|\-|\*|\/|\(|\))/g) || [];
const output = [];
const operators = [];
const precedence = {
'+': 1,
'-': 1,
'*': 2,
'/': 2
};
for (let token of tokens) {
if (/\d/.test(token)) {
output.push(parseFloat(token));
} else if (token === '(') {
operators.push(token);
} else if (token === ')') {
while (operators.length > 0 && operators[operators.length - 1] !== '(') {
output.push(operators.pop());
}
if (operators.length > 0 && operators[operators.length - 1] === '(') {
operators.pop();
}
} else if (['+', '-', '*', '/'].includes(token)) {
while (operators.length > 0 &&
operators[operators.length - 1] !== '(' &&
precedence[operators[operators.length - 1]] >= precedence[token]) {
output.push(operators.pop());
}
operators.push(token);
}
}
while (operators.length > 0) {
output.push(operators.pop());
}
// 计算后缀表达式
const stack = [];
for (let token of output) {
if (typeof token === 'number') {
stack.push(token);
} else {
const b = stack.pop();
const a = stack.pop();
switch (token) {
case '+': stack.push(a + b); break;
case '-': stack.push(a - b); break;
case '*': stack.push(a * b); break;
case '/': stack.push(a / b); break;
}
}
}
return stack[0] || 0;
} catch (error) {
console.error('Calc error:', error);
return 0;
}
}
/**
* 将带单位的字符串转换为像素值
* @param {String} origin 原始字符串,支持 rpx、px、% 单位和 calc() 表达式
* @param {Number} screenK 屏幕比例,默认为 0.5
* @param {Number} scale 缩放比例,默认为 1
* @param {Number} baseSize 当设置了 % 号时,设置的基准值
* @param {Object} viewRect 视图矩形信息,用于 calc() 表达式中的属性引用
* @return {Number} 转换后的像素值
*/
export function toPx(origin, screenK = 0.5, scale = 1, baseSize = 0, viewRect = {}) {
const REG = /-?[0-9]+(\.[0-9]+)?(rpx|px|%)/;
const parsePx = (origin) => {
const results = new RegExp(REG).exec(origin);
if (!origin || !results) {
return origin;
}
const unit = results[2];
const value = parseFloat(origin);
let res = 0;
if (unit === 'rpx' || unit === 'px') {
res = Math.round(value * (screenK || 0.5) * (scale || 1));
} else if (unit === '%') {
res = Math.round((value * baseSize) / 100);
}
return res;
};
const formula = /^calc\((.+)\)$/.exec(origin);
if (formula && formula[1]) {
// 进行 calc 计算
const afterOne = formula[1].replace(
/([^\s\(\+\-\*\/]+)\.(left|right|bottom|top|width|height)/g,
(word) => {
const [id, attr] = word.split('.');
return viewRect[id][attr] || 0;
}
);
const afterTwo = afterOne.replace(new RegExp(REG, 'g'), parsePx);
return calc(afterTwo);
} else {
return parsePx(origin);
}
}