首页 Web前端
文章
取消

Web前端

Owner: Olimi tags: 技术整理 date: 2023年7月25日 16:37 status: Published summary: 本文介绍了JavaScript中的函数原型、扩展运算符、React Hooks和Ant Design等内容,同时也提到了一些工程问题的解决方案,如WebStorm的自动pretty和eslint、缓存问题等。 type: Post

学习资料:

参考所用前端ant design pro中给出的学习路线。使用mdn的web教程。

教程:

Reference:

工具:

知识栈:

  • web基础:html、css、js
  • nodejs以上:npm、yarn等包管理、ts
  • 前端框架:vue、react
  • 打包工具:webpack等

JS学习理解

面向对象

  1. 一切皆对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
     // 一切皆对象的理解。本质上,对象是一种数据结构,它将数据和功能绑定在一起。
     // 所谓的原型,不是class的概念。仍然是对象,对应一个数据结构。
     let first_prototype = {
         a: 1,
         hello: function () {
             console.log('hello world');
         }
     }
        
     const first = Object.create(first_prototype)
     console.log(first.a) // 1
     first.hello() // hello world
        
     first_prototype.a = 2
     first_prototype.hello = function () {
         console.log('hello javascript')
     }
        
     first.hello() // hello javascript
        
     const second = Object.create(first_prototype)
     console.log(second.a) // 2
     second.hello() // hello javascript
    

    核心的理解:对象与原型对象之间,都是通过组合关系绑定到一起。

  2. 构造函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
     // 构造函数的理解
     function F() {
         console.log('hello world');
     }
        
     console.log(F.prototype.constructor === F) // true
        
     ff = new F()
        
     console.log(Object.getPrototypeOf(ff) === F.prototype) // true
        
     Object.getPrototypeOf(ff).constructor() // hello world
    

    理解:

    在 JavaScript 中,每个函数都有一个默认的 prototype 属性,它是一个空对象。当你创建一个新的函数时,JS 引擎会为该函数自动创建一个默认的 prototype 对象,并且为这个对象添加一个 constructor 属性,该属性指向这个函数本身。也就是说,Foo.prototype.constructor === Foo。 可以使用 Object.getPrototypeOf(obj) 方法或者 obj.proto 属性来获取一个对象的原型。因为 prototype 对象也是普通对象,所以它也有原型。在 JavaScript 中,通常将对象的原型称为 proto,因为这个属性实际上是 ECMAScript 规范中定义的内部属性,不过现在它已经成为了 JS 的标准特性之一。

    new的时候就是通过该函数对应的prototype 对象,调用其中的constructor 函数。这个constructor默认就是该函数,但可以自行修改为别的,或者直接自定义一个新的prototype。

    所以定义的函数,也能称为构造函数,按照标准,定义成构造函数的,要大写开头。对构造函数直接调用也会显示warning,Constructor call without new。

知识点

  • …介绍和使用

    扩展运算符 ... 是一种 JavaScript 语法,用于将一个可迭代对象(如数组、字符串、对象等)展开成一个更长的序列。它可以用于函数调用、数组字面量、对象字面量等多种场合。

    下面介绍几种常见的使用方式。

    1. 用于函数调用

    在函数调用时,扩展运算符可以将一个数组展开成一个参数序列。例如:

    1
    2
    3
    4
    5
    6
    7
    
      function myFunc(a, b, c) {
        console.log(a, b, c);
      }
        
      const arr = [1, 2, 3];
      myFunc(...arr); // 输出:1 2 3
        
    

    上面的代码中,...arr 将数组 arr 展开成参数序列,相当于直接调用了 myFunc(1, 2, 3)

    1. 用于数组字面量

    在数组字面量中,可以使用扩展运算符将一个数组展开成另一个数组的一部分。例如:

    1
    2
    3
    4
    5
    
      const arr1 = [1, 2, 3];
      const arr2 = [4, 5, 6];
      const arr3 = [...arr1, ...arr2];
      console.log(arr3); // 输出:[1, 2, 3, 4, 5, 6]
        
    

    上面的代码中,...arr1...arr2 将两个数组展开成了新数组 arr3 的一部分。

    1. 用于对象字面量

    在对象字面量中,可以使用扩展运算符将一个对象展开成另一个对象的一部分。例如:

    1
    2
    3
    4
    5
    
      const obj1 = { a: 1, b: 2 };
      const obj2 = { c: 3, d: 4 };
      const obj3 = { ...obj1, ...obj2 };
      console.log(obj3); // 输出:{ a: 1, b: 2, c: 3, d: 4 }
        
    

    上面的代码中,...obj1...obj2 将两个对象展开成了新对象 obj3 的一部分。

    1. 用于解构赋值

    在解构赋值中,可以使用扩展运算符将一个数组或对象的一部分解构出来。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    
      const arr = [1, 2, 3, 4];
      const [a, b, ...rest] = arr;
      console.log(a, b, rest); // 输出:1 2 [3, 4]
        
      const obj = { a: 1, b: 2, c: 3, d: 4 };
      const { a, b, ...rest } = obj;
      console.log(a, b, rest); // 输出:1 2 { c: 3, d: 4 }
        
    

    上面的代码中,...rest 将数组或对象的一部分解构出来,并赋值给变量 rest

    扩展运算符是一种方便实用的语法,可以简化代码,提高代码的可读性和可维护性。在实际开发中,建议根据需要使用扩展运算符,以提高代码的效率和质量。

  • 区分{}和[],前者是一个对象,后者是一个数组!

