【JS】积累与发现

基础语法

js中!和!!的区别及用法
ECMAScript 6 入门
js中==和===区别

对象

JavaScript 对象
js继承之原型继承
每创建一个函数,该函数就会自动带有一个 prototype 属性,该属性是个指针,指向了一个对象,我们称之为 原型对象。原型对象上默认有一个属性 constructor,该属性也是一个指针,指向其相关联的构造函数。通过调用构造函数产生的实例,都有一个内部属性,指向了原型对象。
解释一下上面的话,下图中,我们定义了一个Test方法,那么Test的类型是一个function,可以称这个Test为构造函数,这个函数本身有一个属性叫做prototype,其指向的对象,就是原型对象,从中可以看出这个原型对象里有两个属性,分别是constructor__proto__
在这里插入图片描述
然后通过调用new Test()构造实例,可以看到这个实例对象里有一个__proto__的属性,指向的就是Test的原型对象
在这里插入图片描述


JS中PROTOTYPE属性解释及常用方法
这篇文章更加深入一点
1.3里解释了为什么向构造函数的prototype里添加属性会影响后续构建的所有对象,因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。 从上面的例子就可以看出
1.6里说:这个区别就是function定义的方法(对象方法)有一个prototype属性,使用new生成的对象就没有这个prototype属性。也就是prototype属性是对象方法或者构造方法的专有属性。 我没懂,可能意思是说(以上面为例),Test里有prototype属性,而let t=new Test()t里只有一个__proto__没有prototype


彻底理解js中this的指向,不必硬背

刚接触通过函数构建对象(对象方法),我的疑惑是,为啥function Test(val){this.val=val}就可以用来构建对象了,例如let t=new Test("1"),后来一想,这可能就是this的功劳,在上面这篇博客里的**构造函数版this:**的讲解可以看到


JavaScript中call,apply,bind方法的总结。

遍历

JS里的for…in和for…of的用法

变量作用域

JavaScript 变量提升
函数的作用域是什么?js 的作用域有几种?
函数作用域和块作用域
理解es6中的暂时性死区
当程序的控制流程在新的作用域(module, function或block作用域)进行实例化时,在此作用域中的用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,也就是对声明语句进行求值运算,所以是不能被访问的,访问就会抛出错误。


前端面试题:JS中的let和var的区别
前面提到了var使用的是函数作用域以及变量提升,那个f函数里打印出来的第一个undifine就是变量提升的结果,在f函数里的作用域,程序构建了一个新的函数作用域,然后发现这个作用域里有一个var定义了变量,与let类似,这个var的变量就会被绑定到这个作用域里并且其声明会被提升到前面去,但此时没有进行词法绑定(求值运算或赋值),但var仍可以被访问。
f里的变量只会影响这个函数作用域的,影响不到f外面


let 和 const 命令

数据类型

JavaScript深入理解之undefined与null

异步

JavaScript异步机制详解
JavaScript:彻底理解同步、异步和事件循环(Event Loop)
“事件”就是线程之间相互通知的信息载体,通过一个event对象来记录

Promise

如何使用 Promise
Promise
怎么理解new Promise(function (resolve, reject){})中函数的参数resolve和reject

function test(resolve, reject) {
		if (Math.random() * 2< 1) {
            console.log('call resolve()...');
            resolve('200 OK');
            console.log('call resolve() done');
        } else {
            console.log('call reject()...');
            reject('less then 0.5');
        }}
var p1 = new Promise(test);
console.log('1');
var p2 = p1.then(result=>console.log('成功:' + result));
var p3 = p2.catch(reason=>console.log('失败:' + reason));

