替换字段名

  1. const replaceKeys = (obj, rules = {}) => {
  2. const keys = Object.keys(rules);
  3. return Object.keys(obj).reduce((acc, key) => {
  4. acc[keys.includes(key) ? rules[key] : key] = obj[key];
  5. return acc;
  6. }, {});
  7. };

区间随机数

  1. export function random(a: number, b: number): number {
  2. return a + (b - a) * Math.random();
  3. }
  1. export function firstOf<T>(array: T[]) {
  2. return array[0];
  3. }
  4. export function lastOf<T>(array: T[]) {
  5. return array[array.length - 1];
  6. }
  7. export function isFlatArray<T>(array: (T | T[])[]): array is T[] {
  8. return !array.some(Array.isArray);
  9. }
  10. export function unique<T>(array: T[]): T[] {
  11. return Array.from(new Set(array));
  12. }

统计出现次数

  1. export const dateCountBy = () => {
  2. const dates = {}
  3. data.forEach(item => {
  4. if (!dates[item.date]) {
  5. dates[item.date] = { date: item.date, value: 1 }
  6. } else {
  7. dates[item.date] = { date: item.date, value: dates[item.date].value + 1 }
  8. }
  9. })
  10. return dates
  11. }

格式转换 @example [[1, 2, 3], [‘a’, ‘b’, ‘c’]] => [[1, ‘a’], [2, ‘b’], [3, ‘c’]]

  1. /**
  2. * @example [[1, 2, 3], ['a', 'b', 'c']] => [[1, 'a'], [2, 'b'], [3, 'c']]
  3. */
  4. export function transpose<T>(matrix: T[][]): T[][] {
  5. const row = matrix.length;
  6. const col = matrix[0].length;
  7. // Note: new Array(col).fill(new Array(row)) is not ok!!!
  8. // Because in this case it will fill new Array(col) with the same array: new Array(row).
  9. const transposed = new Array(col).fill(0).map(() => new Array(row));
  10. for (let i = 0; i < col; i++) {
  11. for (let j = 0; j < row; j++) {
  12. transposed[i][j] = matrix[j][i];
  13. }
  14. }
  15. return transposed;
  16. }

通过url截取视频首帧

  1. export const getVideoFirstBase64 = (url) => {
  2. return new Promise(function (resolve, reject) {
  3. let dataURL = '';
  4. let video = document.createElement("video");
  5. video.setAttribute('autoplay', true);
  6. video.setAttribute('muted', true);
  7. video.setAttribute('preload', true);
  8. video.setAttribute('useCORS', true);
  9. video.setAttribute('crossOrigin', 'Anonymous'); //处理跨域
  10. video.setAttribute('src', url);
  11. video.addEventListener('loadeddata', function () {
  12. video.setAttribute('muted', true);
  13. video.pause();
  14. let canvas = document.createElement("canvas");
  15. let width = video.videoWidth;
  16. let height = video.videoHeight;
  17. canvas.width = width;
  18. canvas.height = height;
  19. canvas.getContext("2d").drawImage(video, 0, 0, width, height);
  20. dataURL = canvas.toDataURL('image/png');
  21. resolve(dataURL);
  22. });
  23. video.onerror = function () {
  24. video.onerror = null;
  25. reject()
  26. }
  27. })
  28. }

base64tofile 上传

  1. export const dataURLtoFile = (base64, filename) => {
  2. var arr = base64.split(','), mime = arr[0].match(/:(.*?);/)[1],
  3. bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  4. while(n--){
  5. u8arr[n] = bstr.charCodeAt(n);
  6. }
  7. // TODO filename记得加后缀
  8. return new File([u8arr], filename, {type:mime});
  9. }