小的问题

  1. string to date。竟然没有很好的转换,可以自己设置格式那种,要自己手写。讨论here

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
     function parseDateString(dateString: any) {
       const year = dateString.slice(0, 4);
       const month = dateString.slice(4, 6) - 1;
       const day = dateString.slice(6, 8);
        
       return new Date(year, month, day);
     }
     // 20230606 to
     // item_date:  2023-06-05T16:00:00.000Z
    

React

Hook

教程:React Hooks 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)

hook ref:Built-in React Hooks – React — React 内置的 Hooks。

组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。 组件的最佳写法应该是函数,而不是类。

Hook就是解决纯函数不能包含状态,也不支持生命周期方法的问题。

所有的钩子都是为函数引入外部功能,所以 React 约定,钩子一律使用use前缀命名,便于识别。你要使用 xxx 功能,钩子就命名为 usexxx。

内置的钩子

  1. useState - 用于在函数组件中添加状态管理。
  2. useEffect - 在组件渲染后执行副作用操作,例如订阅数据、发送网络请求等。
  3. useContext - 用于在组件树中共享数据。
  4. useReducer - 用于管理复杂的状态逻辑。
  5. useCallback - 用于缓存函数并避免不必要的重新渲染。
  6. useMemo - 用于缓存计算结果并避免不必要的重新计算。

比如useState,示例:

1
2
3
4
5
6
7
8
9
10
11
import React, { useState } from "react";

export default function  Button()  {
  const  [buttonText, setButtonText] =  useState("Click me,   please");

  function handleClick()  {
    return setButtonText("Thanks, been clicked!");
  }

  return  <button  onClick={handleClick}>{buttonText}</button>;
}

useState()这个函数接受状态的初始值,作为参数,上例的初始值为按钮的文字。该函数返回一个数组,数组的第一个成员是一个变量(上例是buttonText),指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是set前缀加上状态的变量名(上例是setButtonText)。

接口示例:

  1. useState

接口:

1
const [state, setState] = useState(initialState);

返回值:

  • state:当前状态的值。
  • setState:更新状态的函数。
    1. useEffect

接口:

1
useEffect(effectFunction, depsArray);

返回值:

  • 无。

ant design

  1. ant design pro: 开箱即用的中台前端/设计解决方案 - Ant Design Pro
  2. ant design:https://ant.design/components/overview-cn/
  3. pro-components: https://procomponents.ant.design/components
  4. umi: https://v3.umijs.org/zh-CN/docs

使用:

  1. 面包屑:可以直接套用PageContainer,自动生成。

ProTable使用问题:

  1. ant protable 选择一行就会全选。原因:没有设置好rowKey,所以每行数据不能唯一标识。解决:设置rowKey=”name”。

工程问题

  1. webstrom启用自动pretty和eslint

    选择 “Languages & Frameworks” -> “JavaScript”(或者 “TypeScript”,如果你在 TypeScript 项目中使用 Prettier)。

    选择 “Prettier” 选项卡,然后选择 “Prettier package” 为 “Local”,并指定 Prettier 的安装路径。选择auto自动找路径即可。

    找到 “Languages & Frameworks” -> “JavaScript” -> “Code Quality Tools” -> “ESLint”。

  2. JB系软件。一段时间后,无法从系统粘贴板中读取进行粘贴。解决方案:在IDE中重新Ctrl+C复制一点东西就正常了。讨论:here
  3. 前端的大坑,缓存问题。UMI+MSFU热更新,经常出现更新了代码加载不出来(特别是代码更新到使用的API)。不行就删掉.umi文件夹,然后重新生成。

    “Module ‘xxx‘ does not exist in container“

  4. 基于MSFU等可以实现热更新,但是有时候代码更新了却看不到新的结果。记得用Ctrl+F5强制刷新缓存。
  5. 跨域请求:前端向不同的域(协议、域名、端口不同)发送请求(XHR、fetch),触发浏览器的同域策略判断。需要后端返回orign告诉浏览器前端的域是被允许的。参考here

    后端使用spring直接添加一个注释在控制器中:

    1
    
     @CrossOrigin(origins = "http://localhost:8000", maxAge = 3600, allowCredentials = "true")
    
本文由作者按照 CC BY 4.0 进行授权

WSGI

工程问题