可以先简单了解promise的用法,
test方法是一个耗时函数,而p1是个Promise对象,就是test方法的容器,这个容器会让test方法(以事件循环的方式)异步执行也就是说创建了一个异步任务。并根据执行过程中的结果来判断是执行resolve方法还是reject方法,以上面为例,如果随机数大于0.5,就执行resolve方法,如果小于0.5,就执行reject方法,而这两个方法具体是什么呢?就是由下面那个thencatch来指定的。
但需要特别说明的是,then里传递进的那个匿名函数,并不完全等同于resolve方法,catch也同理。为什么这么说,因为在p1对象生成的时候,test方法就有可能已经被执行了,而这时候并没有指定then方法,所以resovle方法具体做了什么,肯定程序肯定是不知道的;而且从上面代码中可以看出,即使没有指定resolve方法具体要做什么,resolve方法仍旧被执行了,那这只有一个可能,resolve方法本身的执行也是异步的,反正就是要执行一个方法,具体要做什么事情,什么时候then调用了,什么时候执行。但是then传入的方法不能等同视为resolve方法,因为如果then方法返回了一个新的promise,then方法还支持链式调用,所以若果将then传入的方法不能等同视为resolve方法,那么then的返回值我们是拿不到的了。我怀疑用了什么手段,让resolve或者reject方法被调用时,也是异步执行的,如果调用了resolve方法,那么就从then里找到这个具体实现,并且将执行的结果取出来用于链式调用或者结束。

使用 Promise
可以详细了解Promise对象到底是什么,本质上 Promise 是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。并且

可以通过 Promise 的构造器从零开始创建 Promise。这种方式(通过构造器的方式)应当只在封装旧 API 的时候用到。理想状态下,所有的异步函数都已经返回 Promise 了。

也就是说,一般情况下,我们不会手动new一个Promise对象,除非是setTimeout(fn)这类的旧API,这个方法是在一点时间后,将fn放入事件循环队列里等待执行。
这个api是通过将方法fn作为参数传进setTimeout,实现将fn注册为回调函数。但是如果fn执行失败,外部没办法捕获这个异常,异常会被抛到最上层,这不是我们希望的,这是因为setTimeout没提供这个捕获的功能。

function saySomething(s){
    throw new Error('有哪里不对了');
    console.log("say somting"+s);
}
setTimeout(() => saySomething("10 seconds passed"), 1000);

通过如下方法可以将异常捕获掉,原理是,promise的异步方法其实就仅仅是执行一个setTimeout,而resolve方法本身又是promise的回调,虽然其执行的时机会延后个10s,但无论怎样,当执行过程中出现异常的时候,会被catch方法接住

const failureCallback = err=>console.log(err);
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(1000).then(() => saySomething("10 seconds")).catch(failureCallback);

Promise
Promise.then链式调用

If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain.

如下所示,如果then方法本身又返回了一个promise,这个新的promise会暴露出来,也就是说,promise3可以视作等同于promise2,但两者并不是同一个对象,可以通过Object.is(promise2,promise3)返回false来判断。

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('promise1');
  }, 300);
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('promise2');
  }, 300);
});
const promise3 = promise1.then((v) => {
  console.log(v);
  return promise2;
});
promise3.then(
  (v) => {
    console.log(v);
  }
);

Promise.resolve()

In brief, Promise.resolve() returns a promise whose eventual state depends on another promise, thenable object, or other value.

例如,Promise.resolve(123)生成的对象就依赖于123,再比如Promise.resolve(anotherPromise)生成的对象就依赖于anotherPromise
Let’s talk about how to talk about promises
主要描述了什么是resolved,doStuff()的promise就是resolved,他is resolved to second方法返回的promise。所以说,

已决议(resolved),它表示 promise 已经处于已敲定状态,或者为了匹配另一个 promise 的状态被“锁定”了

function doStuff() {
    return first().then(firstResult => return second(firstResult));
}

async/await

理解 JavaScript 的 async/await
补充说明,如果then方法里又返回了一个新的Promise对象,那么这个后续的then方法也需要等这个Promiseresolve之后才能执行,我怀疑如果then里直接返回的是一个非Promise对象,例如“123”,then本身也会返回Promize.resolve(123)对象。

那么什么是async?没有async的时候,创建一个异步任务,是将耗时方法作为参数传入 Promise构造函数完成的。而有了async/await,可以直接将原本用在Promise构造函数里的耗时方法丢在async function里,并调用这个async function来返回Promise对象;好处就是多个万一耗时操作由多个连续的操作组成怎么办。
而使用Promise注册回调的时候,如果需要级联多个耗时操作的回调(而这往往是因为每个回调又都是一个返回Promise的方法),这时就需要反复地then。而有了async/await,可以通过在async function内部使用await+try catch语法改写上述每个返回Promise的回调,从而实现像写同步方法那样写异步方法。见《async/await 的优势在于处理 then 链》

