`标识点模板代码 Template`

<div style="display:inline-block;margin-right: 10px;width:10px;height:10px;background:red;border-radius:100%;"></div>

---
1
2
3
4
5

# Interview

# ES6 (ES2015) 新特性


- 箭头函数 `()=>{}`

- 模板字符串

- let & const 申明

- Promise 对象

- async / await

- 解构赋值

- 扩展运算符

- Class 类语法 

- 新数据类型
  - Symbol 唯一值
  - Set
  - Map

- 模块化(importexport- 数组Array
  - find 、includes、flat

- Proxy
- Reflect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  • 其他重要

ES2017

async / (await queueMicrotask); // 设置 微任务
1

ES2020

- grobalThis;

- BigInt
1
2
3

# null & undefined

null == undefined; // true
null === undefined; // false

// null 在四则运算时会自动转换为 `数值`
Number(null); // 0
5 + null; // 5

Number(undefined); // NaN
1
2
3
4
5
6
7
8

# 非运算 转为 false 的值

  • false
  • null
  • undefined
  • 0
  • "" , ''
  • NaN

# NaN 是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。

  • NaN 不等于任何值,包括其本身
NaN === NaN; // false
1
  • isNaN() 可用于判断 数据类型是否为 NaN
isNaN(NaN); // true
isNaN(1); // false
1
2

# JS 中最快的 StringNumber 操作

let str1 = "123";
str1 = +str1; // 123
str1 = 0 + str1; // '123' 字符串
1
2
3
  • 注意: 实际代码中不建议这么做,建议使用Number()parseInt()

# ASCII 码 (后面两个会使到,简单介绍一下)

ASCII 编码表  是美国信息交换标准代码 (American Standard Code for Information Interchange)的缩写,是一种用于表示文本的计算机编码系统。

ASCII 表是 0-127,共 128 个字符, 但是现在的代码中,使用到的各类字符,早已经超出了 ASCII 表可表示的 128 个字符,列如ASCII 无法表示汉字

UTF-8(可以表示超过110万个字符) 就是更为全面和通用的编码方式

下面介绍的 Base64 、encodeURI、encodeURIComponent都是为了防止特殊字符的无法表示,而进行转码可以打印的字符

每一个 ASCII 都有 3 部分组成. ASCII 值、16 进制、控制字符。

// 如
ASCI16进制 控制字符
  64    40H     @
  65    41H     A
  66    42H     B
1
2
3
4
5

# Base64 转码 (✳)

所谓 Base64 就是一种编码方法,可以将任意值转成0 ~ 9、A ~ Z、a-z、+和/这 64 个字符组成的可打印字符。 使用它的主要目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理。

有时,文本里面包含一些不可打印的符号,比如 ASCII 码 0 到 31 的符号都无法打印出来,这时可以使用 Base64 编码,将它们转成可以打印的字符。

JavaScript 原生提供两个 Base64 相关的方法。

  • btoa():( binary to ASCII ) 任意值转为 Base64 编码
  • atob():( ASCII to binary ) Base64 编码转为原来的值
var string = "Hello World!";
btoa(string); // "SGVsbG8gV29ybGQh"
atob("SGVsbG8gV29ybGQh"); // "Hello World!"
1
2
3
注意,这两个方法不适合非 ASCII 码的字符,会报错。
btoa('你好') // 报错
1

要将非 ASCII 码字符转为 Base64 编码,必须中间插入一个转码环节,再使用这两个方法。

function b64Encode(str) {
  return btoa(encodeURIComponent(str));
}

function b64Decode(str) {
  return decodeURIComponent(atob(str));
}

b64Encode("你好"); // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode("JUU0JUJEJUEwJUU1JUE1JUJE"); // "你好"
1
2
3
4
5
6
7
8
9
10

# encodeURI && encodeURIComponent

encodeURI(有些特殊字符不会转义)encodeURIComponent(所有字符都会转义) 都是 JavaScript 中用于编码 URI 的函数,但它们的用途和行为有所不同。

# encodeURI

encodeURI 函数用于编码整个统一资源标识符(URI),包括路径、查询字符串和片段。它对 URI 中的特殊字符进行编码,但不包括用于分隔 URI 组件的特殊字符(如:/?#.-)。这意味着,如果你有一个完整的 URI 并且想要对其进行编码,以便用作 URL 的一部分,你应该使用 encodeURI

例如:

var originalUrl = "http://example.com/my path/file.txt?query=valu#e";
var encodedUrl = encodeURI(originalUrl);
console.log(encodedUrl); // 输出 "http://example.com/my path/file.txt?query=valu#e"
1
2
3

在这个例子中,encodeURI 不会对路径中的空格或查询字符串中的字符进行编码,因为这些字符是 URI 的一部分,并且按照标准不需要编码。

# encodeURIComponent

encodeURIComponent 函数用于编码单个 URI 组件,如路径、查询字符串的键或值。它会对几乎所有非字母数字字符进行编码,包括那些在encodeURI中不被编码的字符(如/?&)。这意味着,当你需要对 URI 的某个特定部分进行编码时,你应该使用 encodeURIComponent

例如:

var path = "my path/file.txt";
var encodedPath = encodeURIComponent(path);
console.log(encodedPath); // 输出 "my%20path%2Ffile.txt"
1
2
3

在这个例子中,encodeURIComponent 将路径中的空格编码为 %20,斜杠(/)编码为 %2F,这是因为当这些字符出现在 URI 的路径部分时,它们通常需要进行编码。

# 总结

  • 使用 encodeURI 当你需要编码整个 URI,并且想要保留 URI 组件之间的分隔符时。
  • 使用 encodeURIComponent 当你需要编码 URI 的单个组件,并且想要确保所有可能引起问题的字符都被编码时。

正确使用这些函数可以确保你的 URL 在各种情况下都能正确地被解析和处理。在构建 URL 时,通常需要对每个组件单独进行编码,然后将它们组合成一个完整的 URI。

# UNUNUNUN (opens new window)

# typeof & instanceof & Object.proptotype.toString 区别

  • typeof 基础类型运算符:仅基本三类型+object

    注意 typeof null == 'object', 特殊,JS 的遗留问题

  • instanceof 实例运算符:instanceof 运算符返回一个布尔值,表示对象是否为某个构造函数的实例。

    注意 instanceof只能用于对象, 无法判断 基本三类型 注意 null instanceof Object //false, 特殊,JS 的遗留问题

  • Object.proptotype.toString 所有类型判断函数

    JS 中最强类型判断函数

# JS 数值储存的精度 及 衍生问题

数值 (opens new window)

数值精度

JavaScript 内部,所有数字都是以 64 位浮点数形式储存

根据国际标准 IEEE 754,JavaScript 浮点数的 64 个二进制位,从最左边开始,是这样组成的。

  • 第 1 位:符号位,0 表示正数,1 表示负数
  • 第 2 位到第 12 位(共 11 位):指数部分
  • 第 13 位到第 64 位(共 52 位):小数部分(即有效数字) 符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

JavaScript 提供 Number 对象的 MAX_VALUE 和 MIN_VALUE 属性,返回可以表示的具体的最大值和最小值。

Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MIN_VALUE; // 5e-324
1
2

# (little skill)在不报错情况下,typeof 可以用来检查一个没有声明的变量

// 错误的写法-变量v没有用var命令声明,直接使用就会报错
if (v) {
  // ...
}
// ReferenceError: v is not defined

// 正确的写法
if (typeof v === "undefined") {
  // ...
}
1
2
3
4
5
6
7
8
9
10

# (DOM)移除当前元素

使用 el.parentNode.removeChild 方法 或者 使用 remove 方法

// 假设你已经获取到了当前元素,例如通过事件监听器的 target 属性
var currentElement = event.target;

// 确保当前元素有父节点
if (currentElement.parentNode) {
  currentElement.parentNode.removeChild(currentElement);
}

// 或者 --------------------------------------------------------
var currentElement = event.target; // 同样假设你已经获取到了当前元素
currentElement.remove(); // 直接移除当前元素
1
2
3
4
5
6
7
8
9
10
11

# 技术栈

  • Viewer.js 图预览
    • https://mirari.cc/v-viewer/
    • https://www.npmjs.com/package/viewerjs
  • vue-tree-chart 树状 tag 图
  • vue-clipboard2 复制
  • knex knex框架是一个ORM框架,使用knex可以用JavaScript语法指令来操作SQL语句

# JS Reg 正则

# JS 语言

  • 弱类型语言 (动态类型语言)

强类型语言 如 JAVA、C、Tpyescript 等,申明变量时必要申明其数据类型,且之后操作数据类型不可变 弱类型语言 如 Javascript、Python 等,申明变量时 无需申明其数据类型,且之后操作数据类型可变

  • 运行环境:浏览器browser

  • 衍生: Typescript, 弥补由于Javascript动态类型特性带来的语言缺陷,是JS的超集

TS 是强类型语言 TS 相当于JS的马甲,其本质编码逻辑是一样的, 只不过最突出的区别是TS有数据类型声明的特性

  • 进阶: NodeJS , 突破了JS本身只能在浏览器环境的运行环境,可以在操作系统环境中运行

NodeJS 是一种名称而已,本质就是JS运行的一种环境描述,可以理解为赋予了JS的接入操作系统级别环境的权限(具体超集的模块如 fs、http),官网描述【Run JavaScript Everywhere】 NodeJS 利用 chrome v8 引擎实现了在操作系统环境中运行,如实现文件操作、网络服务器搭建等 TS 和 JS 都可以在 NodeJS 中使用,只是一种 NodeJS 采取语言特性的表现形式

# JS 运行机制

JS的运行机制

# 构造函数

# 原型&原型链

# Class 类语法

ES6 新特性 Class 类的全方面理解 (opens new window)

  • 类语法 创建实例必须new
  • 类语法 不存在变量提升(相较于 ES5 的构造函数写法)
  • 类语法 中 this 指向实例对象
  • 类语法 都有 constructor 函数 (默认 return this, 如不手写 constructor 会默认生成)
  • 类语法 static 静态变量仅供 类 调用
  • 类语法 static 静态函数中的 this 指向类
class Creature {
  baz = "hihi";
  static staticField = "staticField"; // static 静态变量仅供 类 调用
  static bar() {
    console.log(this.baz); // static 静态函数中的 this 指向类
  }

  constructor() {
    this.field = "field"; // this指向实例对象
    // 默认返回 return this
  }
}
1
2
3
4
5
6
7
8
9
10
11
12

# new 构造对象原理

# this指向

浅解 this 指向

最常用的基本就五种情况

# call、apply、bind

# 事件循环 EventLoop

# JS Promise() 对象

  • 异步-微任务

  • 重点:

    • Promise 通常由 三种状态,进行中、已完成、已拒绝,且只能由 进行中 到 已完成, 进行中 到 已拒绝
    • ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。
  • 优点:解决回调地狱

  • 缺点:执行无法终止(除非状态变更)

  • 使用 Promise

    注意: resolve 和 reject (和 return 不一样)不会影响后面的语句执行

/**
 * 异步链式调用写法
 */
let mp = new Promise((resolve, reject) => {
  resolve("arg");
  // or
  // reject('arg')
});
mp.then((res) => {
  console.log("resolve", res);
}).catch((err) => {
  console.log("reject", err);
});

/**
 * async/await同步调用写法
 */
let mp001 = () =>
  new Promise((resolve, reject) => {
    // resolve("arg");
    // or
    reject("arg");
  });
let mp001test = async () => {
  try {
    let res = await mp001();
    console.log("resolve", res);
  } catch (e) {
    console.log("reject", e);
  }
};
mp001test();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 申明变量赋值Promise,会得到Promise对象

let mp = new Promise((resolve,resject)=>{})
// Promise {<pending>}

let mpRs = new Promise((resolve,resject)=>{
  resolve()
})
// Promise {<fulfilled>: undefined}

let mpRj = new Promise((resolve,resject)=>{
  resject()
})
// Promise {<rejected>: undefined}
// Uncaught (in promise) undefined // reject 必须要 catch,否则报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14

# Promise.all

  • 并发异步请求
  • 等所有的异步函数都进入 已完成状态,才执行 then 回调;如有函数已拒绝,就直接进入 catch
  • 所有的异步函数都会被执行完
Promise.all([asyncFn,asyncFn,...]).then(res=>{}).catch(err=>{})
1

# Promise.allSettled

  • 并发异步请求__想知道每个 promise 的结果
  • 等所有的异步函数完成(不管状态),才执行 then 回调
  • 所有的异步函数都会被执行完
Promise.all([asyncFn,asyncFn,...]).then(res=>{})

// [
//    { status: 'fulfilled', value: 42 },
//    { status: 'rejected', reason: -1 }
// ]
1
2
3
4
5
6

# Promise.race

  • race 的用法是:传入多个 promise 实例,谁跑的快,就以谁的结果执行回调
Promise.race([asyncFn,asyncFn,...]).then(res=>{}).catch(err=>{})
1

# 手写 Promise()

# JS Blob() 对象

  • Blob (Binary Large Object) 不可变 二进制 类文件对象(通常是 影像、音频等多媒体文件) 是处理大量数据和二进制数据的重要工具类
应用场景
- 需求:图片本地预览 结合 URL.createObjectURL(file/Blob) 使用
- JS File() 对象 (继承于 Blob 对象)
- https://xie.infoq.cn/article/9974df9a229e5c28679c77773
1
2
3
4

# JS FileReader() 对象

  • *FileReader是一个可以读取文件的接口*,读取文件的内容,转换成一个字符串,可以用来读取本地文件,网络文件。
  • `https://developer.mozilla.org/en-US/docs/Web/API/FileReader/FileReader

# JS Image() 对象

/*  新建图片加入页面  */
new Image(100, 100); // Image(width, height)

var myImage = new Image(100, 200);
myImage.src = "picture.jpg";
document.body.appendChild(myImage);

/*  获取图片信息 高/宽  */
var img = new Image();
img.onload = function () {
  console.log("图像宽度:", this.width); // 页面渲染的图片高宽
  console.log("图像高度:", this.height); // 页面渲染的图片高宽
  console.log("图像固有宽度:", img.naturalWidth); // 原始图片高宽--未经style样式改变的高宽
  console.log("图像固有高度:", img.naturalHeight); // 原始图片高宽--未经style样式改变的高宽
};
img.src = "path_to_image.jpg";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# JS URL() 对象

JavaScript 中更安全的 URL 读写 (opens new window)

支持 Chrome 19+

  • 构建安全正确的 URL
const url = new URL("https://www.baidu.com");

// 使用 URL 对象构建 `string` url 能够有效避免 模板字符串 创建时(不经意)产生的空格

url.searchParams.set("model", "model");
url.searchParams.set("locale", "locale");
url.searchParams.set("text", "text");

url.searchParams.has("text"); // true
url.searchParams.get("text"); // 'text'
url.searchParams.delete("text");

url.href; // 'https://www.baidu.com/?model=model&locale=locale&text=text'
1
2
3
4
5
6
7
8
9
10
11
12
13
  • 解析 http 地址 (常用)
new URL('http://127.0.0.1:8080/copyrightCenter/copyRightManage?activeTabName=2')
{
hash: "",
host: "127.0.0.1:8080",
hostname: "127.0.0.1",
href: "http://127.0.0.1:8080/copyrightCenter/copyRightManage?activeTabName=2",
origin: "http://127.0.0.1:8080",
password: "",
pathname: "/copyrightCenter/copyRightManage",
port: "8080",
protocol: "http:",
search: "?activeTabName=2",
searchParams: "URLSearchParams {size: 1}",
username: "",
// [[Prototype]]: URL(),
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# JS XMLHttpRequest() 对象

function RawRequest({ url, method, headers }) {
  let XHR = new XMLHttpRequest();

  // # 方法使用
  XHR.onreadystatechange = (res) => {
    // do something
  };

  // # 事件绑定
  XHR.addEventListener("error", () => {});

  // 初始化请求
  XHR.open(method, url);

  // 设定 headers
  Object.keys(headers).forEach((key) => {
    XHR.setRequestHeader(key, headers[key]);
  });

  // 发送请求
  XHR.send(null);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# JS Math 对象

Math.random(); // 0 - 1 的随机数
Math.pow(num, pow); // 指数运算
Math.round(num); // 四舍五入
Math.ceil(num); // 取最近最大值整数
Math.floor(num); // 取最近最小值整数
1
2
3
4
5

# WebSocket

# HTTP

# 需求

# 不同情况下 函数参数 传入不同类型变量

之前想过,但是不建议这么操作;
typeof
instanceof
Object.propotype.toString.call() //结果格式 [Object string] 推荐使用
1
2
3
4

# 需求:文件上传

# 需求:图片上传

关于图片上传 完全可以单独讲 现在为方便就此处

- 直接上传
- 本地MD5生成 MD5API检测MD5识别重复
- 单独图片服务器OSS上传

- 关于传输中的 文件类型 & http 协议头Content-Type注意
- 流模式 / 指定文件mime type
- FormData 模式
1
2
3
4
5
6
7
在 web 应用程序中使用文件 File_API
https://developer.mozilla.org/zh-CN/docs/Web/API/File_API/Using_files_from_web_applications
Blob

File
FileReader
FileReaderSync

URL.createObjectURL()
URL.revokeObjectURL()

1
2
3
4
5
6
7
8
9
10
11

# 需求:大文件上传

# 需求:断点上传

# 需求: 压缩图片

  • 压缩为 base64 url 格式 base64 url 转为 文件

(opens new window)

  • export { compressImg };
    
    /**
     * 可对 单个或多个图片文件 进行压缩
     * @param {*} file 图片文件 (多个传入 [], 单个直传 file 对象 )
     * @param {*} quality 压缩比 ( 0.2 —— 0.5 为最佳实践压缩比);
     * @param {*} trigger_size 须小于 10*1024;触发压缩的图片文件大小(单位kB_二进制);
     * @returns {Object}
     *
     * @example
     * async () => {
     *  let res = await compressImg( origin_file , 0.52 , 2 * 1024)
     *  return res
     * }
     */
    function compressImg(file, quality = null, trigger_size = 1 * 1024) {
      const optimum_compression_ratio = 0.52; // 默认压缩比
      const file_origin_kb_size = (file.size / 1024).toFixed(2); // 查看图片原始大小(kb)
    
      // 判断环境是否支持canvas
      if (!isCanvasSupported()) {
        if (Object.prototype.toString.call(file) == "[object Array]") {
          return Promise.resolve(file);
        } else {
          return Promise.resolve({ file: file });
        }
      }
    
      if (!quality) {
        quality = optimum_compression_ratio;
      }
    
      // 如果是 file 为数组返回 Promise 数组
      if (file[0]) {
        return Promise.all(
          Array.from(file).map((e) => this.compressImg(e, quality))
        );
      }
      // 如果是 file 为对象进行压缩
      else {
        return new Promise((resolve) => {
          // 是否触发压缩--不满足直接返回原文件
          if (file_origin_kb_size < trigger_size) {
            resolve({ file: file });
          }
          // 满足压缩条件
          else {
            // 创建 FileReader
            const reader = new FileReader();
            // 双重解构拿到源文件的 base64 编码链接
            reader.onload = ({ target: { result: src } }) => {
              // 创建 img 元素
              const image = new Image();
              image.onload = async () => {
                const canvas = document.createElement("canvas"); // 创建 canvas 元素
                const context = canvas.getContext("2d");
    
                var targetWidth = image.width;
                var targetHeight = image.height;
                var originWidth = image.width;
                var originHeight = image.height;
    
                if (
                  1 * 1024 <= file_origin_kb_size &&
                  file_origin_kb_size <= 10 * 1024
                ) {
                  var maxWidth = 1600;
                  var maxHeight = 1600;
                  targetWidth = originWidth;
                  targetHeight = originHeight;
                  // 图片尺寸超过的限制
                  if (originWidth > maxWidth || originHeight > maxHeight) {
                    if (originWidth / originHeight > maxWidth / maxHeight) {
                      // 更宽,按照宽度限定尺寸
                      targetWidth = maxWidth;
                      targetHeight = Math.round(
                        maxWidth * (originHeight / originWidth)
                      );
                    } else {
                      targetHeight = maxHeight;
                      targetWidth = Math.round(
                        maxHeight * (originWidth / originHeight)
                      );
                    }
                  }
                }
                if (
                  10 * 1024 <= file_origin_kb_size &&
                  file_origin_kb_size <= 20 * 1024
                ) {
                  maxWidth = 1400;
                  maxHeight = 1400;
                  targetWidth = originWidth;
                  targetHeight = originHeight;
                  // 图片尺寸超过的限制
                  if (originWidth > maxWidth || originHeight > maxHeight) {
                    if (originWidth / originHeight > maxWidth / maxHeight) {
                      // 更宽,按照宽度限定尺寸
                      targetWidth = maxWidth;
                      targetHeight = Math.round(
                        maxWidth * (originHeight / originWidth)
                      );
                    } else {
                      targetHeight = maxHeight;
                      targetWidth = Math.round(
                        maxHeight * (originWidth / originHeight)
                      );
                    }
                  }
                }
    
                canvas.width = targetWidth;
                canvas.height = targetHeight;
                context.clearRect(0, 0, targetWidth, targetHeight);
                context.drawImage(image, 0, 0, targetWidth, targetHeight); // 绘制 canvas
    
                const canvasURL = canvas.toDataURL("image/jpeg", quality);
                const buffer = atob(canvasURL.split(",")[1]);
                let length = buffer.length;
                const bufferArray = new Uint8Array(new ArrayBuffer(length));
                while (length--) {
                  bufferArray[length] = buffer.charCodeAt(length);
                }
                const miniFile = new File([bufferArray], file.name, {
                  type: "image/jpeg",
                });
    
                let res_file = {
                  file: miniFile,
                  origin: file,
                  beforeSrc: src,
                  afterSrc: canvasURL,
                  beforeKB: Number((file.size / 1024).toFixed(2)),
                  afterKB: Number((miniFile.size / 1024).toFixed(2)),
                  quality: quality,
                };
                // // dev-log >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                // console.log('[Dev_Log][res_file]_>>>',res_file)
                resolve(res_file);
              };
              image.src = src;
            };
            reader.readAsDataURL(file);
          }
        });
      }
    }
    
    /**
     * 判断环境是否支持 canvas 画布
     * @returns {Boolean}
     */
    function isCanvasSupported() {
      // 创建一个 canvas 元素
      const canvas = document.createElement("canvas");
      // 检查浏览器是否支持 getContext 方法
      if (canvas.getContext && canvas.getContext("2d")) {
        return true;
      } else {
        return false;
      }
    }
    
    /**
     * 复制 File 对象
     * @param {*} originalFile
     * @returns {File}
     */
    function cloneFile(originalFile) {
      // 创建一个新的 Blob 对象,使用原始文件的内容
      const newBlob = new Blob([originalFile], { type: originalFile.type });
    
      // 创建一个新的 File 对象,使用原始文件的名称和新创建的 Blob 对象
      const clonedFile = new File([newBlob], originalFile.name, {
        type: originalFile.type,
      });
    
      return clonedFile;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179

# 需求:通过 图片连接 读取图片信息

  • (一)利用浏览器 window.performance 性能记录 API 读取图片文件大小
// # 利用浏览器 window.performance 性能记录API 读取图片文件大小
function readImgFileSizeFromUrlWithPerformance(_url) {
  if (!_url) return new Error("未输入图片链接");

  let Img = new Image();

  Img.onload = () => {
    // window.performance 的使用前提是“图片已经加载到页面中”
    let performanceEntries = window.performance.getEntriesByName(_url);

    if (performanceEntries.length) {
      let entry = performanceEntries[0];
      // // dev-log >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
      console.log(
        `[Dev_Log][${"编码后的大小(字节):"}_]_>>>`,
        entry.encodedBodySize
      );
      return entry.encodedBodySize; // unit is kb
    }
  };

  Img.src = _url;
  document.body.appendChild(Img);
}

readImgFileSizeFromUrlWithPerformance(
  "https://duolai-img.lizhibj.cn/dev/10000001/2024-03-27/019881A249D44CBF95B20008EB5F09B4.png?OSSAccessKeyId=LTAI5tANsomXiv4VQxqcgD8L&Expires=1711595779&Signature=%2BInM4pnnezUYzJc4xjPAPUCiEc0%3D"
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  • (二)利用 图片链接 发送网络请求来 读取图片文件大小 (读取返回的 Content-Length
    • 可使用 HEAD 请求是 HTTP 协议中的一种请求方法,它与 GET 请求非常相似,但有一个关键的区别:HEAD 请求不会获取实际的资源内容,而只会获取资源的元数据,包括响应头信息。
    • 但是要注意 跨域限制

# 监听全局 点击事件 的所有实现途径

  • 原生监听 鼠标 onmousedown (opens new window) 事件即可,可得到事件对象 e

  • vue 全局监听按钮点击事件 (opens new window) 需求:全局监听点击权限

    - 自定义指令 绑定 元素身上
    - 使用其 狗子 函数 隐现
    
    1
    2
  • 元素点击事件 el.click()

  • 移动端兼容的 元素触摸事件 touchstart **touchmove** **touchend** **touchcancel**

  • css 深度选择器 >>>

    • :deep {} // vue3
      ::v-deep {} //vue2
      >>> //vue2
      
      1
      2
      3
  • vuejs 渲染函数 & JSX (opens new window)

  • VNode--虚拟 DOM (opens new window)

  • 需求:拖动鼠标选择区域 爱奇艺

    - 鼠标(mouseEnter,mouseLeave,mouseDown,mouseUp)监听
    - 拖动框 实时 鼠标 移动 渲染
    - 拖动选中 -- 被选区域 动态样式 函数 判断
    - 点击选中 -- 传统逻辑
    - 视频播放器 底层逻辑 ?分方格渲染颜色
    
    1
    2
    3
    4
    5
  • 组件使用 v-model (opens new window)

  • 组件 model 属性 (父子组件传值的响应式改变)

    • <Child v-model="defaultPropName"></Child>
      
      1
    • // child.vue
      {
          props:{
              defaultProp:{type:Array,default:()=>[]}
          },
          model:{
              prop:"defaultProp",
              event:"change"
          }
          methods:{
              itemChange(val){
                  this.$emit("change",val)
              }
          }
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
  • 需求:时间选择器(time,date)

- 格式: YYYYMM-DD / HH-MM
- component model 调用简化 响应式逻辑
1
2
  • scrollIntoView 页面滚动

    • el.scrollIntoView() 调用 -- 将 元素 el 滚动 指定滚动区域的 那个位置 (默认:元素的顶端将和其所在滚动区的可视区域的顶端对齐)

    • https://blog.csdn.net/learn8more/article/details/108047794

    • https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollIntoView

      可用于 验证提示
      
      1

# 需求:div自定义编辑器

# 需求:视频播放器(video 标签)

<video><video/>
1

# 需求:鼠标悬浮 前进后退 播放视频 播放器(video 标签)

# 需求:获取 视频 第一帧 作为封面

  • 核心代码 亦可 作为 图片转 Base64 压缩使用

  • https://blog.csdn.net/qq_42038623/article/details/129662532

    /**
    	* @param {HtmlElementNode} video _videoEl
    	* @return {String} imgUrl base64_image_url
    */
    videoScreenshot(video){
        let imgUrl = null;
        video.currentTime = 2; // 第一帧
        video.oncanplay = () => {
            let canvas = document.createElement('canvas');
            let ctx = canvas.getContext('2d'); // 绘制2d
            canvas.width = video.clientWidth; // 获取视频宽度
            canvas.height = video.clientHeight; // 获取视频高度
            // 利用canvas对象方法绘图
            ctx.drawImage(video, 0, 0, video.clientWidth, video.clientHeight);
            // 转换成base64形式
            imgUrl = canvas.toDataURL('image/png');
            // console.log('imgUrl :>> ', imgUrl);
        };
        return imgUrl
    },
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
  • 通过视频 url 读取视频信息

  • canvas 学习

  • https://www.twle.cn/l/yufei/canvas/canvas-basic-image-drawimage.html

    • void ctx.drawImage(image, dx, dy, dWidth, dHeight);
      
      1
    • 说明
      image 绘制到画板的图像资源,可以是任何的 canvas 图像源 ( CanvasImageSource),例如:HTMLImageElement,HTMLVideoElement,或者 HTMLCanvasElement
      dx 绘制图像时起点的 X 轴位置
      dy 绘制图像时起点的 Y 轴位置
      dWidth 在目标画布上绘制图像的宽度。 允许对绘制的图像进行缩放,如果不传递,绘制图像 如果不说明, 在绘制时图片宽度不会缩放
      dHeight 在目标画布上绘制图像的高度。 允许对绘制的图像进行缩放。 如果不说明, 在绘制时图片高度不会缩放
  • Vue 数据字典

https://blog.csdn.net/Luceyyy/article/details/120901453
https://jddke.blog.csdn.net/article/details/109387922
1
2
png黑白格背景图(预览虽然只有两格、但渲染时会自动填充黑白格):
background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC");
1
2

# 需求:关键词识别

  • 有个 输入框 ,以空格为断字符,识别输入的多个关键词

  • 如:

  • // textarea 输入
    sam 19 male http://www.sasa.com sam21 19 female http://www.sas32a.com
    
    // 输出
    [
        {name:'sam',age:19,gender:'male',blog:'http://www.sasa.com'}
        {name:'sam21',age:19,gender:'female',blog:'http://www.sas32a.com'}
    ]
    
    1
    2
    3
    4
    5
    6
    7
    8
  • UN

  • 需求:vue 基于 动态路由 生成 页面

  • 需求:富文本编辑器 wangeditor

  • 需求:自定义输入框文本编辑器 掘金输入

  • 需求:扫码登录 vue-qr

    • https://www.npmjs.com/package/vue-qr
    • 验证登录
  • 需求 **二维码和背景图片合成海报二维码下载到本地** vue-qr 和 html2canvas

    • https://github.com/niklasvh/html2canvas
  • JS new Map 对象

    • 破除 Object 只能 以 字符串格式的 键值对 形式 存储数据,可使用 对象 作为键
  • JS 弹出下载对话框以及实现常见文件类型的下载 (opens new window)

    • a 标签点击下载 (设置download属性

    • //创建下载元素
      /**
       * @description 通用下载方法
       * @param {String} content
       * @param {String} fileName
       */
      export function createDownLoadClick(content, fileName) {
        const link = document.createElement("a");
        // encodeURI -- 把字符串作为 URI 进行编码
        link.href = encodeURI(content);
        fileName && (link.download = fileName); //fileName 存在才执行
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
  • 保存文件 file-saver 插件

  • JS 构造函数 写法 -- 原型链 属性及 函数处理

    • 私有 处理
  • 脚手架搭建

    • vue+webpack
    • vuecli
    • vue + vite
    • react + vite/webpack
  • 放大缩小元素

    • 点击拖拽(鼠标变为对应箭头)放大缩小 un
    • 滚轮放大缩小
      • https://blog.csdn.net/weixin_43245095/article/details/107972629
  • 模拟 api 数据 mock 服务后端脚手架

  • 浏览器指纹 un

  • elui 表格

    • 合并行或列 https://element.eleme.cn/#/zh-CN/component/table#he-bing-xing-huo-lie
    • 树形数据
  • 浏览器打印

    • 修改弹出的 iflame 样式

    • printjs 插件 https://printjs.crabbly.com/

      • 打印 HTML https://blog.csdn.net/weixin_47180815/article/details/124423104

        • 若使用Print.js 打印HTML,里面的图片没有加载出来,肯定是图片还没有完全加载完,就执行了打印方法

          • 解决思路:延时执行打印

          • function myprintDetails() {
              // // temp-testlog
              console.log("test-printJS");
            
              //   let printJson = [{
              //     a:"ssa",
              //     c:'cdcd'
              //   }]
            
              // for (let index = 0; index < 60; index++) {
            
              //   printJson.push(printJson[0])
              // }
              let style = `@media print {
                @page {
                  size: A4 portrait;
                  margin-top: 0mm;
                  margin-bottom:0mm;
                }
              }
              .info{
                display: flex!important;
                justify-content: space-around;
              }
              `;
              let div = null;
              new Promise((resolve, reject) => {
                div = document.createElement("div");
                div.id = "printDOMID";
                div.style = `
                    position: absolute;
                    top: 0;
                    right: 0;
                    z-index: -999;
                  `;
                // https://www.runoob.com/try/demo_source/pineapple.jpg
                let imgsrc = require("C:/Users/Two/Downloads/doodle.png");
                div.innerHTML = `
                    <h3>runoob</h3>
                    <img src='${imgsrc}' alt='boo' />
                    <div class='info'>
                      <div class="el-descriptions__title">打印时间</div>
                      <div class="el-descriptions__extra">打印人</div>
                    </div>
                  `;
            
                document.querySelector("body").appendChild(div);
                // 等待 图片(原生图片加载是异步的) 加载完成
                setTimeout(() => {
                  resolve();
                }, 1000);
                console.log("test-promiseStart");
              })
                .then(() => {
                  printJS({
                    printable: "printDOMID",
                    // type:'json',
                    type: "html",
                    // type:'image',
                    // properties:[{field: 'a', displayName: '地区', columnSize: `25%`},{field: 'c', displayName: '地区', columnSize: `75%`}],
                    // properties:['a','c'],
                    documentTitle: "sasasa",
                    header: "null",
                    headerStyle: "font-weight: bold;",
                    style: style,
                    onLoadingStart() {},
                    onError(err) {
                      // // temp-testlog
                      console.log("test-error", err);
                    },
                    onLoadingEnd() {
                      div.remove();
                      // // temp-testlog
                      console.log("test-end");
                    },
                  });
                })
                .catch((err) => console.log(err))
                .finally(() => {
                  // div.remove()
                  console.log("test-remove");
                });
            }
            
            1
            2
            3
            4
            5
            6
            7
            8
            9
            10
            11
            12
            13
            14
            15
            16
            17
            18
            19
            20
            21
            22
            23
            24
            25
            26
            27
            28
            29
            30
            31
            32
            33
            34
            35
            36
            37
            38
            39
            40
            41
            42
            43
            44
            45
            46
            47
            48
            49
            50
            51
            52
            53
            54
            55
            56
            57
            58
            59
            60
            61
            62
            63
            64
            65
            66
            67
            68
            69
            70
            71
            72
            73
            74
            75
            76
            77
            78
            79
            80
            81
            82
            83
      • 打印 JSON https://blog.csdn.net/GIAAKK/article/details/126978286 http://www.360doc.com/content/12/0121/07/12185854_1080531322.shtml

    • 不要页眉脚 https://blog.csdn.net/qq_42351675/article/details/124398995

      • printJS({
          printable: "printDOMID",
          type: "html",
          header: "null",
          headerStyle: "font-weight: bold;",
          // 设置以下style
          // style:`@media print {
          //   @page {
          //     margin-top: 0mm;
          //     margin-bottom:0mm;
          //   }
          // }`,
        });
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
      • 可以在打印设置中关闭

  • typora 图床上传

  • ELUI

    • el-tree 设置的坑

      • !注意父子联动
        方法:setChecked 回显数据使用方法 setChecked(v, true, false); (!不要用其他)
        方法:getCheckedKeys,主动获取现在被选中的数据方法
        事件:check,当复选框被点击的时候触发	共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
        
        1
        2
        3
        4
    • table load 懒加载的坑 (:load='handleload'

      • handleload(row,treeNode,resolve){}
        // resolve 的回调 有时候 无法有效更新
        
        
        loadChild(tree, treeNode, resolve) {
            this.resolveMap[tree.id] = resolve;
            list({ pid: tree.id }).then((res) => {
                // 解决目录下只有 一个目录时 的删除情况 列表更新
                // 防止新增成功不自动回显展开箭头(无子级目录的父目录__一开始未收录其 resolve 数据回填函数__即未有展开箭头),
                if (tree.id && this.resolveMap[tree.id]) resolve(res.data);
                // 兼容处理:主动更新 原生EL-table组件 中储存的懒加载数据
                this.$set(
                    this.$refs.catalogTable.$refs.tableElRef.store.states.lazyTreeNodeMap,
                    tree.id,
                    res.data,
                );
            });
        },
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
  • vue 拖拽组件 draggable

    • vue2 vue.draggable https://www.itxst.com/vue-draggable/tutorial.html
    • vue3 vue.draggable.next https://www.itxst.com/vue-draggable-next/tutorial.html
  • Javascript 中 ?. 运算符和 ?? 运算符

    • https://blog.csdn.net/qq_40146789/article/details/124124768

    • ?? 左侧变量的值为undefinednull时,才会取右侧变量的值,否则取左侧变量的值。
      
      1
  • vue .sync 数据流 更新 https://blog.csdn.net/weixin_46719229/article/details/119850803

    • <SonComp :title.sync="title"></SonComp>
      data(){return { title:'hi' }}
      
      1
      2
    • <div @click="$emit('update:title', 'newTitle')">
          {{ title }}
      </div>
      prop:['title']
      
      1
      2
      3
      4
  • Vue (组件通信)数据流更新方式

  - prop 直传 - 单向数据流
  - emit 子组件调用 (父组件函数接收)
  - .sync 修饰符 (或者 "update:property"- 实现父子共享数据响应式
  - 子组件 model 钩子函数 配合 v-model - 实现父子共享数据响应式 - (上方已记录)
  -	依赖注入 provide/inject (非响应式)
  - 本地缓存
  - VueX - (VueX是Vue定制)
1
2
3
4
5
6
7
  • Vue $dispatch 和 $broadcast 详解 (vue 1.0 的 API,之后版本已经废弃)

  • String.padStart(x,'0')

    • **padStart()**方法用另一个字符串填充当前字符串(重复,如果需要的话),以便产生的字符串达到给定的长度。填充从当前字符串的开始(左侧)应用的。
    • https://www.jianshu.com/p/abe66e38645e
  • moment

moment().format("YYYY年MM月DD日"); //中文年月日
1
  • 随机字符串
/**
 * 随机生成指定位数字符串
 * @param {*} length
 * @returns
 */
function generateRandomString(length) {
  var result = "";
  var characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * characters.length));
  }

  return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 需求:vue 3 渲染函数 basestatus
  • 富文本注册引入

1
  • Reflect.ownKeys() & Object.keys() 遍历数组

  • JS structruedClone 拷贝函数

    • 谨慎使用,可使用的浏览器环境版本太高 chrome98 以上
  • JS 身份证验证

    • //两种 15位 18位
      const card15 =
        /^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}[0-9Xx]$/;
      const card18 =
        /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
      if (card15.test(val) || card18.test(val)) {
        return true;
      } else {
        return "请输入合法身份证号码";
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
  • 某个元素查看有没有指定的父元素 (opens new window)

    • mounted() {
        document.addEventListener("click", (e) => this.fintParent(e));
      },
      methods: {
        fintParent(e) {
          const clickNode = e.srcElement;
          let parent = clickNode.parentNode;
          while (parent) {
            if (
              parent.classList &&
              (parent.classList.contains("dropdownWrap") ||
                parent.classList.contains("p_more-service"))
            ) {
              break;
            }
            parent = parent.parentNode;
          }
          if (!parent) {
      		// do nothing
          }
        }<br>}
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
vue
ui ( https://segmentfault.com/a/1190000019826020 )
	组件构建环境、BEM、button、
     约束好z-index使用

admin
Vue3 源码

bili 抽奖小程序 (自动获取抽奖列表,
    类似:https://github.com/shanmiteko/LotteryAutoScript
)
- 类似多多客 嘉琪code
- 视频处理 g

反 核废水 宣传网站 (一个button收集赞👍)

- 封面处理工具--实际上j
	  - 下载-自动取封面,自动生成封面,自动生成文案
	封面:
       - 上传图片
       - 输入文字,生成水印图片,选择位置
       - 图片透明度,灰度调节
    - KeepFit -- 左上角,圆型 (黑底白字,红字)
    - title -- 中间 (白色立体,shadow文字)

- blog 文章下载器 (类似 CSDN 掘金 ==》 下载为md格式的文章)

- code展示组件库

- keepFit 有透明度



mubu 文章
- 表格
- 代码块区域

- el-popover code
- admin layout
- 树形选择
- 自定义列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  • 前端 录制页面用户操作 https://mp.weixin.qq.com/s?__biz=Mzg2NjY2NTcyNg==&mid=2247490043&idx=1&sn=83e2c1b82b61529c8eb1248d7a175d6f&chksm=ce460c6af931857cb640a356fdd8cb2b6948b9c05002a1abb16d07432fed76a74ed1f5859ae0#rd

  • 创建本地预览链接

    • URL createObjectURL
    • FileReader readAsDataURL
    • Base64

react 转 vue

文件关系引用图谱

debox - applet

抽奖

rocket land game

JS 星图


  • 小果视界管理端

小果视界 移动端 -- APP 推广页

小果视界 Admin 首页可视化数据 -- 图表

小果视界 Admin banner 配置

小果视界/力推 Admin 渠道管理

小果视界 发布视频 管理

  • 力值广告平台

力值 首页数据可视化--商务组长/投顾--展示

力值 CID--淘宝链路

力值 图片库 -- 原始库 / 批量合成

力值 爱奇艺 -- 广告计划层级 创建

韶华 -- 广告计划 UI 搭建

  • 推小果管理平台

新增推广项目 飞卢,起点,头条,悟空浏览器,抖音故事

爆文/关键词/发布作品

结算/提现

  • 关键词识别 悟空 关键词 特定 (文字转按钮)
    • 增加 中间枚举 转换
    • 多关键词 识别失效 -- 使用冒号截取了 错误截取 链接的 https:// 导致链接被截取成立两段

KOC 推小果 管理端

  • 七猫,百度

小果视界

  • 网盘链接
  • 小程序推广 - 抖音任务

小果繁星

  • 关键词推广
    • 内容管理
    • banner 配置
  • 商务
    • 项目产品
    • 会员卡政策
    • 返利政策
  • 财务
    • 收益明细
    • 关键词结算
    • 结算会员佣金
  • 设置
    • 移动端目录配置
    • 消息管理
/**
 * 绑定页面事件监听
 * @param {*} evtName    监听事件名称
 * @param {*} elId       id or className
 * @param {*} _callback  回调执行函数(接收事件对象 event)
 * @returns {function} 取消监听函数
 */
export function handleListenPageScoll(evtName, elId, _callback) {
  // 目标元素
  // let targetEl = window;
  let targetElList = document.querySelectorAll(elId);

  if (targetElList && targetElList?.length) {
    targetElList.forEach((item) => {
      // 执行监听页面滚动事件
      item.addEventListener(evtName, _callback);
    });

    // 返回取消监听函数对象
    return function () {
      targetElList.forEach((item) => {
        // 执行监听页面滚动事件
        item.removeEventListener(evtName, _callback);
      });
    };
  } else {
    return function () {};
  }
}

function handleScrollElTrigger(_e) {
  var scrollTop = _e.target.pageYOffset || _e.target.scrollTop;
  if (scrollTop <= 628) {
    pageScrollPosition.value = false;
  } else {
    pageScrollPosition.value = true;
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 工程化

# Webpack核心

# 性能优化

# 编译过程

  • WebPack

  • 项目性能优化

  • 编译过程原理


菜单管理 -- 是否控制APP 菜单
1
  • 权限配置 统一定义在 大文件夹下

  • 搜索配置 定义和重置 -- 封装为组件外部函数-调用-减少重复代码

  • 输入类型 修饰符 v-model.lazy.trim去空格

  • 组合请求 参数时 深拷贝 一份

  • 使用 el-checkbox-group 不显示

    • <el-checkbox-group>
        <el-checkbox label="工具使用"></el-checkbox>
        <el-checkbox label="变现课程"></el-checkbox>
        <el-checkbox label="邀请佣金"></el-checkbox>
        <el-checkbox label="领取视频"></el-checkbox>
      </el-checkbox-group>
      
      1
      2
      3
      4
      5
      6

从 页面 到 组件

组件库优化

  • 下载模板,检索下拉兼容

原生组件 bug

  • tree 获取子叶节点的操作 最好使用 method 来主动提取
  • table tree lazy_load,懒加载时子项(子项数据层更新后)UI 可能不会更新
  • el-input[v-model.number] 使用修饰符输入 . 时后面不能输入 0,否则被截除

1

# Vue

# UNI-APP

  • 注意事项
// uniAPP & Vue2 

WXMP UI自定义组件 写class类将不会被编译🐞

uniapp 不能使用 动态组件 component
uniapp 非pages.json注册页面 无法使用 uniapp 的页面周期钩子🐞
uniapp 非pages.json注册页面组件 created 钩子可能拿不到 prop 参数
uniapp data 注册变量 不要用私有私有属性($ _)声明

1
2
3
4
5
6
7
8
9

# 安全

  • 注入攻击

# 其他

  • 虚拟表格 (大数据加载)