vite+ts项目知识点笔记(中)

简介: fs-extra是fs的一个扩展,提供了非常多的便利API,并且继承了fs所有方法和为fs方法添加了promise的支持。

7 解构出的Api



ProxyOptions

import type { ProxyOptions } from 'vite';
import { InjectionKey, Ref } from 'vue';
import { createContext, useContext } from '/@/hooks/core/useContext';
export interface AppProviderContextProps {
  prefixCls: Ref<string>;
  isMobile: Ref<boolean>;
}
const key: InjectionKey<AppProviderContextProps> = Symbol();
export function createAppProviderContext(context: AppProviderContextProps) {
  return createContext<AppProviderContextProps>(context, key);
}
export function useAppProviderContext() {
  return useContext<AppProviderContextProps>(key);
}
import type { CSSProperties, PropType } from 'vue';
import type { FunctionalComponent, CSSProperties } from 'vue';
const menuManager: {
  domList: Element[];
  resolve: Fn;
} = {
  domList: [],
  resolve: () => {},
};
const propsData: Partial<ContextMenuProps> = {};
const propsData: Partial<ContextMenuProps> = {};
let timerId: ReturnType<typeof setInterval> | null;
import type { CSSProperties } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs';
import type { Directive, App } from 'vue';
const loadingDirective: Directive = {
  mounted(el, binding) {
    const tip = el.getAttribute('loading-tip');
    const background = el.getAttribute('loading-background');
    const size = el.getAttribute('loading-size');
    const fullscreen = !!binding.modifiers.fullscreen;
    const instance = createLoading(
      {
        tip,
        background,
        size: size || 'large',
        loading: !!binding.value,
        absolute: !fullscreen,
      },
      fullscreen ? document.body : el
    );
    el.instance = instance;
  },
  updated(el, binding) {
    const instance = el.instance;
    if (!instance) return;
    instance.setTip(el.getAttribute('loading-tip'));
    if (binding.oldValue !== binding.value) {
      if (binding.oldValue !== binding.value) {
        instance.setLoading?.(binding.value && !instance.loading);
      }
    }
  },
  unmounted(el) {
    el?.instance?.close();
  },
};
const mounted = (el: Element, binding: DirectiveBinding<any>) => {
  isAuth(el, binding);
};
import type { InjectionKey, ComputedRef, Ref } from 'vue';
import { createContext, useContext } from '/@/hooks/core/useContext';
export interface PageContextProps {
  contentHeight: ComputedRef<number>;
  pageHeight: Ref<number>;
  setPageHeight: (height: number) => Promise<void>;
}
const key: InjectionKey<PageContextProps> = Symbol();
export function createPageContext(context: PageContextProps) {
  return createContext<PageContextProps>(context, key, { native: true });
}
export function usePageContext() {
  return useContext<PageContextProps>(key);
}
export function entries<T>(obj: Recordable<T>): [string, T][] {
  return Object.keys(obj).map((key: string) => [key, obj[key]]);
}

8 公共函数



isDevFn

export function isDevFn(mode: string): boolean {
  return mode === 'development';
}

wrapperEnv

/**
 * @description 转换从 .env 文件中获取的对象
 * @author wfd
 * @date 2021/10/8 09:30
 * @param envConf
 */