无参数调用IOS 和 Android 方法

  1. export function isAndroid(): boolean {
  2. return /android/.test(navigator.userAgent.toLowerCase());
  3. }
  4. export function isIOS(): boolean {
  5. return /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
  6. }
  7. /// not params
  8. /// options: {
  9. /// ios: { func: '', data: null },
  10. /// android: { func: '', data: null }
  11. // }
  12. const utils = (options) => {
  13. const { ios, android } = options
  14. if(isIOS()){
  15. window.webkit.messageHandlers[ios.func].postMessage(ios.data)
  16. }
  17. if(isAndroid){
  18. window.android[android.func](android.data)
  19. }
  20. }
  1. // 判断Android系统的正则
  2. ANDROID_REGEXP = /(Android)\s+([\d.]+)/i
  3. // 判断iOS系统的正则
  4. IOS_REGEXP = /\(i[^;]+;( U;)? cpu.+mac os x/i
  5. // 判断移动端正则
  6. MOBILE_REGEXP = /AppleWebKit.*Mobile.*/i
  7. // 判断苹果产品系列正则
  8. APPLE_REGEXP = /(iPhone|iPad|iPod|iOS|Mac OS X)/i
  9. // 判断iPad正则
  10. IPAD_REGEXP = /(iPad).*OS\s([\d_]+)/i
  11. // 判断iPhone正则
  12. IPHONE_REGEXP = /(iPhone\sOS)\s([\d_]+)/i
  13. // 判断QQ APP正则
  14. QQ_REGEXP = /QQ\/([\d.]+)/i
  15. // 判断微信正则
  16. WEI_XIN_REGEXP = /micromessenger/i
  17. // 判断企业微信正则
  18. WEI_XIN_WORK_REGEXP = /wxwork\/.* MicroMessenger/i
  19. // 判断微博正则
  20. WEI_BO_REGEXP = /WeiBo/i
  21. // 判断支付宝正则
  22. ALIPAY_REGEXP = /AlipayClient/i
  23. export const isServer: boolean = Vue.prototype.$isServer; // 是否是服务端渲染
  24. export function isAndroid(): boolean {
  25. /* istanbul ignore next */
  26. return isServer ? false : /android/.test(navigator.userAgent.toLowerCase());
  27. }
  28. export function isIOS(): boolean {
  29. /* istanbul ignore next */
  30. return isServer ? false : /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
  31. }
  1. // 判断两个对象是否相等
  2. export const isObjectEqual = (a, b) => {
  3. var aProps = Object.getOwnPropertyNames(a);
  4. var bProps = Object.getOwnPropertyNames(b);
  5. if (aProps.length !== bProps.length) {
  6. return false;
  7. }
  8. for (var i = 0; i < aProps.length; i++) {
  9. var propName = aProps[i];
  10. if (a[propName] !== b[propName]) {
  11. return false;
  12. }
  13. }
  14. return true;
  15. }

reset-scroll

  1. /** scroll.js */
  2. type ScrollElement = HTMLElement | Window;
  3. // get nearest scroll element
  4. // http://w3help.org/zh-cn/causes/SD9013
  5. // http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
  6. const overflowScrollReg = /scroll|auto/i;
  7. export function getScrollEventTarget(element: HTMLElement, rootParent: ScrollElement = window) {
  8. let node = element;
  9. while (
  10. node &&
  11. node.tagName !== 'HTML' &&
  12. node.nodeType === 1 &&
  13. node !== rootParent
  14. ) {
  15. const { overflowY } = window.getComputedStyle(node);
  16. if (overflowScrollReg.test(<string>overflowY)) {
  17. if (node.tagName !== 'BODY') {
  18. return node;
  19. }
  20. // see: https://github.com/youzan/vant/issues/3823
  21. const { overflowY: htmlOverflowY } = window.getComputedStyle(<Element>node.parentNode);
  22. if (overflowScrollReg.test(<string>htmlOverflowY)) {
  23. return node;
  24. }
  25. }
  26. node = <HTMLElement>node.parentNode;
  27. }
  28. return rootParent;
  29. }
  30. export function getScrollTop(element: ScrollElement): number {
  31. return 'scrollTop' in element ? element.scrollTop : element.pageYOffset;
  32. }
  33. export function setScrollTop(element: ScrollElement, value: number) {
  34. 'scrollTop' in element ? (element.scrollTop = value) : element.scrollTo(element.scrollX, value);
  35. }
  36. export function getRootScrollTop(): number {
  37. return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
  38. }
  39. export function setRootScrollTop(value: number) {
  40. setScrollTop(window, value);
  41. setScrollTop(document.body, value);
  42. }
  43. // get distance from element top to page top
  44. export function getElementTop(element: ScrollElement) {
  45. return (
  46. (element === window ? 0 : (<HTMLElement>element).getBoundingClientRect().top) +
  47. getRootScrollTop()
  48. );
  49. }
  50. export function getVisibleHeight(element: ScrollElement) {
  51. return element === window
  52. ? element.innerHeight
  53. : (<HTMLElement>element).getBoundingClientRect().height;
  54. }
  55. // Use
  56. /**
  57. * Hack for iOS12 page scroll
  58. * https://developers.weixin.qq.com/community/develop/doc/00044ae90742f8c82fb78fcae56800
  59. */
  60. import { isIOS as checkIsIOS } from '../validate/system';
  61. import { getRootScrollTop, setRootScrollTop } from './scroll';
  62. const isIOS = checkIsIOS();
  63. /* istanbul ignore next */
  64. export function resetScroll() {
  65. if (isIOS) {
  66. setRootScrollTop(getRootScrollTop());
  67. }
  68. }

截图

  1. /* h5截图按钮, 截图成功回调 */
  2. dom.on('click', function (data) {
  3. var pictureData = data.paramData.base64
  4. var downloadElement = document.createElement('a')
  5. downloadElement.setAttribute('href', pictureData)
  6. var fileName = Date.now() + '.png'
  7. downloadElement.setAttribute('download', fileName)
  8. downloadElement.click()
  9. pictureData = null
  10. })

对象成员分组2

  1. let group = [
  2. {spid:1,gysid:'a',spname:'商品1',price:2},
  3. {spid:2,gysid:'a',spname:'商品2',price:5},
  4. {spid:3,gysid:'b',spname:'商品3',price:3},
  5. {spid:4,gysid:'c',spname:'商品4',price:7},
  6. {spid:5,gysid:'c',spname:'商品5',price:6}
  7. ]
  8. function groupBy(originArr, property){
  9. return originArr.reduce((accumulator, currentValue)=>{
  10. let key = currentValue[property]
  11. if(!accumulator[key]){
  12. accumulator[key] = []
  13. }
  14. accumulator[key].push(currentValue)
  15. return accumulator
  16. },{})
  17. }
  18. console.log(groupBy(group, 'gysid'))
  1. const camelizeRE = /-(\w)/g;
  2. // 驼峰
  3. export function camelize(str: string): string {
  4. return str.replace(camelizeRE, (_, c) => c.toUpperCase());
  5. }
  6. // 补零
  7. export function padZero(num: number | string, targetLength = 2): string {
  8. let str = num + '';
  9. while (str.length < targetLength) {
  10. str = '0' + str;
  11. }
  12. return str;
  13. }
  1. export function isNumber(value: string): boolean {
  2. return /^\d+(\.\d+)?$/.test(value);
  3. }
  4. export function isNaN(value: any): boolean {
  5. if (Number.isNaN) {
  6. return Number.isNaN(value);
  7. }
  8. // eslint-disable-next-line no-self-compare
  9. return value !== value;
  10. }
  1. // 事件委托
  2. // elem.addEventListener('click',function(e){
  3. // var event=e||window.event,
  4. // target = event.target||event.srcElement;
  5. // console.log(target.innerText);
  6. // },false);
  7. // 回文字符串 -- 低性能
  8. function run(input) {
  9. if (typeof input !== 'string') return false
  10. return (
  11. input
  12. .split('')
  13. .reverse()
  14. .join('') === input
  15. )
  16. }
  17. // 回文字符串 -- 高性能
  18. const palindrome = str => {
  19. // str = "abaaba"
  20. if (typeof str !== 'string') return false
  21. let len = str.length
  22. for (let i = 0; i < len / 2; ++i) {
  23. if (str[i] !== str[len - i - 1]) {
  24. return false
  25. }
  26. }
  27. return true
  28. }
  29. /**
  30. * @param {string} str
  31. * @returns {Boolean}
  32. */
  33. export function isString(str) {
  34. if (typeof str === 'string' || str instanceof String) {
  35. return true
  36. }
  37. return false
  38. }
  39. /**
  40. * Empty is true
  41. * @param {(Object|string|number)}
  42. * @returns {Boolean}
  43. */
  44. export function isEmpty(value) {
  45. return (
  46. value === undefined ||
  47. value === null ||
  48. (typeof value === 'object' && Object.keys(value).length === 0) ||
  49. (typeof value === 'string' && value.trim().length === 0)
  50. )
  51. }
  52. /**
  53. * @param {Array} arg
  54. * @returns {Boolean}
  55. */
  56. export function isArray(arg) {
  57. if (typeof Array.isArray === 'undefined') {
  58. return Object.prototype.toString.call(arg) === '[object Array]'
  59. }
  60. return Array.isArray(arg)
  61. }
  62. /**
  63. * @param {string} path
  64. * @returns {Boolean}
  65. */
  66. export function isExternal(path) {
  67. return /^(https?:|mailto:|tel:)/.test(path)
  68. }
  69. export function formatDate(date, fmt) {
  70. if (/(y+)/.test(fmt)) {
  71. fmt = fmt.replace(
  72. RegExp.$1,
  73. (date.getFullYear() + '').substr(4 - RegExp.$1.length)
  74. )
  75. }
  76. let o = {
  77. 'M+': date.getMonth() + 1,
  78. 'd+': date.getDate(),
  79. 'h+': date.getHours(),
  80. 'm+': date.getMinutes(),
  81. 's+': date.getSeconds()
  82. }
  83. for (let k in o) {
  84. if (new RegExp(`(${k})`).test(fmt)) {
  85. let str = o[k] + ''
  86. fmt = fmt.replace(
  87. RegExp.$1,
  88. RegExp.$1.length === 1 ? str : padLeftZero(str)
  89. )
  90. }
  91. }
  92. return fmt
  93. }
  94. /**
  95. * Parse the time to string
  96. * @param {(Object|string|number)} time
  97. * @param {string} cFormat
  98. * @returns {string}
  99. */
  100. export function parseTime(time, cFormat) {
  101. if (arguments.length === 0) {
  102. return null
  103. }
  104. const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  105. let date
  106. if (typeof time === 'object') {
  107. date = time
  108. } else {
  109. if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
  110. time = parseInt(time)
  111. }
  112. if (typeof time === 'number' && time.toString().length === 10) {
  113. time = time * 1000
  114. }
  115. date = new Date(time)
  116. }
  117. const formatObj = {
  118. y: date.getFullYear(),
  119. m: date.getMonth() + 1,
  120. d: date.getDate(),
  121. h: date.getHours(),
  122. i: date.getMinutes(),
  123. s: date.getSeconds(),
  124. a: date.getDay()
  125. }
  126. const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
  127. let value = formatObj[key]
  128. // Note: getDay() returns 0 on Sunday
  129. if (key === 'a') {
  130. return ['日', '一', '二', '三', '四', '五', '六'][value]
  131. }
  132. if (result.length > 0 && value < 10) {
  133. value = '0' + value
  134. }
  135. return value || 0
  136. })
  137. return time_str
  138. }
  139. /**
  140. * @param {number} time
  141. * @param {string} option
  142. * @returns {string}
  143. */
  144. export function formatTime(time, option) {
  145. if (('' + time).length === 10) {
  146. time = parseInt(time) * 1000
  147. } else {
  148. time = +time
  149. }
  150. const d = new Date(time)
  151. const now = Date.now()
  152. const diff = (now - d) / 1000
  153. if (diff < 30) {
  154. return '刚刚'
  155. } else if (diff < 3600) {
  156. // less 1 hour
  157. return Math.ceil(diff / 60) + '分钟前'
  158. } else if (diff < 3600 * 24) {
  159. return Math.ceil(diff / 3600) + '小时前'
  160. } else if (diff < 3600 * 24 * 2) {
  161. return '1天前'
  162. }
  163. if (option) {
  164. return parseTime(time, option)
  165. } else {
  166. return (
  167. d.getMonth() +
  168. 1 +
  169. '月' +
  170. d.getDate() +
  171. '日' +
  172. d.getHours() +
  173. '时' +
  174. d.getMinutes() +
  175. '分'
  176. )
  177. }
  178. }
  179. /**
  180. * @param {string} url
  181. * @returns {Object}
  182. */
  183. export function getQueryObject(url) {
  184. url = url == null ? window.location.href : url
  185. const search = url.substring(url.lastIndexOf('?') + 1)
  186. const obj = {}
  187. const reg = /([^?&=]+)=([^?&=]*)/g
  188. search.replace(reg, (rs, $1, $2) => {
  189. const name = decodeURIComponent($1)
  190. let val = decodeURIComponent($2)
  191. val = String(val)
  192. obj[name] = val
  193. return rs
  194. })
  195. return obj
  196. }
  197. /**
  198. * @param {string} input value
  199. * @returns {number} output value
  200. */
  201. export function byteLength(str) {
  202. // returns the byte length of an utf8 string
  203. let s = str.length
  204. for (var i = str.length - 1; i >= 0; i--) {
  205. const code = str.charCodeAt(i)
  206. if (code > 0x7f && code <= 0x7ff) s++
  207. else if (code > 0x7ff && code <= 0xffff) s += 2
  208. if (code >= 0xdc00 && code <= 0xdfff) i--
  209. }
  210. return s
  211. }
  212. /**
  213. * @param {Array} actual
  214. * @returns {Array}
  215. */
  216. export function cleanArray(actual) {
  217. const newArray = []
  218. for (let i = 0; i < actual.length; i++) {
  219. if (actual[i]) {
  220. newArray.push(actual[i])
  221. }
  222. }
  223. return newArray
  224. }
  225. /**
  226. * @param {Object} json
  227. * @returns {Array}
  228. */
  229. export function param(json) {
  230. if (!json) return ''
  231. return cleanArray(
  232. Object.keys(json).map(key => {
  233. if (json[key] === undefined) return ''
  234. return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
  235. })
  236. ).join('&')
  237. }
  238. /**
  239. * @param {string} url
  240. * @returns {Object}
  241. */
  242. export function param2Obj(url) {
  243. const search = url.split('?')[1]
  244. if (!search) {
  245. return {}
  246. }
  247. return JSON.parse(
  248. '{"' +
  249. decodeURIComponent(search)
  250. .replace(/"/g, '\\"')
  251. .replace(/&/g, '","')
  252. .replace(/=/g, '":"')
  253. .replace(/\+/g, ' ') +
  254. '"}'
  255. )
  256. }
  257. /**
  258. * @param {string} val
  259. * @returns {string}
  260. */
  261. export function html2Text(val) {
  262. const div = document.createElement('div')
  263. div.innerHTML = val
  264. return div.textContent || div.innerText
  265. }
  266. /**
  267. * Merges two objects, giving the last one precedence
  268. * @param {Object} target
  269. * @param {(Object|Array)} source
  270. * @returns {Object}
  271. */
  272. export function objectMerge(target, source) {
  273. if (typeof target !== 'object') {
  274. target = {}
  275. }
  276. if (Array.isArray(source)) {
  277. return source.slice()
  278. }
  279. Object.keys(source).forEach(property => {
  280. const sourceProperty = source[property]
  281. if (typeof sourceProperty === 'object') {
  282. target[property] = objectMerge(target[property], sourceProperty)
  283. } else {
  284. target[property] = sourceProperty
  285. }
  286. })
  287. return target
  288. }
  289. /**
  290. * @param {HTMLElement} element
  291. * @param {string} className
  292. */
  293. export function toggleClass(element, className) {
  294. if (!element || !className) {
  295. return
  296. }
  297. let classString = element.className
  298. const nameIndex = classString.indexOf(className)
  299. if (nameIndex === -1) {
  300. classString += '' + className
  301. } else {
  302. classString =
  303. classString.substr(0, nameIndex) +
  304. classString.substr(nameIndex + className.length)
  305. }
  306. element.className = classString
  307. }
  308. /**
  309. * @param {string} type
  310. * @returns {Date}
  311. */
  312. export function getTime(type) {
  313. if (type === 'start') {
  314. return new Date().getTime() - 3600 * 1000 * 24 * 90
  315. } else {
  316. return new Date(new Date().toDateString())
  317. }
  318. }
  319. /**
  320. * @param {Function} func
  321. * @param {number} wait
  322. * @param {boolean} immediate
  323. * @return {*}
  324. */
  325. export function debounce(func, wait, immediate) {
  326. let timeout, args, context, timestamp, result
  327. const later = function() {
  328. const last = +new Date() - timestamp
  329. if (last < wait && last > 0) {
  330. timeout = setTimeout(later, wait - last)
  331. } else {
  332. timeout = null
  333. // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
  334. if (!immediate) {
  335. result = func.apply(context, args)
  336. if (!timeout) context = args = null
  337. }
  338. }
  339. }
  340. return function(...args) {
  341. context = this
  342. timestamp = +new Date()
  343. const callNow = immediate && !timeout
  344. if (!timeout) timeout = setTimeout(later, wait)
  345. if (callNow) {
  346. result = func.apply(context, args)
  347. context = args = null
  348. }
  349. return result
  350. }
  351. }
  352. /**
  353. * This is just a simple version of deep copy
  354. * Has a lot of edge cases bug
  355. * If you want to use a perfect deep copy, use lodash's _.cloneDeep
  356. * @param {Object} source
  357. * @returns {Object}
  358. */
  359. export function deepClone(source) {
  360. if (!source && typeof source !== 'object') {
  361. throw new Error('error arguments', 'deepClone')
  362. }
  363. const targetObj = source.constructor === Array ? [] : {}
  364. Object.keys(source).forEach(keys => {
  365. if (source[keys] && typeof source[keys] === 'object') {
  366. targetObj[keys] = deepClone(source[keys])
  367. } else {
  368. targetObj[keys] = source[keys]
  369. }
  370. })
  371. return targetObj
  372. }
  373. /**
  374. * @param {Array} arr
  375. * @returns {Array}
  376. */
  377. export function uniqueArr(arr) {
  378. return Array.from(new Set(arr))
  379. }
  380. /**
  381. * @returns {string}
  382. */
  383. export function createUniqueString() {
  384. const timestamp = +new Date() + ''
  385. const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  386. return (+(randomNum + timestamp)).toString(32)
  387. }
  388. /**
  389. * Check if an element has a class
  390. * @param {HTMLElement} elm
  391. * @param {string} cls
  392. * @returns {boolean}
  393. */
  394. export function hasClass(ele, cls) {
  395. return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
  396. }
  397. /**
  398. * Add class to element
  399. * @param {HTMLElement} elm
  400. * @param {string} cls
  401. */
  402. export function addClass(ele, cls) {
  403. if (!hasClass(ele, cls)) ele.className += ' ' + cls
  404. }
  405. /**
  406. * Remove class from element
  407. * @param {HTMLElement} elm
  408. * @param {string} cls
  409. */
  410. export function removeClass(ele, cls) {
  411. if (hasClass(ele, cls)) {
  412. const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
  413. ele.className = ele.className.replace(reg, ' ')
  414. }
  415. }
  416. // 补0
  417. function padLeftZero(str) {
  418. // 例如 传入9 则为009 substr(1) 返回 09
  419. return ('00' + str).substr(str.length)
  420. }
  421. // 兼容低版本浏览器 NodeList的for)
  422. if (window.NodeList && !NodeList.prototype.forEach) {
  423. NodeList.prototype.forEach = function(callback, thisArg) {
  424. thisArg = thisArg || window
  425. for (let i = 0; i < this.length; i++) {
  426. callback.call(thisArg, this[i], i, this)
  427. }
  428. }
  429. }
  430. /*
  431. 查看对象属性配置*/
  432. //列出对象的属性.
  433. function listProperties(obj) {
  434. var newLine = '<br />'
  435. var names = Object.getOwnPropertyNames(obj)
  436. for (var i = 0; i < names.length; i++) {
  437. var prop = names[i]
  438. document.write(prop + newLine)
  439. // 列出对象的属性配置(descriptor)动用getOwnPropertyDescriptor函数。
  440. var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
  441. for (var attr in descriptor) {
  442. document.write('...' + attr + ': ' + descriptor[attr])
  443. document.write(newLine)
  444. }
  445. document.write(newLine)
  446. }
  447. }
  448. /*兼容*/
  449. window.requestAnimationFrame = (function() {
  450. return (
  451. window.requestAnimationFrame ||
  452. window.webketRequestAnimationFrame ||
  453. window.mozRequestAnimationFrame ||
  454. function(callback) {
  455. window.setTimeout(callback, 1000 / 60)
  456. }
  457. )
  458. })()
  459. window.cancelAnimationFrame = (function() {
  460. return (
  461. window.cancelAnimationFrame ||
  462. window.webketCancelAnimationFrame ||
  463. window.mozCancelAnimationFrame ||
  464. function(timerId) {
  465. window.clearTimeout(timerId)
  466. }
  467. )
  468. })()
  469. /*extend inherit 原型圣杯模式 思想:function f(){}
  470. f.prototype=parent.prototype;
  471. son.prototype=new f()*/
  472. function extend(Sub, Sup) {
  473. //Sub表示子类,Sup表示超类
  474. // 首先定义一个空函数
  475. var F = function() {}
  476. // 设置空函数的原型为超类的原型
  477. F.prototype = Sup.prototype
  478. // 实例化空函数,并把超类原型引用传递给子类
  479. Sub.prototype = new F()
  480. // 重置子类原型的构造器为子类自身
  481. Sub.prototype.constructor = Sub
  482. // 在子类中保存超类的原型,避免子类与超类耦合
  483. Sub.sup = Sup.prototype
  484. if (Sup.prototype.constructor === Object.prototype.constructor) {
  485. // 检测超类原型的构造器是否为原型自身
  486. Sup.prototype.constructor = Sup
  487. }
  488. }
  489. var inherit = (function() {
  490. var F = function() {}
  491. return function(target, origin) {
  492. F.prototype = origin.prototype
  493. target.prototype = new F()
  494. target.prototype.construct = target // 把target原型的构造函数修复为target 原本为new f-->orgin.__proto__
  495. target.prototype.uber = origin.prototype // 找到Target的真正原型
  496. }
  497. })()
  498. /* 接上更好的写法 */
  499. var EventUtil = {
  500. getEvent: function(event) {
  501. return event ? event : window.event
  502. },
  503. getTarget: function(event) {
  504. return event.target || event.srcElement
  505. },
  506. /* 绑定事件 */
  507. addEvent: function(elem, eType, fn) {
  508. if (elem.addEventListener) {
  509. elem.addEventListener(eType, fn, false)
  510. } else if (elem.attachEvent) {
  511. elem.attachEvent('on' + eType, function() {
  512. fn.call(elem)
  513. })
  514. } else {
  515. elem['on' + eType] = fn
  516. }
  517. },
  518. /*阻止默认事件 */
  519. cancelHanlder: function(event) {
  520. if (event.prevenDefault) {
  521. event.prevenDefault()
  522. } else {
  523. event.returnValue = false
  524. }
  525. },
  526. /*阻止冒泡事件 bubble*/
  527. stopBubble: function(event) {
  528. if (event.stopPropagation) {
  529. event.stopPropagation()
  530. } else {
  531. event.cancelBubble = true
  532. /* IE */
  533. }
  534. },
  535. // 解绑事件
  536. removeEvent: function(elem, type, handler) {
  537. if (elem.removeEventListener) {
  538. elem.removeEventListener(type, handler, false)
  539. } else if (elem.detachEvent) {
  540. elem.detachEvent('on' + type, handler)
  541. } else {
  542. elem['on' + type] = false
  543. }
  544. }
  545. }
  546. /* ---end--- */
  547. /* 兼容 滚动条滚动距离 */
  548. function getScrolloffset() {
  549. if (window.pageXOffset) {
  550. return {
  551. X: window.pageXOffset,
  552. Y: window.pageYOffset
  553. }
  554. } else {
  555. return {
  556. X: document.body.scrollLeft + document.documentElement.scrollLeft,
  557. Y: document.body.scrollTop + document.documentElement.scrollTop
  558. }
  559. }
  560. }
  561. /* 兼容 滚动条滚动距离 结束*/
  562. /* 兼容 获取视口尺寸(不加边框) */
  563. function getViewportOffset() {
  564. if (window.innerWidth) {
  565. return {
  566. W: window.innerWidth,
  567. H: window.innerHeight
  568. }
  569. } else {
  570. /* 怪异模式 混杂模式 去掉<docType html> 怪异模式向下兼容*/
  571. if (document.compatMode === 'backcompat') {
  572. return {
  573. W: document.body.clientWidth,
  574. H: document.body.clientHeight
  575. }
  576. } else {
  577. return {
  578. W: document.documentElement.clientWidth,
  579. H: document.documentElement.clientHeight
  580. }
  581. }
  582. }
  583. }
  584. /* 兼容 获取视口尺寸 结束 */
  585. /* 模仿系统的insertBefore()写出insetafter() insetBefore(A,B)即insert A,Befor B
  586. 思想:在谁后面插入即在下一个兄弟节点前面插入,最后一个节点直接oppdenChild() */
  587. Element.prototype.insertAfter = function(targetNode, afterNode) {
  588. var beforNode = afterNode.nextElementSibling
  589. if (beforNode == null) {
  590. this.appendChild(targetNode)
  591. } else {
  592. this.insertBefore(targetNode, beforNode)
  593. }
  594. }
  595. /* insertAfter结束*/
  596. /* 兄弟节点sibling 兼容 */
  597. function retSibling(ele, no) {
  598. while (ele && no) {
  599. // no>0时下一个兄弟
  600. if (no > 0) {
  601. if (0 && ele.nextElementSibling) {
  602. ele.nextElementSibling
  603. } else {
  604. for (ele.nextSibling; ele && ele.nodeType === 1; ele.nextSibling);
  605. }
  606. }
  607. // no<0时上一个兄弟
  608. else {
  609. if (0 && ele.previousSibling) {
  610. ele.previousSibling
  611. } else {
  612. for (
  613. ele.previousSibling;
  614. ele && ele.nodeType === 1;
  615. ele.previousSibling
  616. );
  617. }
  618. }
  619. }
  620. return ele
  621. }
  622. /* 兄弟节点sibling 兼容结束 */
  623. /* 封装返回元素ele的第num层的父级元素节点 */
  624. function retParent(element, num) {
  625. while (element && num) {
  626. element = element.parentElement
  627. num--
  628. }
  629. return element
  630. }
  631. /* 第num层的父级元素节点 结束 */
  632. /* 不用children实现元素节点遍历 */
  633. function retElementChild(node) {
  634. var arr = [],
  635. children = node.ChildNodes(),
  636. len = children.length
  637. for (var i = 0; i < len; i++) {
  638. if (children[i].nodeType === 1) {
  639. arr.push(children[i])
  640. }
  641. }
  642. return arr
  643. }
  644. /* 不用children实现元素节点遍历结束 */
  645. /* 获取样式兼容 */
  646. function getStyle(ele, prop) {
  647. if (ele.currentStyle) {
  648. return ele.currentStyle[prop]
  649. } else {
  650. return getComputedStyle(ele, false)[prop]
  651. }
  652. }
  653. /* getComputedStyle(ele,null);第二个参数可以获取为元素
  654. 获取样式兼容结束 */
  655. /* 封装重用class */
  656. function getByClass(ele, sClass) {
  657. var oEle = ele.getElementsByTagName('*'), //获取所有的\
  658. oResult = [],
  659. len = oEle.length
  660. for (var i = 0; i < len; i++) {
  661. if (oEle[i].className == sClass) {
  662. /* return oEle[i]; 这样一次只能选出一个class (class可以重名)*/
  663. oResult.push(oEle[i])
  664. }
  665. }
  666. return oResult //返回多个class
  667. }
  668. /* 封装重用class结束 */
  669. //拖拽函数 drag.init(ele)
  670. var drag = {
  671. init: function(dom) {
  672. this.dom = dom
  673. this.bandEvent()
  674. },
  675. bandEvent: function() {
  676. this.dom.onmousedown = this.mouseDown.bind(this)
  677. },
  678. mouseDown: function(e) {
  679. var event = e || window.event
  680. document.onmousemove = this.mouseMove.bind(this)
  681. document.onmouseup = this.mouseUp.bind(this)
  682. this.disX = e.clientX - this.dom.offsetLeft
  683. this.disY = e.clientY - this.dom.offsetTop
  684. },
  685. mouseMove: function(e) {
  686. var event = e || window.event
  687. this.dom.style.top = e.clientY - this.disY + 'px'
  688. this.dom.style.left = e.clientX - this.disX + 'px'
  689. },
  690. mouseUp: function() {
  691. document.onmousemove = null
  692. document.onmouseup = null
  693. }
  694. }
  695. /* 运动开始 */
  696. function startMove(obj, json, fn) {
  697. clearInterval(obj.timer)
  698. obj.timer = setInterval(function() {
  699. var bStop = true //这一次运动就结束了——所有的值都到达了
  700. for (var attr in json) {
  701. //1.取当前的值
  702. var iCur = 0
  703. if (attr == 'opacity') {
  704. iCur = parseInt(parseFloat(getStyle(obj, attr)) * 100)
  705. } else {
  706. iCur = parseInt(getStyle(obj, attr))
  707. }
  708. //2.算速度
  709. var iSpeed = (json[attr] - iCur) / 8
  710. iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed)
  711. //3.检测停止
  712. if (iCur != json[attr]) {
  713. bStop = false
  714. }
  715. if (attr == 'opacity') {
  716. obj.style.filter = 'alpha(opacity:' + (iCur + iSpeed) + ')'
  717. obj.style.opacity = (iCur + iSpeed) / 100
  718. } else {
  719. obj.style[attr] = iCur + iSpeed + 'px'
  720. }
  721. }
  722. if (bStop) {
  723. clearInterval(obj.timer)
  724. if (fn) {
  725. fn()
  726. }
  727. }
  728. }, 30)
  729. }
  730. /* 运动结束 */
  731. // 弹性运动
  732. function startMove(dom, iTarget) {
  733. clearInterval(dom.timer)
  734. var iSpeed = 0,
  735. a = 0,
  736. u = 0.8
  737. dom.timer = setInterval(function() {
  738. a = (iTarget - dom.offsetLeft) / 5
  739. iSpeed = 0.8 * (iSpeed + a)
  740. if (Math.abs(iSpeed) < 1 && dom.offsetLeft === iTarget) {
  741. dom.style.left = iTarget + 'px'
  742. clearInterval(dom.timer)
  743. }
  744. dom.style.left = dom.offsetLeft + iSpeed + 'px'
  745. }, 30)
  746. }
  747. // 深度克隆
  748. function deepClone(Target, Origin) {
  749. var Origin = Origin || {}
  750. for (var prop in Target) {
  751. if (Target.hasOwnProperty(prop)) {
  752. if (Target[prop] !== 'null' && typeof Target[prop] === 'object') {
  753. if (Object.prototype.toString.call(Target[prop]) === '[object Array]') {
  754. Origin[prop] = []
  755. } else {
  756. Origin[prop] = {}
  757. }
  758. //Origin[prop] = Object.prototype.toString.call(Target[prop]) === '[object Array]' ? [] :{}//
  759. deepClone(Target[prop], Origin[prop])
  760. } else {
  761. Origin[prop] = Target[prop]
  762. }
  763. }
  764. }
  765. return Origin
  766. }
  767. //Origin深度克隆Target//
  768. // var obj = {
  769. // name : 'wang',
  770. // age : 21,
  771. // card : ['gongshang','youzheng'],
  772. // school : {
  773. // middle : '69',
  774. // high : 'songlei',
  775. // university : 'haligong'
  776. // }
  777. // }
  778. // var Cobj = {
  779. // }
  780. // deepClone(obj,Cobj);
  781. // type类型判断 jQuery内部有 $.type
  782. // ie6 null object Object.prototype.toString.call(Target) 返回[ object Object ]
  783. function type(Target) {
  784. var template = {
  785. '[object Array]': 'array',
  786. '[object Object]': 'object',
  787. '[object String]': 'string - object',
  788. '[object Nember]': 'number - object',
  789. '[object Boolean]': 'boolean - object'
  790. }
  791. // ie6兼容
  792. if (Target == null) {
  793. return 'null'
  794. } else if (typeof Target == 'object') {
  795. return template[Object.prototype.toString.call(Target)]
  796. } else {
  797. return typeof Target
  798. }
  799. }
  800. ;(function(root, factory) {
  801. if (typeof module === 'object' && typeof module.exports === 'object') {
  802. module.exports = factory()
  803. } else {
  804. root.DN = root.$ = factory()
  805. }
  806. // this =window
  807. })(this, function() {
  808. var DN = {
  809. type: function(obj) {
  810. if (obj == null) {
  811. return obj + ' '
  812. } else {
  813. return typeof obj === 'object' || typeof obj === 'function'
  814. ? class2type[Object.prototype.toString.call(obj)] || 'object'
  815. : typeof obj
  816. }
  817. }
  818. }
  819. var class2type = {}
  820. 'Boolean Number String Error Object Array Aate RegExp Function'
  821. .split(' ')
  822. .map(function(item, index) {
  823. //统一大小写
  824. class2type['[object' + item + ']'] = item.toLocaleLowerCase()
  825. })
  826. return DN
  827. })
  828. /*异步加载 */
  829. function loadScript(url, callback) {
  830. var aScript = document.createElement('script')
  831. aScript.type = 'text/javaScript'
  832. /* aScript.src=url; */
  833. if (aScript.readyState) {
  834. aScript.onreadyStateChange = function() {
  835. if (aScript.readyState == 'complete' || aScript.readyState == 'loaded') {
  836. callback()
  837. }
  838. }
  839. } else {
  840. aScript.onload = function() {
  841. callback()
  842. }
  843. }
  844. aScript.src = url
  845. /* 防止瞬间加载完毕不执行 onreadystatechange 所以在底部 */
  846. document.head.appendChild(aScript)
  847. }
  848. /*异步加载 结束*/
  849. //管理cookie
  850. var manageCookie = {
  851. //存 (名字,值,过期时间)
  852. setCookie: function(name, value, iDay) {
  853. var oDate = new Date()
  854. oDate.setDate(oDate.getDate() + iDay) //计算机当前时间iDay天后cookie过期
  855. document.cookie = name + '=' + value + ';expires=' + oDate
  856. return this
  857. },
  858. //删除cookie (要删除的名称 '1'是随便写)
  859. removeCookie: function(iName) {
  860. return this.setCookie(iName, '1', -2)
  861. },
  862. //取cookie(取谁的值)
  863. getCookie: function(name, callback) {
  864. //cookie值规律,通过 ; 和空格分隔的 ( username=123;expires=30 .......)
  865. var arr = document.cookie.split('; ') //通过 ; 和空格分隔cookie为数组
  866. /*arr->['username=123','password=admin',...]*/
  867. for (var i = 0; i < arr.length; i++) {
  868. var arr2 = arr[i].split('=') //通过=号把arr分隔成 名称,值 然后判断参数name与名称
  869. if (name == arr2[0]) {
  870. callback(arr2[1]) //返回对应的值
  871. return this
  872. }
  873. }
  874. callback('cookie not find')
  875. return this
  876. }
  877. }
  878. //数组去重
  879. Array.prototype.unique1 = function() {
  880. var tmpArr = []
  881. for (var i = 0; i < this.length; i++) {
  882. if (tmpArr.indexOf(this[i]) == -1) {
  883. tmpArr.push(this[i])
  884. }
  885. }
  886. return tmpArr
  887. }
  888. Array.form(new set([2, 2, 2, 12, 4, 5]))
  889. const newArr = [...new Set([2, 2, 2, 12, 4, 5])]
  890. Array.prototype.unique2 = function() {
  891. var tmpArr = [] //结果数组
  892. for (var i = 0; i < this.length; i++) {
  893. if (this.indexOf(this[i]) == i) {
  894. tmpArr.push(this[i])
  895. }
  896. }
  897. return tmpArr
  898. }
  899. Array.prototype.unique3 = function() {
  900. var tmpArr = [],
  901. hash = {}
  902. for (var i = 0; i < this.length; i++) {
  903. if (!hash[this[i]]) {
  904. hash[this[i]] = true
  905. tmpArr.push(this[i])
  906. }
  907. }
  908. return tmpArr
  909. }
  910. // let a = ['1', '2', '3', 1,NaN,NaN,undefined,undefined,null,null, 'a', 'b', 'b'];
  911. const unique = arr => {
  912. var obj = {}
  913. arr.forEach(value => {
  914. obj[value] = 0 //这步新添加一个属性,并赋值,如果不赋值的话,属性会添加不上去
  915. })
  916. return Object.keys(obj) //`Object.keys(对象)`返回这个对象可枚举属性组成的数组,这个数组就是去重后的数组
  917. }
  918. console.log(unique(a)) //["1", "2", "3", "NaN", "undefined", "null", "a", "b"]
  919. //防抖(在这个时间段内没有触发事件的时候才执行回调)
  920. // immediate 立即的
  921. function debounce(callback, wait, immediate) {
  922. var timer = null
  923. var debounced = function() {
  924. var _this = this
  925. var _argus = arguments
  926. clearTimeout(timer)
  927. if (immediate) {
  928. if (!timer) {
  929. callback.apply(_this, _argus)
  930. timer = setTimeout(function() {
  931. timer = null
  932. }, wait)
  933. }
  934. } else {
  935. timer = setTimeout(function() {
  936. callback.apply(_this, _argus)
  937. }, wait)
  938. }
  939. }
  940. debounced.cancel = function() {
  941. clearTimeout(timer)
  942. timer = null
  943. }
  944. return debounced
  945. }
  946. //节流(在这个时间段只触发一次回调)
  947. function throttle(callback, wait) {
  948. var lastTime = 0
  949. return function() {
  950. var nowTime = +new Date()
  951. if (lastTime - nowTime > wait) {
  952. callback.apply(this, arguments)
  953. lastTime = nowTime
  954. }
  955. }
  956. }
  957. //动态脚本
  958. function loadScript(url) {
  959. var script = document.createElement('script')
  960. script.type = 'text/javascript'
  961. script.src = url
  962. document.body.appendChild(script)
  963. }
  964. function loadScriptString(code) {
  965. var script = document.createElement('script')
  966. script.type = 'text/javascript'
  967. try {
  968. script.appendChild(document.createTextNode(code))
  969. } catch (ex) {
  970. script.text = code
  971. }
  972. document.body.appendChild(script)
  973. }
  974. //动态样式
  975. function loadStyles(url) {
  976. var link = document.createElement('link')
  977. link.rel = 'stylesheet'
  978. link.type = 'text/css'
  979. link.herf = url
  980. var head = document.getElementsByTagName('head')[0]
  981. head.appendChild(link)
  982. }
  983. function loadStylesString(css) {
  984. var style = document.createElement('style')
  985. style.type = 'text/css'
  986. try {
  987. style.appendChild(document.createTextNode(css))
  988. } catch (ex) {
  989. style.styleSheet.cssText = css
  990. }
  991. var head = document.getElementsByTagName('head')[0]
  992. head.appendChild(style)
  993. }
  994. var CookieUtil = {
  995. get: function(name) {
  996. var cookieName = encodeURIComponent(name) + '=',
  997. cookieStart = document.cookie.indexOf(cookieName),
  998. cookieValue = null,
  999. cookieEnd
  1000. if (cookieStart > -1) {
  1001. cookieEnd = document.cookie.indexOf(';', cookieStart)
  1002. if (cookieEnd == -1) {
  1003. cookieEnd = document.cookie.length
  1004. }
  1005. cookieValue = decodeURIComponent(
  1006. document.cookie.substring(cookieStart + cookieName.length, cookieEnd)
  1007. )
  1008. }
  1009. return cookieValue
  1010. },
  1011. set: function(name, value, expires, path, domain, secure) {
  1012. var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value)
  1013. if (expires instanceof Date) {
  1014. cookieText += '; expires=' + expires.toGMTString()
  1015. }
  1016. if (path) {
  1017. cookieText += '; path=' + path
  1018. }
  1019. if (domain) {
  1020. cookieText += '; domain=' + domain
  1021. }
  1022. if (secure) {
  1023. cookieText += '; secure'
  1024. }
  1025. document.cookie = cookieText
  1026. },
  1027. unset: function(name, path, domain, secure) {
  1028. this.set(name, '', new Date(0), path, domain, secure)
  1029. }
  1030. }
  1031. /**
  1032. // 设置 cookie
  1033. CookieUtil.set('name', 'lai');
  1034. CookieUtil.set('sex', 'man');
  1035. // 读取 cookie
  1036. CookieUtil.get('name'); // 'lai'
  1037. CookieUtil.get('sex'); // 'man'
  1038. // 删除 cookie
  1039. CookieUtil.unset('name');
  1040. CookieUtil.unset('sex');
  1041. // 设置 cookie,包括它的路径、域、失效日期
  1042. CookieUtil.set('name', 'lai', '/', 'www.laixiangran.cn', new Date());
  1043. */