如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。

下列例子里,v就是resolve方法的入参,所以,await的是resolve方法的执行

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}
async function test() {
    const v = await takeLongTime();
    console.log(v);
}
test();

async 函数
await

Generator 函数的含义与用法
async 函数的含义和用法

模块

JS 之export、export default和module.exports
js中的export、import、export default等导入导出全解
导包时import花括号{}的作用

运算符

The left-hand side of an assignment expression may not be an optional property access.ts(2779)
?.是可选链运算符号,只能用于给读取值或者别人赋值,像这种ref.current?.style.height='100px'属于被赋值

【JS】问号点(?.)和双问号(??)的用法

BOM与DOM

screen

screen描述的是整个屏幕

window

window描述的是整个浏览器窗口的信息

navigator

navigator描述的是浏览器自身所带的信息(例如版本等)

location

节点树


获取节点的属性和子节点<div id="d1" class="div"> <div id="d2" class="div">text</div> </div>
获取属性和属性的值,但建议还是用nodeName和nodeValue,不容易混淆,因为文档中都是节点
在这里插入图片描述


元素节点:<div class="class" id="d1">123</div>就是元素节点,获取方式为document.getElementById("id")
属性节点:<div> class="class" id="d1">123</div>里的class="class"就是元素节点,获取方式为document.getElementById("id").attributes['class']或者.attributes[0]
内容节点 <div> class="class" id="d1">123</div>里的123就是内容节点,获取方式为document.getElementById("id").childNodes[0]
需要进一步说明的是,没有明确指定的属性是不会生成属性节点的,例如<input />这个元素节点的属性节点是空的,所以要访问其value,只能通过.value的方法;另外,通过.可以获得元素节点的全部非自定义属性运行时使用的值
例如<input type="checkbox" checked="checked"/>.checked返回结果为true,并且其结果会随着选中状态的改变而改变;而.attributes['checked']返回结果为checked,即只能获取html页面(浏览器调试台的element页面)上写的属性的值,当然如果使用了js修改了某个属性(例如name)的值,.attributes['checked']也会跟着改变。


innerHTML和innerText的使用和区别


不要用自身的子节点替换另一个子节点,如下所示,本意是将第一个节点替换为第二个节点,但这样的操作会直接导致第一个节点被删除,结果变为2 3;而如果将outerD.replaceChild(children[1],children[0]);改为outerD.replaceChild(children[0],children[1]);,结果会导致第二个节点被删除,结果变为1 3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        function f() {
            let outerD=document.getElementById("outerD");
            let children=outerD.children;
            outerD.replaceChild(children[1],children[0]);
        }

    </script>
</head>
<body>

<div id="outerD">
    <div id="d1">1</div>
    <div id="d2">2</div>
    <div id="d3">3</div>
</div>
<button onclick="f()">button</button>
</body>
</html>

为什么呢?个人理解是这样的。对于节点的操作有appendChild,insertBefore,replace等等很多,以replace(newNode,oldNode)为例,功能是将oldNode节点替换为newNode节点,具体操作过程是分步的:即首先将newNode节点从其原本所属的父节点上拆下来,然后把oldNode替换为newNode;如上例,outerD.replaceChild(children[1],children[0]);,其中children[1]d2children[0]d1,先把d2outerD上拆下来,此时outerD上只有d1d3,随后将d1替换成d2,此时就剩d2d3了。appendChild同理,需要将待添加的元素从原来的父节点上拆下来,加到新的节点后面


JavaScript中querySelector()和getElementById()(getXXXByXX)的区别
由于querySelector返回的是静态的,因此在使用template的时候,使用的是query获取template节点,以免破坏template本身


事件

JS事件机制
简述 JavaScript 的事件捕获和事件冒泡
冒泡与捕获阶段


