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教程。
教程:
- ant design pro: 开箱即用的中台前端/设计解决方案 - Ant Design Pro
- antd:https://ant.design/components/overview-cn
mdn guide: [学习 Web 开发 MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Learn) - 阮一峰老师es6:es6tutorial/sidebar.md at gh-pages · ruanyf/es6tutorial (github.com)
- React Hooks 入门教程 - 阮一峰的网络日志 (ruanyifeng.com)
Reference:
- typescript: 文档简介 · TypeScript中文网 · TypeScript——JavaScript的超集 (tslang.cn)
- react:React
- Built-in React Hooks – React — React 内置的 Hooks。
工具:
- 支持react的在线编辑器:codesandbox.io
知识栈:
- web基础:html、css、js
- nodejs以上:npm、yarn等包管理、ts
- 前端框架:vue、react
- 打包工具:webpack等
JS学习理解
面向对象
一切皆对象
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
核心的理解:对象与原型对象之间,都是通过组合关系绑定到一起。
构造函数
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 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 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 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 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。扩展运算符是一种方便实用的语法,可以简化代码,提高代码的可读性和可维护性。在实际开发中,建议根据需要使用扩展运算符,以提高代码的效率和质量。
区分{}和[],前者是一个对象,后者是一个数组!
小的问题
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。
内置的钩子
useState- 用于在函数组件中添加状态管理。useEffect- 在组件渲染后执行副作用操作,例如订阅数据、发送网络请求等。useContext- 用于在组件树中共享数据。useReducer- 用于管理复杂的状态逻辑。useCallback- 用于缓存函数并避免不必要的重新渲染。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)。
接口示例:
useState:
接口:
1
const [state, setState] = useState(initialState);
返回值:
state:当前状态的值。setState:更新状态的函数。useEffect:
接口:
1
useEffect(effectFunction, depsArray);
返回值:
- 无。
ant design
- ant design pro: 开箱即用的中台前端/设计解决方案 - Ant Design Pro
- ant design:https://ant.design/components/overview-cn/
- pro-components: https://procomponents.ant.design/components
- umi: https://v3.umijs.org/zh-CN/docs
使用:
- 面包屑:可以直接套用PageContainer,自动生成。
ProTable使用问题:
- ant protable 选择一行就会全选。原因:没有设置好rowKey,所以每行数据不能唯一标识。解决:设置rowKey=”name”。
工程问题
webstrom启用自动pretty和eslint
选择 “Languages & Frameworks” -> “JavaScript”(或者 “TypeScript”,如果你在 TypeScript 项目中使用 Prettier)。
选择 “Prettier” 选项卡,然后选择 “Prettier package” 为 “Local”,并指定 Prettier 的安装路径。选择auto自动找路径即可。
找到 “Languages & Frameworks” -> “JavaScript” -> “Code Quality Tools” -> “ESLint”。
- JB系软件。一段时间后,无法从系统粘贴板中读取进行粘贴。解决方案:在IDE中重新Ctrl+C复制一点东西就正常了。讨论:here。
前端的大坑,缓存问题。UMI+MSFU热更新,经常出现更新了代码加载不出来(特别是代码更新到使用的API)。不行就删掉.umi文件夹,然后重新生成。
“Module ‘xxx‘ does not exist in container“
- 基于MSFU等可以实现热更新,但是有时候代码更新了却看不到新的结果。记得用Ctrl+F5强制刷新缓存。
跨域请求:前端向不同的域(协议、域名、端口不同)发送请求(XHR、fetch),触发浏览器的同域策略判断。需要后端返回orign告诉浏览器前端的域是被允许的。参考here。
后端使用spring直接添加一个注释在控制器中:
1
@CrossOrigin(origins = "http://localhost:8000", maxAge = 3600, allowCredentials = "true")