isMobile, isEmail, isDate

  1. export function isMobile(value: string): boolean {
  2. value = value.replace(/[^-|\d]/g, '');
  3. return /^((\+86)|(86))?(1)\d{10}$/.test(value) || /^0[0-9-]{10,13}$/.test(value);
  4. }
  5. /* eslint-disable */
  6. export function isEmail(value: string): boolean {
  7. const reg = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
  8. return reg.test(value);
  9. }
  10. import { isNaN } from './number';
  11. export function isDate(date: Date): boolean {
  12. return (
  13. Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime())
  14. );
  15. }

urlToBase64

  1. urlToBase64(url) {
  2. return new Promise ((resolve,reject) => {
  3. let image = new Image();
  4. image.onload = function() {
  5. let canvas = document.createElement('canvas');
  6. canvas.width = canvas.naturalWidth;
  7. canvas.height = canvas.naturalHeight;
  8. // 将图片插入画布并开始绘制
  9. canvas.getContext('2d').drawImage(image, 0, 0);
  10. let result = canvas.toDataURL('image/png')
  11. resolve(result);
  12. };
  13. // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
  14. image.setAttribute("crossOrigin",'Anonymous');
  15. image.src = url;
  16. // 图片加载失败的错误处理
  17. image.onerror = () => {
  18. reject(newError('图片流异常'));
  19. });
  20. }

base64ToBlob

  1. base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
  2. return new Promise((resolve, reject) => {
  3. // 使用 atob() 方法将数据解码let byteCharacters = atob(b64data);
  4. let byteArrays = [];
  5. for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
  6. let slice = byteCharacters.slice(offset, offset + sliceSize);
  7. let byteNumbers = [];
  8. for (let i = 0; i < slice.length; i++) {
  9. byteNumbers.push(slice.charCodeAt(i));
  10. }
  11. // 8 位无符号整数值的类型化数组。内容将初始化为 0。// 如果无法分配请求数目的字节,则将引发异常。
  12. byteArrays.push(newUint8Array(byteNumbers));
  13. }
  14. let result = new Blob(byteArrays, {
  15. type: contentType
  16. })
  17. result = Object.assign(result,{
  18. // jartto: 这里一定要处理一下 URL.createObjectURL
  19. preview: URL.createObjectURL(result),
  20. name: `图片示例.png`
  21. });
  22. resolve(result)
  23. })
  24. }