下面这个键盘敲击事件传入的是this,也就是元素节点对象,你会发现当你输入的是abc的时候,事件函数获取其valueab,也就是说,onkeypress事件函数会发生在input标签的value更新之前;为了修正这个问题,我们可以把onkeypress改为onkeyuponkeyup的事件函数会发生在input标签的value更新之后,这也就是说,输入框的更新时机是键盘敲击之后,抬起之前

<input id="username" type="text" onkeypress="check_name(this)"/>
function check_name(element){console.log(element.value)}

事件及DOM

事件参考
目前的html规范已经不建议在html标签里直接写onclick的属性了,而是建议按dom2的方式书写,但是我觉得这样有点麻烦啊= =,例如,要在页面加载完成后绑定事件方法,以及用onkeydown="return false"可以禁止输入,但使用下面的方法如何控制禁止输入呢

<input id="username" type="text"/>
function check_name(event) {
	console.log(event);//事件本身
	console.log(this);//事件触发的元素节点
}
document.getElementById("username").addEventListener("keypress",check_name);

如何禁止输入,找到了一个答案

function check_name(event) {
	console.log(event);//事件本身
	console.log(this);//事件触发的元素节点
	event.returnValue=false;//通过这个属性进行更改
}

或者dom0方式进行时间绑定

document.getElementById("someID").onkeydown=function(event){
        console.log(this);//事件触发的元素节点
        console.log(event);//事件本身
    }
    document.getElementById("dom0").onkeydown=null;//注销事件

表单事件onsubmit可以阻止表单的提交,如onsubmit="return f()"f(){return false}onkepress也可以实现禁止输入

form表单提交onclick和onsubmit

jQuery

选择器

<div id="d1">Hello JQuery</div>
<div >Hello JQuery</div>

在这里插入图片描述
可以看到返回的jQuery对象有一个叫0的属性,这个属性的对象就是div#d1这个div,可以通过$("#d1")[0]来获取这个对象,这个对象就是DOM原生的元素节点对象


jQuery里的this

<script>
	$(function(){
		$(".b").click(function(){
			console.log(this,this.value);//this就是选择器所选择的标签,是一个DOM原生的元素节点对象,
            let jQuery_obj = $(this);//用$将元素节点对象转化为jQuery对象
            console.log(jQuery_obj.val());//使用jQuery对象的方法
		});
	});
</script>
<button value=":input" class="b">切换所有的:input</button>

propattr的关系类似于从原生DOM的元素节点上通过.和通过属性节点获得属性的值。prop能获取元素节点的全部非自定义属性的运行时使用的值****,而attr只能获取html页面**(浏览器调试台的element页面)上写的属性的值,例如

<input type="checkbox"  id="c" game="LOL" checked="checked" name="check"/>

通过$("#c").prop("checked")的结果true,其结果会随着选中状态的改变而改变,而$("#c").attr("checked")的结果checked,选中状态的改变并不会改变checked这个属性的值,所以.attr("checked")不会跟着变,当然如果使用了js修改了某个属性(例如name)的值,.attr("name")也会跟着改变。

事件

jQuery的事件对象不是DOM原生的事件对象,是对其的封装,不过功能基本相同


Nodejs

何为nodejs-和-npm
nodejs就是一个js的运行环境

NPM vs. NPX,傻傻分不清楚
什么是npx?

nvm

npmmirror 中国镜像站

nvm node_mirror https://npmmirror.com/mirrors/node/
nvm npm_mirror https://npmmirror.com/mirrors/npm/

模块基础

Node搜寻模块规则


npm install -g是全局安装,该包会安装在nodejs目录的node_module下面
如果在一个名字为A的文件夹下面安装依赖库,并且这个依赖库的名字也是A的话,会报错,文件夹名字不能与安装的包的名字相同,这样会导致搜索包时的无限循环


nodejs中package.json和package-lock.json文件的功能分析
npm install 安装依赖包 --save、–save-dev、-S、-D的区别

Nvm ls-remote结果为N/A的解决方案
在环境变量里加上export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/
在 TypeScript 中导入 JavaScript 包,解决声明文件报错问题
其实就是要去官网找@types的js包。但是,比如react-transition-group这个包,我需要同时安装react-transition-group@types/react-transition-group才能用