export function wrapperEnv(envConf: Recordable): ViteEnv {
  // 创建一个对象来存储转换的键值
  const ret: any = {};
  /**
   * @description wrapperEnv
   * @author wfd
   * @date 2021/10/8 14:19
   * @example
   * Object.keys(envConf) = [
        'VITE_USE_MOCK',
        'VITE_PUBLIC_PATH',
        'VITE_PROXY',
        'VITE_DROP_CONSOLE',
        'VITE_GLOB_API_URL',
        'VITE_GLOB_UPLOAD_URL',
        'VITE_GLOB_API_URL_PREFIX',
        'VITE_PORT',
        'VITE_GLOB_APP_TITLE',
        'VITE_GLOB_APP_SHORT_NAME'
     ]
   */
  for (const envName of Object.keys(envConf)) {
    /**
     * @description
       realName 是每一个配置对应的 value
       中间的正则替换就是将\\n替换成\n。
       console.log('asda\\\n\\n\n'.replace(/\n/g, '\n')) =>asda\ [回车\n] \n [回车\n]
       console.log('asda\\\n\\n\n'.replace(/\\n/g, '\n'))=>asda\ [回车\n] [回车\n] [回车\n]
       console.log('asda\\\n\\n\n'.replace(/\\\n/g, '\n'))=>asda [回车\n] \n [回车\n]
     */
    let realName = envConf[envName].replace(/\\n/g, '\n');
    // 将 'true' 或者 'false' 的字符串转换为 boolean 对应的 true 或者 false
    realName = realName === 'true' ? true : realName === 'false' ? false : realName;
    // 端口转换成 number 类型
    if (envName === 'VITE_PORT') {
      realName = Number(realName);
    }
    // 将代理配置转换成数组
    if (envName === 'VITE_PROXY' && realName) {
      try {
        realName = JSON.parse(realName.replace(/'/g, '"'));
      } catch (error) {
        realName = '';
      }
    }
    // 将转换后的属性值 realName 赋值给 ret 对应的每一个键
    ret[envName] = realName;
    // 将原始的值也就是未转换的值赋值给 process.env
    if (typeof realName === 'string') {
      process.env[envName] = realName;
    } else if (typeof realName === 'object') {
      process.env[envName] = JSON.stringify(realName);
    }
  }
  return ret;
}

getConfFiles

/**
 * 获取当前环境下生效的配置文件名
 */
function getConfFiles() {
  const script = process.env.npm_lifecycle_script;
  const reg = new RegExp('--mode ([a-z]+)');
  const result = reg.exec(script as string) as any;
  if (result) {
    const mode = result[1] as string;
    return ['.env', `.env.${mode}`];
  }
  return ['.env', '.env.production'];
}

getEnvConfig

export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) {
  let envConfig = {};
  confFiles.forEach((item) => {
    try {
      const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item)));
      envConfig = { ...envConfig, ...env };
    } catch (e) {
      console.error(`Error in parsing ${item}`, e);
    }
  });
  const reg = new RegExp(`^(${match})`);
  Object.keys(envConfig).forEach((key) => {
    if (!reg.test(key)) {
      Reflect.deleteProperty(envConfig, key);
    }
  });
  return envConfig;
}

resultSuccess

export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
  return {
    code: 0,
    result,
    message,
    type: 'success',
  };
}

resultPageSuccess

export function resultPageSuccess<T = any>(
  page: number,
  pageSize: number,
  list: T[],
  { message = 'ok' } = {}
) {
  const pageData = pagination(page, pageSize, list);
\
  return {
    ...resultSuccess({
      items: pageData,
      total: list.length,
    }),
    message,
  };
}

resultError

export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
  return {
    code,
    result,
    message,
    type: 'error',
  };
}

pagination

export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
  const offset = (pageNo - 1) * Number(pageSize);
  const ret =
    offset + Number(pageSize) >= array.length
      ? array.slice(offset, array.length)
      : array.slice(offset, offset + Number(pageSize));
  return ret;
}

requestParams

export interface requestParams {
  method: string;
  body: any;
  headers?: { authorization?: string };
  query: any;
}

getRequestToken

/**
 * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改
 *
 */
export function getRequestToken({ headers }: requestParams): string | undefined {
  return headers?.authorization;
}

getRootPath

export function getRootPath(...dir: string[]) {
  return path.resolve(process.cwd(), ...dir);
}

withInstall

export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component);
    if (alias) {
      app.config.globalProperties[alias] = component;
    }
  };
  return component as T & Plugin;
};

isHexColor

/**
 * 判断是否 十六进制颜色值.
 * 输入形式可为 #fff000 #f00
 *
 * @param   String  color   十六进制颜色值
 * @return  Boolean
 */
export function isHexColor(color: string) {
  const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/;
  return reg.test(color);
}

rgbToHex

/**
 * RGB 颜色值转换为 十六进制颜色值.
 * r, g, 和 b 需要在 [0, 255] 范围内
 *
 * @return  String          类似#ff00ff
 * @param r
 * @param g
 * @param b
 */
export function rgbToHex(r: number, g: number, b: number) {
  // tslint:disable-next-line:no-bitwise
  const hex = ((r << 16) | (g << 8) | b).toString(16);
  return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex;
}

hexToRGB

/**
 * Transform a HEX color to its RGB representation
 * @param {string} hex The color to transform
 * @returns The RGB representation of the passed color
 */
export function hexToRGB(hex: string) {
  let sHex = hex.toLowerCase();
  if (isHexColor(hex)) {
    if (sHex.length === 4) {
      let sColorNew = '#';
      for (let i = 1; i < 4; i += 1) {
        sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1));
      }
      sHex = sColorNew;
    }
    const sColorChange: number[] = [];
    for (let i = 1; i < 7; i += 2) {
      sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2)));
    }
    return 'RGB(' + sColorChange.join(',') + ')';
  }
  return sHex;
}