blobToBase64

  1. blobToBase64(blob) {
  2. return new Promise((resolve, reject) => {
  3. const fileReader = new FileReader();
  4. fileReader.onload = (e) => {
  5. resolve(e.target.result);
  6. };
  7. // readAsDataURL
  8. fileReader.readAsDataURL(blob);
  9. fileReader.onerror = () => {
  10. reject(newError('文件流异常'));
  11. };
  12. });
  13. }

返回对象指定的键值

  1. // 返回对象指定的键值
  2. function GetKeys(obj = {}, keys = []) {
  3. return Object.keys(obj).reduce((items, item) => (
  4. keys.includes(item) && (items[item] = obj[item]), items
  5. ), {});
  6. }
  7. const target = { a: 1, b: 2, c: 3, d: 4 };
  8. const keyword = ["a", "d"];
  9. GetKeys(target, keyword);
  10. // { a: 1, d: 4 }

字符串翻转

  1. // 字符串翻转
  2. function ReverseStr(str = "") {
  3. return str.split("").reduceRight((items, item) => items + item);
  4. }
  5. const str = "reduce最牛逼";
  6. ReverseStr(str);
  7. // "逼牛最ecuder"

对象成员特殊分组

  1. // 对象成员特殊分组
  2. function Group(arr = [], key) {
  3. return key ? arr.reduce((t, v) => (
  4. !t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t
  5. ), {}) : {};
  6. }
  7. const arr = [
  8. { area: "GZ", name: "YZW", age: 27 },
  9. { area: "GZ", name: "TYJ", age: 25 },
  10. { area: "SZ", name: "AAA", age: 23 },
  11. { area: "FS", name: "BBB", age: 21 },
  12. { area: "SZ", name: "CCC", age: 19 }
  13. ];
  14. // 以地区area作为分组依据
  15. Group(arr, "area");
  16. //{ GZ: Array(2), SZ: Array(2), FS: Array(1) }