TypeScript

Interface

TypeScript之interface定义对象(二)
ts里的interface更像是pojo

TypeScript 中的类和接口 - tireLYL的文章 - 知乎
可以看到interface编译之后什么都没有出来,因为ts编译之后就是js,而js本身没有类型,所有interface的对象在被ts编译后,就都变成了传统的无类型的js对象。因此,interface就仅仅是ts的一种语法(很像java的泛型和泛型擦除)
更进一步的,其实js里本身没有java里的那种真实的类,js里每个对象都仍然像是{a:1,b:"hello"}的这种东西,两个对象同属于同一个类,真实情况下这两个对象只不过是恰好长得一样罢了。
typescript进阶(二):interface 和 class 的区别

undefined

Type ‘undefined’ is not assignable to type in TypeScript
The “Type ‘undefined’ is not assignable to type” error occurs when a possibly undefined value is assigned to something that expects a different type.To solve the error, use the non-null assertion operator or a type guard to verify the value is of the specific type before the assignment.

TS系列篇|类(class)

类型

typescript中,对象使用动态变量作为key获取相应的值时类型声明

export declare const PresetStatusColorTypes: readonly ["success", "processing", "error", "default", "warning"];
export type PresetStatusColorType = typeof PresetStatusColorTypes[number];

PresetStatusColorTypes声明了一个“取值必须是只读列表”的一个对象,然后PresetStatusColorType的类型就是PresetStatusColorTypes列表中的任意一个,所以PresetStatusColorType的实际类型,就是"success" | "processing" | "error" | "default" | "warning"

function f(t:PresetStatusColorType){
    return ""
}
let t="success";
f(t as PresetStatusColorType)

最后如果不写t as PresetStatusColorType,那么因为t的类型是string,与"success" | "processing" | "error" | "default" | "warning"不符,就会报编译异常

React

安装

npx create-react-app 使用淘宝镜像

文档

https://beta.reactjs.org/learn

jsx、tsx

(005)RN开发 js jsx ts tsx的区别
就是Javascript和XML结合的一种格式,一个代码里,即能写js,也能写xml。tsx就是将js升级为ts,带上了类型
3.1 react的空标签

Lifecycle

React 18 生命周期
生命周期
组件的生命周期可分成三个状态,上面文章中提到的方法就是下面几个阶段的前后执行的:

  • Mounting(挂载):已插入真实 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸载):已移出真实 DOM

useXXX

useXXX都是带来side-effect的内置函数,所谓side-effect指的是副作用,直译就是侧面的影响,如果一个函数的运行不会对外部的数据造成影响,那么说这个函数没有产生副作用,反之那么就说这个函数有副作用。比如useState就是为了给函数带来一些副作用,并且通过这些副作用来从而控制每次的输出。比如说分页请求,第一次渲染某个组件,我们会使用useState来保存页码,我们保存的这个页码数据和这个组件本身没关系,这个页码数据存储在和这个组件不相关的地方,因此产生了副作用,然后用户修改了分页大小或者做了翻页,那么我们就会调用setState去更新这个数据,并且会触发useState的机制,导致重新渲染这个页面的时候。

这块确实建议看官方文档,讲得很好

