Vue3 JSX

  1. Dialog.confirm({
  2. title: "课程名称",
  3. message: () => {
  4. return h(
  5. h(CellGroup),
  6. h(Field, {
  7. modelValue: groupInfo.value.title,
  8. "onUpdate:modelValue": (value) => (groupInfo.value.title = value),
  9. label: "群名称",
  10. placeholder: "请输入新的群名称",
  11. })
  12. );
  13. },
  14. })
  15. .then(async () => {
  16. await handleEditGroupTitle();
  17. })
  18. .catch(() => {
  19. // on cancel
  20. });

Typescript

值为空或者类型不同

类型守卫

  1. // in关键字,检测是否改属性
  2. if ("startDate" in emp) {
  3. console.log("Start Date: " + emp.startDate);
  4. }
  5. // typeof关键字,判断是否是该类型
  6. if (typeof padding === "number") {
  7. return Array(padding + 1).join(" ") + value;
  8. }
  9. if (typeof padding === "string") {
  10. return padding + value;
  11. }
  12. // instanceof 关键字
  13. interface Padder {
  14. getPaddingString(): string;
  15. }
  16. class SpaceRepeatingPadder implements Padder {
  17. constructor(private numSpaces: number) {}
  18. getPaddingString() {
  19. return Array(this.numSpaces + 1).join(" ");
  20. }
  21. }
  22. class StringPadder implements Padder {
  23. constructor(private value: string) {}
  24. getPaddingString() {
  25. return this.value;
  26. }
  27. }
  28. let padder: Padder = new SpaceRepeatingPadder(6);
  29. if (padder instanceof SpaceRepeatingPadder) {
  30. // padder的类型收窄为 'SpaceRepeatingPadder'
  31. }
  32. // 自定义类型保护的类型谓词
  33. function isNumber(x: any): x is number {
  34. return typeof x === "number";
  35. }

值为空

  1. // 值为空 情形一
  2. if (timeValue.value) {
  3. editCalendarData.value.time_begin = moment(timeValue.value[0]).valueOf();
  4. editCalendarData.value.time_end = moment(timeValue.value[1]).valueOf();
  5. }
  6. // 值为空 情形二
  7. queueStatusPhraseMap[status] ?? status

前端数据对象类型注解

可以使用type或者interface两种方式

  1. // 类型定义形式
  2. export type SingalObj = {
  3. signalName: string;
  4. name: string;
  5. }
  6. // 接口形式
  7. export interface {
  8. signalName: string;
  9. name: string;
  10. }

ES5/ES3 中的异步函数或方法需要 “Promise” 构造函数。请确保具有一个 “Promise” 构造函数的声明,或在 “—lib” 选项中包含了 “ES2015”

在tsconfig.json中配置lib

  1. {
  2. "compilerOptions": {
  3. "lib": [
  4. "ES2015"
  5. ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
  6. },
  7. }

异步行为

onchange事件后只处理最后一次请求的数据

  1. // 全局请求数据锁
  2. let currentRequestId = 0;
  3. /**
  4. * 获得搜索后数据
  5. */
  6. const getSearchData = async () => {
  7. const id = ++currentRequestId;
  8. getConceptSearchDataApi({
  9. keyword: search.value,
  10. }).then((r) => {
  11. // 只处理最后一次数据请求
  12. id === currentRequestId && timeFormat(r);
  13. });
  14. };

DOM

滚动事件监听

父元素为以下几种情况下不能直接监听事件:

  • overflow : hidden
  • 未超出父元素长度

使用以下方式解决

  1. window.addEventListener(
  2. 'scroll',
  3. () => {
  4. console.log('scroll');
  5. },
  6. true,
  7. );

CSS

a :visited

浏览器记录中访问过的URL都会被标记为 :visited,如果有其他的需求需要与后端配合与接口配合或者由前端使用sessionStorage实现。

大列表渲染卡顿

滚动获取数据节流

  1. import { debounce } from 'lodash-es';
  2. const box = document.querySelector('.intimenews-box');
  3. // 网页被卷去的高
  4. let winScrollTop = 0;
  5. //网页正文全文高
  6. let winHeight = 0;
  7. // div被卷去的高度
  8. let boxScrollY = 0;
  9. const getnewintimenews = debounce(async () => {
  10. await getInTimeNews(16, 'down');
  11. // .then(() => {
  12. oldWinHeight.value = document.body.scrollHeight;
  13. // });
  14. }, 80);
  15. // 轮询获取数据
  16. timer = setInterval(async () => {
  17. // 判断滚动后的
  18. await getInTimeNews(16, 'up');
  19. winScrollTop = document.body.scrollTop;
  20. winHeight = document.body.scrollHeight;
  21. if (winScrollTop > 0) {
  22. document.body.scrollTop = winHeight - oldWinHeight.value + winScrollTop;
  23. oldWinHeight.value = winHeight;
  24. }
  25. boxScrollY = box.getBoundingClientRect().y;
  26. }, 2000);
  27. //滚动后获取新数据
  28. document.body.addEventListener(
  29. 'scroll',
  30. () => {
  31. winScrollTop = document.body.scrollTop;
  32. winHeight = document.body.scrollHeight;
  33. boxScrollY = box.getBoundingClientRect().y;
  34. if (boxScrollY < 0) {
  35. getnewintimenews(16, 'down');
  36. }
  37. },
  38. true,
  39. );

禁止vue监听

  1. const data = Object.freeze((await getDataApi()).data);

Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;也不能添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举型、可配置性、可写性,以及不能修改已有属性的值。

如果你有一个巨大的数组或者对象,并且确信数据不会修改,使用 Object.freeze() 可以让性能大幅提升。这种提升大约有5~10倍,倍数随着数据量递增。对于纯展示的大数据,都可以使用 Object.freeze 提升性能。Object.freeze() 冻结的是值,你仍然可以将变量的引用替换掉。

纯函数

  • 此函数在相同的输入值时,需产生相同的输出。函数的输出和输入值以外的其他隐藏信息或状态无关
  • 此函数不能有语义上可观察的函数副作用
    1. let a = 2
    2. function add(b) {
    3. const total = a + b
    4. return total
    5. }
    6. console.log(add(1, 3))

    副作用

    副作用指的是函数在执行过程中,除了返回可能的函数值之外,还对主调用函数产生附加的影响。
    例如:修改了全局变量、修改了传入的参数、甚至是 console.log(), ajax 操作,直接修改 DOM,计时器函数,其他异步操作,其他会对外部产生影响的操作都是算作副作用。
    1. let a = 2
    2. function add() {
    3. a = 3
    4. }
    5. console.log(add())
    我们运行上面的add函数,外部的变量a的值发生了改变,这就产生了副作用

    Tips:console.log 也被称为副作用是因为它们会向控制台打印日志,控制台存在于函数外部

字段验证

  • 所有字段必须使用对应的类型,一般为 datestringnumber
  • 在number类型时,值绑定使用 :value.number 修饰符,有些时候(eg:select元素)即使使用number修饰符也未必得到number类型这时需要强制类型转换。

    参考

    【1】关于useEffect清除副作用