数组分割 例: chunk([1, 2, 3, 4, 5], 2) -> [[1, 2], [3, 4], [5]]

  1. // 数组分割
  2. function Chunk(arr = [], size = 1) {
  3. return arr.length ? arr.reduce((items, item) => {
  4. return items[items.length - 1].length === size
  5. ? items.push([item]) : items[items.length - 1].push(item)
  6. , items
  7. }, [[]])
  8. : [];
  9. }
  10. const arr = [1, 2, 3, 4, 5];
  11. Chunk(arr, 2);
  12. // [[1, 2], [3, 4], [5]]

react should update

  1. var { List, Map } = Immutable;
  2. var is = Immutable.is.bind(Immutable);
  3. function shallowEqualImmutable(objA, objB) {
  4. if (objA === objB || is(objA, objB)) {
  5. return true;
  6. }
  7. if (typeof objA !== 'object' || objA === null ||
  8. typeof objB !== 'object' || objB === null) {
  9. return false;
  10. }
  11. var keysA = Object.keys(objA);
  12. var keysB = Object.keys(objB);
  13. if (keysA.length !== keysB.length) {
  14. return false;
  15. }
  16. // Test for A's keys different from B.
  17. var bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
  18. for (var i = 0; i < keysA.length; i++) {
  19. if (!bHasOwnProperty(keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
  20. return false;
  21. }
  22. }
  23. return true;
  24. }

把字符串转成以分为单位的整数。

  1. /**
  2. * tozhCN 把字符串转成以分为单位的整数。
  3. * @memberof module:money
  4. * @param {number|string} num 金额
  5. * @returns {string} 中文大写的金额, 标准会计格式
  6. * @runkit true
  7. * @example
  8. * tozhCN(500.3);
  9. * // => 伍佰元叁角整
  10. */
  11. function tozhCN(num: string | number): string {
  12. if (typeof num === 'number') {
  13. num = String(num);
  14. }
  15. if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(num)) {
  16. throw new Error(`非法数据: ${JSON.stringify(num)}`);
  17. }
  18. let unit = '京亿万仟佰拾兆万仟佰拾亿仟佰拾万仟佰拾元角分';
  19. let str: string = '';
  20. num += '00';
  21. const pos = num.indexOf('.');
  22. if (pos >= 0) {
  23. num = num.substring(0, pos) + num.substr(pos + 1, 2);
  24. }
  25. unit = unit.substr(unit.length - num.length);
  26. for (let i = 0, len = num.length; i < len; i++) {
  27. str +=
  28. '零壹贰叁肆伍陆柒捌玖'.charAt(Number(num.charAt(i))) + unit.charAt(i);
  29. }
  30. return str
  31. .replace(/零(仟|佰|拾|角)/g, '零')
  32. .replace(/(零)+/g, '零')
  33. .replace(/零(兆|万|亿|元)/g, '$1')
  34. .replace(/(兆|亿)万/g, '$1')
  35. .replace(/(京|兆)亿/g, '$1')
  36. .replace(/(京)兆/g, '$1')
  37. .replace(/(京|兆|亿|仟|佰|拾)(万?)(.)仟/g, '$1$2零$3仟')
  38. .replace(/^元零?|零分/g, '')
  39. .replace(/(元|角)$/g, '$1整');
  40. }