[
State: A Component’s Memory
(https://juejin.cn/post/6979786083680649223)
useState为什么不能放到条件语句里面?
useState为什么不能放在判断里,从问题深入到源码,盘它

useEffect

轻松学会 React 钩子:以 useEffect() 为例

React18的useEffect会执行两次
useEffect是在挂载后执行,之所以执行两次,是因为开发模式下,多模拟了一次卸载和挂载,个人理解,比如说退出一个页面后重新进入这个页面,可能不需要再次请求这个页面所需的数据了,也就是所说的react未来希望支持的,卸载后,仍然保留状态。更进一步说,如果让同一个页面再次挂载,那会不会因为数据等问题(比如重复请求了数据)导致出错。为了规避这些问题,所以react强行模拟了一次重新加载。让开发人员将前端页面做得幂等。
后文中的例子,描述了一些卸载后重置页面状态等例子,但对于其中数据类的例子(3-1、3-2)个人觉得例子没有意义,这个只是利用了development模式下执行两次挂载的特性,强行让useEffect内部关键的一些功能,在第二次重新挂载的时候执行。但这和react这样的设计相悖。至于3-2的例子是有一点贴切的,比如重新挂载的时候,可以不要去请求数据了。

Synchronizing with Effects
Add cleanup if needed 章节讲了为啥开发模式会执行两次useEffect
以及cleanup函数的执行时机

React will call your cleanup function each time before the Effect runs again, and one final time when the component unmounts (gets removed).

You Might Not Need an Effect

如果仅仅是同步地对数据进行处理然后渲染,那么不应该使用useEffect,就直接在主函数处理就好了。
这篇文章还讲到了好多其他react特性,例如key、例如react函数的用法。

  1. key与useState的用法,笔记见后面的key部分内容。
  2. Adjusting some state when a prop changes :如果在render过程中执行了setXX导致当前组件re-render,那么react会直接丢弃掉第一次render的jsx(即未)然后直接开始重新渲染。第一次render仅仅就执行到生成了新的jsx,并未真正地进行渲染,因此子组件也未被触发re-render
  3. When you’re not sure whether some code should be in an Effect or in an event handler, ask yourself why this code needs to run. Use Effects only for code that should run because the component was displayed to the user. 这句话难理解一点,useEffect应该用于页面被展示出来后应该做的一些操作,例如请求数据、提交埋点等。而点击这种操作是由用户导致的事件,不应该用useEffect
  4. Initializing the application 对于某些整个app阶段只能执行一次的的代码,需要特殊处理,否则如果这些代码的组件被unmount->re-mount,那么这些代码就会被二次执行,可能导致错误。react18的开发模式为我们模拟了这种情况,提醒我们不要忘记这个问题。

useRef

useRef “Object is possibly null” error in React [Solved]
typescript里useRef需要泛型,并且会做非空判断。
property ‘click’ does not exist on type ‘never’ useref
React useRef 指南

export default function A6Update(a6UpdateProps: A6UpdateProps) 这个组件,如果使用的时候

<A6Insert open={insertModalOpen} student={insertForm}>
</A6Insert>

会报错Property 'children' does not exist on type 'IntrinsicAttributes & A6InsertProps',需要写<A6Insert open={insertModalOpen} student={insertForm}></A6Insert>也就是说,></A6Insert>不能分开,因为这个组件不具备内部元素

Key

是时候该知道React中的Key属性的作用与最佳实践了!
聊聊React中的key
React之key详解

对上文所说的“key相同且数据相同则不会重新渲染”应该是错的,因为子模块仍然会重新渲染,key也不具备“记忆功能”,key并不是用于优化性能的,而仅仅就用于标识一个组件的id,如果通过key判断发现key变了,那么这个组件就要重新生成,那么useState等信息不可以共用;反之如果某个组件没有key,那么react会认为就是一个组件,useState等信息可以共用。但再次声明,key不具备记忆能力,比如key从1->2->1,第二次变回1的时候,仅依赖key是想不起来上次1的组件样式是什么的。

CSS

在 React 中设置全局 font family

// index.tsx
// 👇️ import css
import './index.css';

import {createRoot} from 'react-dom/client';
import App from './App';

const rootElement = document.getElementById('root');
const root = createRoot(rootElement);

root.render(
  <App />
);
// index.css
body,
html {
  font-family: 'Poppins', sans-serif;
}

event

react-event-type-in-typescript
react的click事件的ts类型?
react组件之间的通信

React18 - react-transition-group

React18 - react-transition-group
React系列十四 - React过渡动画
React 学习 — 过渡动画

AntD

Form

Ant Design表单之labelCol 和wrapperCol的实际开发笔记
antd项目中input框的value值不能被修改,form.setFieldsValue 来动态改变表单值

Day.js

Day.js中文网

Axios

使用Typescript重构axios(十三)——让响应数据支持泛型
ts里的axios本身也支持泛型,比如axios.get<T>()

EventEmitter3

EventEmitter3 模块的使用经验及骚操作
React Native 中 使用hooks 离开页面时卸载事件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值