colorIsDark

export function colorIsDark(color: string) {
  if (!isHexColor(color)) return;
  const [r, g, b] = hexToRGB(color)
    .replace(/(?:\(|\)|rgb|RGB)*/g, '')
    .split(',')
    .map((item) => Number(item));
  return r * 0.299 + g * 0.578 + b * 0.114 < 192;
}

darken

/**
 * Darkens a HEX color given the passed percentage
 * @param {string} color The color to process
 * @param {number} amount The amount to change the color by
 * @returns {string} The HEX representation of the processed color
 */
export function darken(color: string, amount: number) {
  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
  amount = Math.trunc((255 * amount) / 100);
  return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight(
    color.substring(2, 4),
    amount
  )}${subtractLight(color.substring(4, 6), amount)}`;
}

lighten

/**
 * Lightens a 6 char HEX color according to the passed percentage
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed color represented as HEX
 */
export function lighten(color: string, amount: number) {
  color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
  amount = Math.trunc((255 * amount) / 100);
  return `#${addLight(color.substring(0, 2), amount)}${addLight(
    color.substring(2, 4),
    amount
  )}${addLight(color.substring(4, 6), amount)}`;
}

addLight

/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */
/**
 * Sums the passed percentage to the R, G or B of a HEX color
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed part of the color
 */
function addLight(color: string, amount: number) {
  const cc = parseInt(color, 16) + amount;
  const c = cc > 255 ? 255 : cc;
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
}

luminanace

/**
 * Calculates luminance of an rgb color
 * @param {number} r red
 * @param {number} g green
 * @param {number} b blue
 */
function luminanace(r: number, g: number, b: number) {
  const a = [r, g, b].map((v) => {
    v /= 255;
    return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
  });
  return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}

contrast

/**
 * Calculates contrast between two rgb colors
 * @param {string} rgb1 rgb color 1
 * @param {string} rgb2 rgb color 2
 */
function contrast(rgb1: string[], rgb2: number[]) {
  return (
    (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
    (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
  );
}

calculateBestTextColor

/**
 * Determines what the best text color is (black or white) based con the contrast with the background
 * @param hexColor - Last selected color by the user
 */
export function calculateBestTextColor(hexColor: string) {
  const rgbColor = hexToRGB(hexColor.substring(1));
  const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]);
\
  return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF';
}

subtractLight

/**
 * Subtracts the indicated percentage to the R, G or B of a HEX color
 * @param {string} color The color to change
 * @param {number} amount The amount to change the color by
 * @returns {string} The processed part of the color
 */
function subtractLight(color: string, amount: number) {
  const cc = parseInt(color, 16) - amount;
  const c = cc < 0 ? 0 : cc;
  return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
}


相关文章
|
4月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript数组转置
[小笔记]TypeScript/JavaScript数组转置
37 0
|
4月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript模拟Python中的Range函数
[小笔记]TypeScript/JavaScript模拟Python中的Range函数
28 0
|
21天前
|
JavaScript 前端开发
TypeScript极速入门笔记1
TypeScript极速入门笔记1
30 4
|
4月前
|
JavaScript 前端开发 Java
小笔记:如何使用代码注释:关于JavaScript与TypeScript 注释和文档的自动生成
小笔记:如何使用代码注释:关于JavaScript与TypeScript 注释和文档的自动生成
191 0
|
4月前
|
JavaScript 前端开发 测试技术
[小笔记]TypeScript/JavaScript模拟Python中的zip(不使用map)
[小笔记]TypeScript/JavaScript模拟Python中的zip(不使用map)
19 0
|
4月前
|
存储 JavaScript 前端开发
TypeScript笔记(15)—— 深入理解TypeScript中的装饰器
TypeScript笔记(15)—— 深入理解TypeScript中的装饰器
54 0
|
4月前
|
存储 JavaScript 前端开发
TypeScript笔记(5)—— 基本数据类型
TypeScript笔记(5)—— 基本数据类型
39 0
|
4月前
|
JavaScript 前端开发 编译器
TypeScript笔记(4)—— TypeScript中的类型注解
TypeScript笔记(4)—— TypeScript中的类型注解
20 0
|
4月前
|
域名解析 JavaScript 前端开发
TypeScript笔记(3)—— 使用WebPack工具
TypeScript笔记(3)—— 使用WebPack工具
25 0
|
4月前
|
JSON JavaScript 前端开发
TypeScript笔记(2)—— 使用VSCode实时编译TypeScript代码
TypeScript笔记(2)—— 使用VSCode实时编译TypeScript代码
50 0