模板字符串替代方案

  1. function parseStringTemplate(str, obj) {
  2. let parts = str.split(/\$\{(?!\d)[\wæøåÆØÅ]*\}/);
  3. let args = str.match(/[^{\}]+(?=})/g) || [];
  4. let parameters = args.map(argument => obj[argument] || (obj[argument] === undefined ? "" : obj[argument]));
  5. return String.raw({ raw: parts }, ...parameters);
  6. }
  7. undefined
  8. parseStringTemplate("[ActiveX 控件自动提示]未启用,请手动启用!${a}", { a: "<div class='repair' onclick='writereg()'>可点击一键修复</div>"})
  9. "[ActiveX 控件自动提示]未启用,请手动启用!<div class='repair' onclick='writereg()'>可点击一键修复</div>"

扁平数据转tree

  1. function arrayToTree(items) {
  2. const result = []; // 存放结果集
  3. const itemMap = {}; //
  4. for (const item of items) {
  5. const id = item.id;
  6. const pid = item.pid;
  7. if (!itemMap[id]) {
  8. itemMap[id] = {
  9. children: [],
  10. }
  11. }
  12. itemMap[id] = {
  13. ...item,
  14. children: itemMap[id]['children']
  15. }
  16. const treeItem = itemMap[id];
  17. if (pid === 0) {
  18. result.push(treeItem);
  19. } else {
  20. if (!itemMap[pid]) {
  21. itemMap[pid] = {
  22. children: [],
  23. }
  24. }
  25. itemMap[pid].children.push(treeItem)
  26. }
  27. }
  28. return result;
  29. }
  30. const arr = [
  31. {id: 1, name: '部门1', pid: 0},
  32. {id: 2, name: '部门2', pid: 1},
  33. {id: 3, name: '部门3', pid: 1},
  34. {id: 4, name: '部门4', pid: 3},
  35. {id: 5, name: '部门5', pid: 4},
  36. ]
  37. // 格式如下图

