8-9
1 react浅层比较
[1] React里的浅比较.https://www.mengfansheng.com/2018/12/23/React%E9%87%8C%E7%9A%84%E6%B5%85%E6%AF%94%E8%BE%83/
2 seo优化方案
前端如何进行seo优化.https://blog.csdn.net/yuyuking/article/details/89374794
总的来说,就是加上 <mata>
头部元信息
title: "SheepDex - First DEX integrating Spot and Derivatives",
meta: [
{
name: "google-site-verification",
content: "Bm0ZzqadNVHojD8pMOiGJTCmtor5SpnuVZetrmuH6mo",
},
{
name: "description",
content:
"SheepDex is a decentralized cross-chain liquidity aggregation platform based on the integration of spot and derivatives on Binance Smart Chian (BSC) with 0 Funding Rate Perpetual Contract.",
},
]
3 匹配正则-临时
(\d+)px(?=[; ])
${r($1)}
${px2vwm($1)}
4 M1Mac无法用nvm安装旧版本node的问题
描述:M1如果用nvm安装16版本以下的node,会出现很多错误信息,nodev14, v12等低版本node无法正常安装
解决方案:进入一个模式,进行安装即可
注意:在安装nvm之前,先把原本的node删除掉
进入以下模式就不再会报错
arch -x86_64 zsh
之后在这个模式下就可以旧版本node了
nvm install 12
[附] nvm安装方法
直接命令行,输入
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
nvm ls-remote
nvm指定默认版本
nvm alias default 14
# 指定版本为14
nvm use 14
⚠️ 切换node版本,请不要通过vscode的命令行切换,通过自带bash切换vscode才会生效
在vscode中,通过nvm切换node版本之后需要重启一下,才会生效
[1] https://github.com/nvm-sh/nvm
[附] nvm和node卸载方法
卸载nvm
1.删除.nvm目录
cd ~
rm -rf .nvm
2.移除掉~/.profile, ~/.bash_profile, ~/.zshrc, ~/.bashrc文件中关于nvm的配置
- vim .bash_profile -》打开Path配置
- 将export NVM_DIR 那段语句删除
- 按ESC,:后键入wq,回车 -》保存修改
- source .bash_profile -》让配置文件里面生效
3.命令行输入nvm、npm,分别提示command not found,删除成功
卸载node
1.通过brew安装的,用brew卸载:brew uninstall nodejs
2.安装包安装的,通过sudo 强制卸载:sudo rm -rf /usr/local/{bin/{node,npm},lib/node_modules/npm,lib/node,share/man//node.}
3.其他方式安装的,可以删除这些文件:
sudo rm -rf /usr/local/lib/node \
/usr/local/lib/node_modules \
/var/db/receipts/org.nodejs.*
[1] Mac下卸载删除nvm和node.https://www.cnblogs.com/qianxiaox/p/13765802.html
[2] mac M1 nvm 安装问题.https://blog.csdn.net/longgege001/article/details/114067242
nvm-windows
问题1:nvm安装,nvm use 一直报错exit status 1 或 exit status 145 问题?
5 pingfang字体下载
https://fonts.lanzoui.com/b00ueryef
fray
font-spider是一个文件一个文件进行操作的
yarn global add font-spider
font-spider index.html
# OR
font-spider /h5/*.html
6 vue3+vuei18n
注意i18n版本,否则ts会报找不到声明类型
vue3
vue-i18n@next
[1] vue3中引入vue-i18n, 国际化方案.https://blog.csdn.net/cwxxiayi/article/details/115602088【重点】
[2] vue3.0 + ts + element-plus + i18n 中英文切换.https://www.icode9.com/content-4-999139.html
7 一句话css让a标签默认样式失效
a,a:link,a:visited,a:hover,a:active{
text-decoration: none;
color:inherit;
}
一句话让button清除所有默认样式
margin: 0;
padding: 0;
border: 1px solid transparent; //自定义边框
outline: none; //消除默认点击蓝色边框效果
8 判断是否为pc的通用方法-客户端检查
🏷:isPc | 客户端检查
法一:React-device-detect库
有一个库 react-device-detect
,可以直接引入进行检测
import { isMobile } from 'react-device-detect'
import { isMobile as isPc } from 'react-device-detect'
法二:用userAgent检测
const IsPc = () => {
let userAgentInfo = navigator.userAgent
let Agents = new Array(
'Android',
'iPhone',
'SymbianOS',
'Windows Phone',
'iPad',
'iPod'
)
console.log("userAgentInfo", userAgentInfo)
let flag = true
for (let v = 0;v < Agents.length;v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false
break
}
}
return flag
}
IsPc()
=>>
true
9 注意字符串.toString(16)是无效的
toSring(参数)只适用于数字类型
'22222222222222'.toString(16) // 错误
22222222222222..toString(16) // 正确
=>>
22222222222222 // 数字类型
'143603a9638e' // 十六进制字符串类型
10 react如何使用Jest测试单个文件?
带上文件即可,支持正则符号
jest ./src/utils/*.ts
[1] 如何使用Jest测试单个文件?.https://qastack.cn/programming/28725955/how-do-i-test-a-single-file-using-jest
11 mac-docker安装和卸载
Mac 配备 Apple 芯片
您必须安装Rosetta 2,因为某些二进制文件仍然是 Darwin/AMD64。要从命令行手动安装 Rosetta 2,请运行以下命令:
$ softwareupdate --install-rosetta
再安装docker
[1] 安装docker官网.https://docs.docker.com/desktop/mac/install/
[2] 卸载参见 Docker 官网: <Uninstall Docker Desktop on Mac>
[3] m1芯片macOS安装docker.https://zhuanlan.zhihu.com/p/364183156
12 React组件Warning: Received false
for a non-boolean attribute collapsed
.
index.js:1 Warning: Received `false` for a non-boolean attribute `collapsed`.
If you want to write it to the DOM, pass a string instead: collapsed="false" or collapsed={value.toString()}.
If you used to conditionally omit it with collapsed={condition && value}, pass collapsed={condition ? value : undefined} instead.
解决方案:
用 0
和 1
代替boolean
<p collapsed={value? 0: 1}></p>
[1] Warning: Received true
for non-boolean attribute gray
.https://github.com/styled-components/styled-components/issues/1198
13 中文正则表达式匹配-正则中文匹配
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
[1] 中文正则表达式匹配-正则中文匹配.https://www.jianshu.com/p/8695c2ba8ace
14 web3js方法获取账户信息和余额
调起小狐狸,并获取账户地址,此方法可以调起解锁
⚠️ 注意:enable()方法已被metamask弃用,请使用request代替
,无法通过Provider去唤醒小狐狸
const accounts = await ethereum.request({ method: 'eth_requestAccounts' })
=>>
['0xjlksadjfkljasldfjlsajdfkljaslkdjfklajsdfl']
const enable = await ethereum.enable();
=>>
['0xjlksadjfkljasldfjlsajdfkljaslkdjfklajsdfl']
[1] web3js方法获取账户信息和余额.https://blog.csdn.net/JackieDYH/article/details/115380639
15 如何让vscode支持路径代码提示
❗ 支持路径别名,需要两方面支持,一是项目本身,二是vscode
项目的别名通过webpack、或者tsconfig配置,而vscode则通过setting.json配置
在 vscode 的 setting.json
中给 Path Intellisence 配置(该方案是最优选,能识别任意格式文件,覆盖率最广。当别名发生改变时只需修改配置即可)
// setting.json
"path-intellisense.mappings": {
"a": "${workspaceRoot}/src",
"c": "${workspaceRoot}/src/components",
...
}
[1] vscode 中 Vue别名路径提示.https://segmentfault.com/a/1190000023438286
16 Vue3的模板引用
在Vue2中,我们直接给标签设置ref属性,之后再用this.$refs去取该元素,
而在Vue3中,则用 ref()
响应式函数来处理,看例子:
<input ref="inputRef">
setup(){
const inputRef = ref(null)
return {inputRef}
}
17 Vue3+Ts项目中在Vscode中引入ts文件,提示无法导入.ts文件
猜测:虽然提示这个,但是编译后,程序并没有宕掉,所以这是vscode提示出错,所以解决方案就是让vscode知道
import en from "./en.ts"; // 出错:无法导入.ts文件
import en from "./en"; // 正确:不加后缀
本身是支持导入ts的,但编译器报错,所以不加后缀了
18 Vue3项目在Vscode中,无路径提示,但安装了Path Intellisence
解决方案,手动配置,让Vscode支持路径提示
// setting.json
"path-intellisense.mappings": {
"a": "${workspaceRoot}/src",
"c": "${workspaceRoot}/src/components",
...
}
[1] vscode 中 Vue别名路径提示.https://segmentfault.com/a/1190000023438286
19 自动化部署
其中涉及到:
- git代码管理
- git-workflows配置(工作流程配置)
- ssh登录权限配置,ssh-agent用法
- docker常用命令
- DockerFile编写
- docker-compose配置
参考
[1] github-action自动化部署.https://frostming.com/2020/04-26/github-actions-deploy/
[2] github-action官方文档.https://docs.github.com/cn/actions/reference/workflow-syntax-for-github-actions
[3] compose官方文档.https://docs.docker.com/compose/gettingstarted/
20 iphone safari不兼容CSS的active
<body ontouchstart="" onmouseover="">
</body>
[1] http://stackoverflow.com/questions/8330559/hover-effects-using-css3-touch-events
21 一个在线压缩图片的网站
22 Hexo集成Algolia全局搜索插件
Algolia全局搜索原理:通过 hexo-algolia
插件将数据导入Algolia,搜索时,请求Algolia的服务器获取搜索数据和对应的链接
[1] Hexo集成Algolia搜索插件.https://blog.naaln.com/2016/07/hexo-with-algolia/
[2] 集成过程中的一些坑.https://www.zhihu.com/question/46822587
[3] Algolia官网.https://www.algolia.com/apps/
一些问题:
- 如果用instantsearch自带的reset按钮重置的话,会导致无法点击下一页
[1] instantsearch.https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/
23 CSS3动画复习
tranform,过渡,动画
- 普通translate,3D版translate3d(x,y,z), scale, rotate等
- 透视
透视-perspective
人眼距离物体的距离
perspective: 100px;
/* 透视越小,图形越大 */
以下分别是 100px
和300px
的效果
动画-animation
@keyframe animationName{
from{}
percent{}
to{}
}
@keyframe animationName2{
0%{}
100%{}
}
.box{
animation: animationName 3s;
}
实例:一个旋转的loading
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`
const StyledSVG = styled.svg<{ size: string; stroke?: string }>`
animation: 2s ${rotate} linear infinite;
height: ${({ size }) => size};
width: ${({ size }) => size};
path {
stroke: ${({ stroke, theme }) => stroke ?? theme.primary1};
}
`
export default function Loader({
size = '16px',
stroke,
...rest
}: {
size?: string
stroke?: string
[k: string]: any
}) {
return (
<StyledSVG viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" size={size} stroke={stroke} {...rest}>
<path
d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 9.27455 20.9097 6.80375 19.1414 5"
strokeWidth="2.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</StyledSVG>
)
}
实例:一个增量显示...的动画
export const Dots = styled.span`
&::after {
display: inline-block;
animation: ellipsis 1.25s infinite;
content: '.';
width: 1em;
text-align: left;
}
@keyframes ellipsis {
0% {
content: '.';
}
33% {
content: '..';
}
66% {
content: '...';
}
}
`
25 多行文本-单行文本超出省略-white-space: no-wrap
注意:
- 控制文本换行与否,用
white-space
控制,而非word-wrap - 省略出现的前提是,文本得超出容器
实例:多行-单行省略
下方是例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>016.多行-单行省略</title>
<style>
.box {
width: 100px;
height: 60px;
/* 此多行省略方案有兼容性问题,Chrome, FireFox可用,其他待验证 */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
line-height: 20px;
}
.box-single {
width: 100px; /* 把文字限定宽度 */
text-overflow: ellipsis;
white-space: nowrap; /* 决定遇到空格如何处理,不包裹 */
overflow: hidden;
}
</style>
</head>
<body>
<div class="box">
我是文字加上了肯德基反垃圾SDK分离焦虑肯德基阿斯利康放进拉克丝等级分类卡死了点击快乐番薯讲道理快捷方式来看待缴费落款时间到了就
</div>
<hr>
<div class="box-single">
我是文字加上了肯德基反垃圾SDK分离焦虑肯德基阿斯利康放进拉克丝等级分类卡死了点击快乐番薯讲道理快捷方式来看待缴费落款时间到了就
</div>
</body>
</html>
WebKit内核浏览器解决办法
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
[1][CSS 多行文本溢出省略显示](https://juejin.cn/post/6844903461209767944)
26 如何扩展ts的类型?像js的扩展运算符一样
在ts中叫做交叉类型 &
,当然也可以用继承,注意与联合类型 |
区分
const speakProxy = <T>(target: T): T & SpeakProxy => {
return {
...target,
speak(){
const that = this as Animal
console.log('[我会说话了!]:', that.name)
}
}
}
const proxyDog = speakProxy(dog)
const proxyCat = speakProxy(cat)
[1] Typescript高级特性之交叉类型,联合类型,类型保护.https://blog.csdn.net/baidu_28196435/article/details/89707673
27 mac开启ssh服务-并内网穿透
由来:为练习github-action自动化部署,而又没有公网服务器,所以用本机做服务器,内网穿透后让github服务器能够访问
开启ssh服务
现在就可以通过ssh登录本mac了
内网穿透
工具:花生壳
第一步:增加新映射-> 配置tcp-> ssh服务 -> 保存
第二步:登录服务器
ssh -p 23186 [email protected]
之后输入密码,如果正确则登录成功
- yourname为你的登录账号
28 ssh-agent
作用:多台服务器之间进行登录,而免密码
本机-> Server1 可以登录
本机-> Server2 可以登录
Server1-> Server2 登录失败,因为Server1和Server2之间并没有进行免密登录
这里就需要开启ssh-agent,如下是开启步骤:
step1. 开启 ssh-agent
$ eval `ssh-agent`
Agent pid XXX
step2. 添加私钥
$ ssh-add ~/.ssh/id_rsa
# 如果生成密钥时是使用的默认的,那么就是这个了,如果不是的话就写你的私钥地址吧
step3. 告诉ssh 允许 ssh-agent 转发
修改全局:
$ echo "ForwardAgent yes" >> /etc/ssh/ssh_config
修改个人
$ touch ~/.ssh/config
$ vim ~/.ssh/config
Host *
ForwardAgent yes
step4. 修改每台服务器的 ssh 配置文件,让它们都对 ssh-agent 进行转发
到每台服务器上去按 step3 -> 全局,做一下。
参考:
[1][ssh-agent 使用指南](https://segmentfault.com/a/1190000002449006).https://segmentfault.com/a/1190000002449006
28 Failed to execute script docker-compose
docker没有启动,请检查docker是否启动
service docker start
29 [Fail] RUN apk add --no-cache gcc musl-dev linux-headers
原因:gcc没安装
参考下方链接安装gcc再次docker-compose即可
[1] MAC m1 与GCC(C++/C编译环境).https://blog.csdn.net/qq_42678864/article/details/115560757
30 React组件如何进行测试
详见:Tmp9-6的React测试
测试组件大致流程?
首先,React官网有相关文章.https://zh-hans.reactjs.org/docs/testing.html
[1] React测试官方文档.https://zh-hans.reactjs.org/docs/testing.html
31 git回滚
首先说需求:本地 feat/v2
分支和远端 origin/feat/v2
分支目前是同步的,但我想回退到 v1.0
,如何操作呢?
暴力法(常用)
注意:先备份分支
- 本地代码回滚到上一版本(或者指定版本)
git reset --hard HEAD~1
- 加入-f参数,强制提交,远程端将强制跟新到reset版本
git push -f origin feat/v2
注意给稳定的代码打tag
git tag -a v1.0 -m '第一个稳定版本'
#记得写描述
git push origin v1.0
# 推送到远端
常规法(删除分支法)
首先备份当前
feat/v2
分支,如果出现意外还可以还原git checkout -b back/feat/v2
强制让本地分支回退到v1.0版本
git reset --hard v1.0
删除远端
origin/feat/v2
分支git push origin :feat/v2
提交本地分支
git push origin feat/v2
如果没有异常,删除备份
back/feat/v2
分支
[1] git 远程分支回滚.https://blog.csdn.net/u013399759/article/details/52212436
28 react依赖测试
一句话: react依赖的比较只会进行
===
比较,主要为了提高效率
测试依赖变化,只要依赖是useMemo后的值,那么不管它是什么类型 React都可以检测出是否改变
const [objTestState, setobjTestState] = useState(false)
const obj = useMemo(() => {
// return objTestState ? { aaa: 123 } : {}
// 引用类型
return objTestState ? 123 : 0
// 值类型
}, [objTestState])
useEffect(() => {
console.log('[obj]:', obj)
setTimeout(() => {
console.log('[setobjTestState]:')
// setobjTestState((prev: boolean) => !prev)
setobjTestState(true)
}, 2000)
}, [obj])
29 commit规范
用于说明 commit 的类别,只允许使用下面7个标识。
• feat:新功能(feature)
• fix:修补bug
• docs:文档(documentation)
• style: 格式(不影响代码运行的变动)
• refactor:重构(即不是新增功能,也不是修改bug的代码变动)
• test:增加测试
• chore:构建过程或辅助工具的变动
如果type为feat和fix,则该 commit 将肯定出现在 Change log 之中。其他情况(docs、chore、style、refactor、test)由你决定,要不要放入 Change log,建议是不要。
30 Mac安装Electron的坑-死活安装不上-卡在node install.js那里
原因 :网络原因
两种方案:1配置国内源 2终端代理
解决方法,配置yarn源
1.配置
vim ~/.yarnrc
registry "https://registry.npm.taobao.org"
disturl "https://npm.taobao.org/dist"
electron_mirror "https://npm.taobao.org/mirrors/electron/"
# 注意这里小写,不要写成ELECTRON_MIRROR了
lastUpdateCheck 1629902708964
# 如果安装失败,把lastUpdateCheck这一行删除试试
2.运行,即可
yarn add electron
[1] electron官网.https://www.electronjs.org/docs/tutorial/quick-start
[2] Electron安装失败.https://blog.csdn.net/mocoe/article/details/86751925
31 前端页面换肤逻辑
样式覆盖法、变量法、多套皮肤法
主流的有:变量法和Css in Js
最常用,且兼容性最好的为 css in js
法
[1] 前端一键换肤实现,css变量兼容方案,ant-design换肤(转).https://juejin.cn/post/6844904130171895821
32 React如何轮询数据
- 研究multicall如何工作的
TODO模仿自写一套轮询工具
33 让css颜色变黑|变亮的通用库
polished
这个库
npm install --save polished
介绍
这个库可以将输入css变白(lighten),变黑(darken),增加透明(opacify),减少透明(transparentize),反转颜色(invert)
Usage
import { lighten, modularScale, darken } from 'polished'
Open the console and play around with it!
const styles = {
color: lighten(0.2, '#000'),
"font-size": modularScale(1),
[hiDPI(1.5)]: {
"font-size": modularScale(1.25)
}
}
// =>>输出
const styles = {
color: '#333',
"font-size": '1.33em',
'@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 1.5/1), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx)': {
"font-size": '1.66625em',
}
}
一些技巧:给按钮加上点击效果
给按钮添加一个hover变色,一般加黑 0.05
即可
const Button = styled.div`
background-color: ({theme}) => theme.primary01;
&:hover{
background-color: ({theme}) => darken(0.05, theme.primary01);
}
`
34 ??和||的区别
判断方式不同:
使用 ??
时,只有当值1为null
或undefined
时才返回值2;【收敛】
使用 ||
时,值1会转换为布尔值判断,为true
返回值1,false
返回值2
[1] JS中 ?? 与 || 的区别.https://blog.csdn.net/weixin_41650390/article/details/113739845
35 ts阻塞等待
第一种:暴力法(同步)-精确
const now = () => new Date().getTime()
const start = now()
const limit = 1000 // 等待1秒
while(true){
const end = now()
if(end-start >= limit) break
}
第二种:异步法-不精确(定时器不可靠)
前提是在异步函数中
function wait(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms))
}
function waitRandom(min: number, max: number): Promise<void> {
return wait(min + Math.round(Math.random() * Math.max(0, max - min)))
}
// 在异步函数中
await waitRandom(1000, 2500)
36 React组件重新渲染
React的依赖变更规则
只进行最简单的比较 ===
简单类型
只进行===比较
数组
数组只是进行===比较,不会比较内容,只有数组引用变了 才会触发依赖更新
const arr = []
// arr[0]=1 不改变
// arr.push(0) 不改变
// arr=[] 改变
// return prev.map((item:number)=> item+1) 改变
useMemo(()=>{}, [arr])对象也一样
联想:useSelector的依赖机制呢?
默认情况下,也是 ===
比较,所以只要dispatch的值和store的值不一样,则每次都会更新依赖,会造成性能问题
useSelector的第二个参数,可以传入一个函数,用于比较前后值从而决定是否要更新依赖
useSelector(()=>{}, shallowEqual)
// 进行浅层比较,可以比较两个对象最外层内容是否有变化
// shallowEqual从redux库中导出,只适用于最外层内容是否变化,对于数组包含对象的情况不适用
所有手写了一个适用于数组包含对象的deepArrEqual
export function deepArrEqual(left: any[] | undefined, right: any[] | undefined): boolean {
if (!left || !right) return false
if (left.length != right.length) return false
for (let i = 0; i < left.length; ++i) {
if (!shallowEqual(left[i], right[i])) return false
}
return true
}
React函数组件setState()更新机制
setState多少次,函数就重新执行多少次,但有特殊情况,当 多个紧挨的set且值未改变
时,会被合并为一次(所以setState()通常情况下是异步的),看下面例子:
setCounter((prev: number)=> prev+ 1) // poll
setCounter1((prev: number)=> prev+ 1) // poll
=>>
会执行两次
setCounter((prev: number)=> prev+ 1) // poll
setCounter1((prev: number)=> prev+ 1) // poll
setName((prev: number)=> prev)
setAge((prev: number)=> prev)
=>>
会执行三次,下面紧挨的值未改变的被合并为一次
setCounter((prev: number)=> prev+ 1) // poll
setCounter1((prev: number)=> prev+ 1) // poll
setName((prev: number)=> prev)
setAge((prev: number)=> prev)
setCounter2((prev: number)=> prev+ 1) // poll
setArr((prev)=> prev)
=>>
会执行五次
值的变更依据,就是 最简单的===比较
,不会进行深层比较 例如:
setArr((prev)=> {
prev.push(0)
return prev
})
=>> 不改变
setArr((prev)=> {
return []
})
=>> 改变,每次都返回新的数组[]
37 精读《useEffect 完全指南》
[1] 精读《useEffect 完全指南》.https://github.com/ascoders/weekly/blob/v2/096.%E7%B2%BE%E8%AF%BB%E3%80%8AuseEffect%20%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97%E3%80%8B.md
38 区块链 Dapp 开发教程
[1] https://github.com/rebase-network/Dapp-Learning
39 uniswap3设计原理
坚实的梦想博客
介绍:
代码架构
Uniswap v3 在代码层面的架构和 v2 基本保持一致,将合约分成了两个仓库:
core 仓库的功能主要包含在以下 2 个合约中:
- UniswapV3Factory: 提供创建 pool 的接口,并且追踪所有的 pool
- UniswapV3Pool: 实现代币交易,流动性管理,交易手续费的收取,oracle 数据管理。接口的实现粒度比较低,不适合普通用户使用,错误的调用其中的接口可能会造成经济上的损失。
peirphery 仓库的功能主要包含在以下 2 个合约:
- SwapRouter: 提供代币交易的接口,它是对 UniswapV3Pool 合约中交易相关接口的进一步封装,前端界面主要与这个合约来进行对接。
- NonfungiblePositionManager: 用来增加/移除/修改 Pool 的流动性,并且通过 NFT token 将流动性代币化。使用 ERC721 token(v2 使用的是 ERC20)的原因是同一个池的多个流动性并不能等价替换(v3 的集中流性动功能)。
这些合约间的关系大致如下图:
[1] 坚实的梦想博客.https://liaoph.com/tags/#Uniswap
交易过程
路径选择
在进行两个代币交易时,是首先需要在链下计算出交易的路径,例如使用 ETH
-> DAI
:
- 可以直接通过
ETH/DAI
的交易池完成 - 也可以通过
ETH
->USDC
->DAI
路径,即经过ETH/USDC
,USDC/DAI
两个交易池完成交易
Uniswap 的前端会帮用户实时计算出最优路径(即交易的收益最高),作为参数传给合约调用。前端中这部分计算的具体实现在这里,具体过程为先用需要交易的输入代币,输出代币,以及一系列可用的中间代币(代码中叫 Base token)生成所有的路径(当然为了降低复杂度,路径中最多包含3个代币),然后遍历每个路径输出的输出代币数量,最后选取最佳路径。
事实上因为 v3 引入了费率的原因,在路径选择的过程中还需要考虑费率的因素。关于交易结果的预计算,可以参考本文末尾处更新的内容。
40 替换国际化路径的正则
请忽使用,稍稍有点问题
(?<=#: src/pages/LiquidityMining/)PledgeH5.(?=tsx[\s\S\r]msgid "Expand")
41 让图片切换具有过渡效果-将图片当做背景图
目前发现问题:
如果加上动画,在IPhone上图片会闪动
.image-container {
background: url('./assets/default.png') center center no-repeat;
background-size: contain;
width: 20px;
height: 20px;
-webkit-transition: all .3s ease-in-out;
-moz-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.image-container:hover {
background-image: url('./assets/00linux图片.png');
}
<div class="image-container"></div>
42 vscode不提示hooks依赖问题
总结
2022-05-21 11:47:38
导致该问题最有可能原因是eslint配置有问题,运行,就可以看到具体配置错误
eslint
以前解决思路
一般为setting.json配置问题,注意开启setting.json的 eslint.validate
"eslint.validate": ["typescript", "typescriptreact"]
下面为package.json
{
"name": "@uniswap/interface",
"description": "Uniswap Interface",
"homepage": ".",
"private": true,
"devDependencies": {
"@ethersproject/experimental": "^5.2.0",
"@lingui/cli": "^3.9.0",
"@lingui/loader": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@metamask/jazzicon": "^2.0.0",
"@popperjs/core": "^2.4.4",
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.3.5",
"@typechain/ethers-v5": "^7.0.0",
"@types/jest": "^25.2.1",
"@types/lingui__core": "^2.7.1",
"@types/lingui__macro": "^2.7.4",
"@types/lingui__react": "^2.8.3",
"@types/lodash.flatmap": "^4.5.6",
"@types/luxon": "^1.24.4",
"@types/multicodec": "^1.0.0",
"@types/node": "^13.13.5",
"@types/qs": "^6.9.2",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.1",
"@types/react-redux": "^7.1.16",
"@types/react-router-dom": "^5.0.0",
"@types/react-virtualized-auto-sizer": "^1.0.0",
"@types/react-window": "^1.8.2",
"@types/rebass": "^4.0.7",
"@types/styled-components": "^5.1.0",
"@types/testing-library__cypress": "^5.0.5",
"@types/ua-parser-js": "^0.7.35",
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@uniswap/default-token-list": "^2.0.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
"@uniswap/token-lists": "^1.0.0-beta.19",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.0-alpha.2",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "1.0.0",
"@uniswap/v3-sdk": "^3.0.0-alpha.9",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/portis-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^6.2.0",
"@web3-react/walletlink-connector": "^6.2.0",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"copy-to-clipboard": "^3.2.0",
"cross-env": "^7.0.2",
"cypress": "^4.11.0",
"eslint": "^7.11.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^4.0.0",
"ethers": "^5.2.0",
"inter-ui": "^3.13.1",
"lightweight-charts": "^3.3.0",
"lodash.flatmap": "^4.5.0",
"luxon": "^1.25.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"node-vibrant": "^3.1.5",
"polished": "^3.3.2",
"prettier": "^2.2.1",
"qs": "^6.9.4",
"react": "^17.0.1",
"react-confetti": "^6.0.0",
"react-device-detect": "^1.6.2",
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-ga": "^2.5.7",
"react-markdown": "^4.3.1",
"react-popper": "^2.2.3",
"react-redux": "^7.2.2",
"react-router-dom": "^5.0.0",
"react-scripts": "^4.0.3",
"react-spring": "^8.0.27",
"react-use-gesture": "^6.0.14",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"rebass": "^4.0.7",
"redux-localstorage-simple": "^2.3.1",
"serve": "^11.3.2",
"start-server-and-test": "^1.11.0",
"styled-components": "^4.2.0",
"styled-system": "^5.1.5",
"typechain": "^5.0.0",
"typescript": "^4.2.3",
"ua-parser-js": "^0.7.28",
"use-count-up": "^2.2.5",
"wcag-contrast": "^3.0.0",
"workbox-core": "^6.1.0",
"workbox-expiration": "^6.1.0",
"workbox-precaching": "^6.1.0",
"workbox-routing": "^6.1.0",
"workbox-strategies": "^6.1.0"
},
"resolutions": {
"@walletconnect/web3-provider": "1.4.2-rc.2"
},
"scripts": {
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
"compile-external-abi-types": "typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
"compile-v3-contract-types": "typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
"build:pro": "yarn compile-contract-types && yarn i18n:extract && yarn i18n:compile && react-app-rewired build",
"build:test": "REACT_APP_ENV=development yarn compile-contract-types && yarn i18n:extract && yarn i18n:compile && react-app-rewired build",
"i18n:extract": "lingui extract --locale en-US",
"i18n:extract:en": "lingui extract --locale en-US",
"i18n:extract:cn": "lingui extract --locale zh-CN",
"i18n:extract:tw": "lingui extract --locale zh-TW",
"i18n:extract:jp": "lingui extract --locale ja-JP",
"i18n:extract:ru": "lingui extract --locale ru-RU",
"i18n:extract:ko": "lingui extract --locale ko-KR",
"i18n:extract:de": "lingui extract --locale de-DE",
"i18n:extract:vi": "lingui extract --locale vi-VN",
"i18n:extract:id": "lingui extract --locale id-ID",
"i18n:extract:all": "yarn i18n:extract:en && yarn i18n:extract:tw && yarn i18n:extract:cn && yarn i18n:extract:de && yarn i18n:extract:ko && yarn i18n:extract:ru && yarn i18n:extract:jp && yarn i18n:extract:vi && yarn i18n:extract:id ",
"i18n:compile": "lingui compile",
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
"postinstall": "yarn compile-contract-types",
"start": "yarn compile-contract-types && react-scripts start",
"test": "react-scripts test --env=jsdom"
},
"eslintConfig": {
"extends": "react-app",
"ignorePatterns": [
"node_modules"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"license": "GPL-3.0-or-later",
"dependencies": {
"@apollo/client": "^3.4.7",
"add": "^2.0.6",
"antd": "^4.16.8",
"apollo-boost": "^0.4.9",
"bignumber.js": "^9.0.1",
"compression-webpack-plugin": "^8.0.1",
"customize-cra": "^1.0.0",
"graphql": "^15.5.1",
"graphql-tag": "^2.12.5",
"node-fetch": "^2.6.1",
"progress-bar-webpack-plugin": "^2.1.0",
"react-app-rewired": "^2.1.8",
"uglifyjs-webpack-plugin": "^2.2.0",
"webpack-bundle-analyzer": "^4.4.2",
"yarn": "^1.22.10"
}
}
下面为.eslintrc.json
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
// Allows for the parsing of JSX
"jsx": true
}
},
"ignorePatterns": ["node_modules/**/*", "src/plugins/@uniswap/**/*"],
"settings": {
"react": {
"version": "detect"
}
},
"extends": [
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"rules": {
"@typescript-eslint/explicit-function-return-type": "off",
"prettier/prettier": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/explicit-module-boundary-types": "off"
}
}
43 vscode常用插件
vetur vue tool 提供vue代码语法高亮,格式化等
Auto Rename Tag 改标签名的时候,自动更改闭合标签名
Bookmarks 书签插件,记录代码重点,review的时候更容易get对应的点
Bracket Pair Colorizer 括号着色,对于多个嵌套的括号对应识别精准
Change Case 代码变量声明时候,可以对已有变量切换成驼峰式,常量式,其他的风格
Codelf 怎么命名
cssrem 一个CSS值转REM的VSCode插件
Live Server 提供对HTML的即时服务预览,代码改动即时刷新
Path Intellisense 路径引入智能感知
npm-intellisense npm module 引入智能感知
RegExp Preview and Editor 正则表达式预览和编辑
Settings Sync 同步你的vscode设置,包括插件,主题一切用户数据
SVG Viewer 预览SVG
Todo Tree 显示你代码里面的TODO列表
translate 翻译
Tslint ts代码格式检测工具
Version Lens npm version检测
vscode-fileheader 生成文档注释头
JavaScript (ES6) code snippets es代码片段
Copy Relative Path 复制相对路径
koroFileHeader 头部注释
vscode-icons 显示小图标
vscode-pdf 查看pdf
44 react animation library
yarn install react-spring
[1] https://docs.pmnd.rs/react-spring/introduction
44 react drag library
yarn add react-use-gesture
[1] https://use-gesture.netlify.app/
45 web3-react连接流程
TODO 1.画一个流程图出来
[1] https://github.com/NoahZinsmeister/web3-react
46 ::selection
属性可以改变网页文字选中样式
::selection {
background-color: #000;
/* 选中文字背景变为黑色 */
}
允许的属性,详见https://developer.mozilla.org/en-US/docs/Web/CSS/::selection
47 antd的切换图标最佳实践
TODO
48 ESLint 忽略特定的文件和目录
根目录建立 .eslintignore
**/*.js
# eslint忽略所有js文件
49 改变placehoder文字颜色
input::-webkit-input-placeholder {
color: red !important;
}
input:-moz-placeholder { /* Firefox 18- */
color: red !important;
}
input::-moz-placeholder { /* Firefox 19+ */
color: red !important;
}
input:-ms-input-placeholder {
color: red !important;
}
50 判断数字和小数点-只要数字类型
if (price) {
// 只要数字和小数点
if (!price.match(/^[\d\.]+$/g)) return
// 只要一个小数点
const hasOnlyOnePoint = price.match(/\./g)
if (hasOnlyOnePoint && hasOnlyOnePoint.length > 1) return
}