image.png

LRU cache

  1. class LRUCache {
  2. constructor(lenght) {
  3. this.length = lenght; // 存储长度
  4. this.data = new Map(); // 存储数据
  5. }
  6. // 存储数据,通过键值对的方式
  7. set(key, value) {
  8. const data = this.data;
  9. if (data.has(key)) {
  10. data.delete(key)
  11. }
  12. data.set(key, value);
  13. // 如果超出了容量,则需要删除最久的数据
  14. if (data.size > this.length) {
  15. const delKey = data.keys().next().value;
  16. data.delete(delKey);
  17. }
  18. }
  19. // 获取数据
  20. get(key) {
  21. const data = this.data;
  22. // 未找到
  23. if (!data.has(key)) {
  24. return null;
  25. }
  26. const value = data.get(key); // 获取元素
  27. data.delete(key); // 删除元素
  28. data.set(key, value); // 重新插入元素
  29. }
  30. }
  31. const lruCache = new LRUCache(5);
  32. // 超出了容量 就删除最早的数据
  33. lruCache.set('name', '小猪课堂');
  34. lruCache.set('age', 22);
  35. lruCache.set('sex', '男');
  36. lruCache.set('height', 176);
  37. lruCache.set('weight', '100');
  38. lruCache.set('height1', 176);
  39. lruCache.set('weight2', '100');
  40. console.log(lruCache);
  41. // sex, height, weight, height1, weight2