10-19
1 Babel
目的:
- babel是什么?做什么?
- babel原理?
一些重点:
- babel是基于插件的,如果没有配置插件(预设),则babel不会进行转化
一些关联问题:
- babel与corejs的关系是什么?babel的一个插件依赖corejs,详见问题二
- BrowserList是什么?babel的一个插件依赖BrowserList,详见问题一
- postcss插件又是干什么的?
- js中的Reflect(反射)是什么?
介绍:babel是一个能够将es2015(es6)以上的js语法转换为es5的语法。
// Babel Input: ES2015 arrow function
[1, 2, 3].map(n => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
问题一:Browserlist
babel与browserlist的关系:
By default @babel/preset-env
will use browserslist config sources unless either the targets or ignoreBrowserslistConfig options are set.
问题二:babel与corejs的关系是什么?
corejs 是一个现代填充库(Modular standard library for JavaScript.),支持 state>0
的Ecma-262的提案。
babel 是一个工具链,主要用于在当前和旧浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容的 JavaScript 版本。
注意:babel能够进行两部分转化,语法转化和API转化。
babel本身不带有任何作用,都是依靠插件进行工作,例如:@babel/preset-env、@babel/polyfill等
@babel/preset-env本身只有语法转化的功能,如果配置了useBuiltIns,则可以利用@babel/polyfill进行API填充,而@babel/polyfill本身利用corejs进行填充,所以这就是它们俩的关系。
但babel v7.4.0以上不在建议使用@babel/polyfill ,而是使用core-js/stable、regenerator-runtime/runtime代替。
再来看看 @babel/core
,它是babel的编译器,包含三个部分,@babel/paser、@babel/traverse、@babel/generator,也就是解析代码为AST、转化AST、生成代码
再来看看 @babel/preset-env
,它是babel的一组插件的集合,它能够将es2015+的代码转化为目标代码(默认为es5)
[1] babel,babel-core是什么关系?分不清他们的职责?.https://www.zhihu.com/question/277409645
[2] 了解babel:polyfill、loader、 preset-env及 core之间的关系.https://zhuanlan.zhihu.com/p/138108118
2 safeTransferFrom is not a function
原因:abi文件有多个方法,它会优先访问第一个方法
✅ 解决方案:删除多余方法即可,此处为safeTransferFrom方法
3 styled-components的生态系统
生态系统:https://styled-components.com/ecosystem
里面包含很多在styled-components基础上实现的库
import { ApolloClient, HttpLink, ApolloLink, InMemoryCache, concat } from '@apollo/client';
const httpLink = new HttpLink({ uri: '/graphql' });
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
authorization: localStorage.getItem('token') || null,
}
}));
return forward(operation);
})
const client = new ApolloClient({
cache: new InMemoryCache(),
link: concat(authMiddleware, httpLink),
});
4 nodejs的官网好好看一下
nodejs官网文档14.8.1:https://nodejs.org/dist/latest-v14.x/docs/api/fs.html#fs_promise_example
5 在react中想渲染空格的方法
有两种方法
第一种:用{' '}
<Text>{' '}123</Text>
=>> 123
第二种:用html标记符
123
=>> 123
6 jsdelivr的CDN缓存
在github上面的公开项目,如果打了一个版本号,那么自动进入jsdelivr的CDN缓存
第一步:发布一个版本
第二步:引用网址
https://cdn.jsdelivr.net/gh/你的用户名/你的仓库名@发布的版本号/文件路径
//例如:加载 jQuery v3.2.1
https://cdn.jsdelivr.net/gh/jquery/jquery@3.2.1/dist/jquery.min.js
7 package.workspaces属性作用
介绍:它能够指定多个包,而用 yarn
之后可以安装多个项目的依赖
示例:在根目录下安装多个项目的依赖
//root下
package.json
packages
-- A
-- -- package.json
-- B
-- -- package.json
在root目录下的package.json内容如下:
{
"name": "root",
"private": true,
"npmClient": "yarn",
"usingWorkspances": true,
"workspaces": {
"packages": [
"packages/*" //重点
],
"nohoist": [
"**/*",
"**/**"
]
},
}
而A下的package.json
{
"name": "@test/admin",
"version": "0.0.1",
"private": true,
}
B下的package.json
{
"name": "@test/sever",
"version": "0.0.1",
"private": true,
}
那么如果在根目录运行 yarn
,则会安装三个package.json对应的依赖,并在根目录的node_modules下挂载A、B包的依赖路径
7 [科普]小白如何理解UniswapV3白皮书
v2和v3的核心公式
其实,它们的核心公式都是
x*y = k
只是在v3中引入了虚拟数量,导致x和y分成了两部分
(x + △x)(y + △y) = k
所以图就像左下角移动了,流动性范围利用率提高了(橙色部分),而斜率(价格)不变。
添加流动性数量计算
区间内
L = delta x * (√p * √p_{upper}) / (√p_{upper} - √p)
L = delta y / √(p - p_{lower})
L表示k=𝐿^2,L=√k
p表示价格
delta x表示要添加的x数量
delta y表示要添加的y数量
高于区间
L = delta y / √(p_{upper} - p_{lower})
低于区间
L = delta x * (√p_{upper} * √p_{lower}) / (√p_{upper} - √p_{lower})
[1] 如何计算导数?https://www.shuxuele.com/calculus/derivatives-introduction.html
[2][科普]小白如何理解UniswapV3白皮书.https://learnblockchain.cn/article/3055
[3][科普]由浅入深理解uniswapV3原理【视频】.https://www.bilibili.com/video/BV1uq4y1N7o6?from=search&seid=12157076229729745114&spm_id_from=333.337.0.0
8 Typescript接口命名规范
不用加I
9 GraphQL
问题一:GraphQL与SQL的区别?
SQL是Structured Query Language
,GraphQL很显然,是Graph Query Language
,它们的区别如下:
- SQL的数据源是数据库,GraphQL的数据源可以是restful API,各种服务/微服务,或者数据库。
- MySQL是SQL的实现,Apollo, Relay也是GraphQL规范的实现
[1] GraphQL入门&server搭建(一).https://juejin.cn/post/6978395879040516110
问题二:GraphQL如何以以太坊网络的数据为数据源?
这里需要知道三个库:
- Graph Node – 一种服务器实现,用于对来自以太坊的数据进行索引、缓存和服务查询。
- Graph CLI – 用于构建和编译部署到 Graph 节点的项目的 CLI。
- Graph TypeScript Library – TypeScript/AssemblyScript 库,用于编写要部署到 The Graph 的子图映射。
大致流程为:程序员利用TS编写子图映射,通过CLI工具构建、编译和部署到Node上。Node会提供url以供GraphQL客户端查询(Apollo客户端,是GraphQL的实现)。
回到问题本身,我们可以看到是Node在帮我们操作,在获取以太坊网络的数据。
可以看以下图,表示前端Dapp应用和智能合约与整个以太坊网络的数据同步和检索的流程:
[1] graph协议.https://github.com/graphprotocol
[2] graph协议入门.https://github.com/graphprotocol/graph-node/blob/master/docs/getting-started.md
[3] assemblyscript.https://github.com/AssemblyScript/assemblyscript
问题三:如何基于已有的 REST API 实现 GraphQL API?
dad-joke-dadabase项目(爸爸笑话):https://github.com/thawkin3/dad-joke-dadabase
[1] 如何基于已有的 REST API 实现 GraphQL API.https://juejin.cn/post/6930911717950947341
10 死活安装不上 sharp
解决:回家重新yarn,安装上了,公司网络问题
11 雷电模拟器3.0无法使用 指针位置
功能
解决方案:需要在模拟器所在的VMS文件夹新建一个debug的空TXT文本
问题一:为什么用3.0的版本?
因为3.0支持学习强国的视频播放
[1] 开发者模式的指针位置开启后不起作用.https://www.ldmnq.com/forum/72566.html
12 Lua基础语法
模拟类写法
第一种:
Person = {}
Person.speak = function (self)
...
end
-- 调用
Person:speak()
第二种:
function Person:speak()
...
end
-- 调用
Person:speak()
逻辑运算符
or and not
获取时间戳
os.time()
-- 获取秒级别时间戳
抛出错误
error(msg, [level])
[1] Lua 基础简明教程.https://www.cnblogs.com/xiand/p/6699964.html
13 Mac安装MongoDB
不要怕麻烦,两步,下载、解压-> 配置环境变量
第一步:下载社区版MongoDB
https://www.mongodb.com/try/download/community
第二步:放到自己喜欢的目录(等下要用),解压
第三步:设置环境变量,让mongo命令生效
#mongo
export PATH="/Users/jiangjin/Documents/static-app/mongodb-macos-x86_64-5.0.3/bin:$PATH"
注意软件路径
14 box.shadow(x,y,模糊半径,扩散半径,颜色)
如题
15 yarn global add的软件无法在全局访问(Mac)
在 .bash_profile
中添加
export PATH="$PATH:`yarn global bin`:$HOME/.config/yarn/global/node_modules/.bin"
之后再source一下
source ~/.bash_profile
⚠️ 附,这样添加 无
效
export PATH="$PATH:`yarn global bin`"
export PATH="/Users/jiangjin/.yarn/bin:$PATH"
附,yarn查看全局安装路径
yarn global dir
[1][记录]解决MAC使用 yarn 安装全局包后找不到命令的问题.export PATH="$PATH:yarn global bin
:$HOME/.config/yarn/global/node_modules/.bin"
16 重新审视GraphQL
总体上来讲GraphQL分为查询(变更)语言、类型系统、执行和内省
查询和变更 | Schema 和类型 |
---|---|
字段(Fields) | 类型系统(Type System) |
参数(Arguments) | 类型语言(Type Language) |
别名(Aliases) | 对象类型和字段(Object Types and Fields) |
片段(Fragments) | 参数(Arguments) |
操作名称(Operation Name) | 查询和变更类型(The Query and Mutation Types) |
变量(Variables) | 标量类型(Scalar Types) |
指令(Directives) | 枚举类型(Enumeration Types) |
变更(Mutations) | 列表和非空(Lists and Non-Null) |
内联片段(Inline Fragments) | 接口(Interfaces) |
联合类型(Union Types) | |
输入类型(Input Types) |
还有验证、执行(resolver)、内省(查询支持类型)
查询语言
查询中又分为:别名、片段&内联片段、变量、指令、变更
变量
动态更改查询值
#JEDI是默认值
query HeroNameAndFriends($episode: Episode = "JEDI") {
hero(episode: $episode) {
name
friends {
name
}
}
}
指令
动态更改查询结构
query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
{
"episode": "JEDI",
"withFriends": false
}
GraphQL 的核心规范包含两个指令,其必须被任何规范兼容的 GraphQL 服务器实现所支持:
@include(if: Boolean)
仅在参数为true
时,包含此字段。@skip(if: Boolean)
如果参数为true
,跳过此字段。
变更
其实任何语句都可以实现变更,只是mutation语义上更加符合,具体实现要看resolver
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
#查询变量
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
注意,在多个 字段
变更请求中,执行是继发的。查询字段时,是并行执行,而变更字段时,是线性执行,一个接着一个。
类型语言
称之为 “GraphQL schema language”
type Character {
name: String!
appearsIn: [Episode!]!
}
类型分为:标量类型和复杂类型,复杂类型以标量类型为基础堆叠起来的类型。例如:枚举、列表、接口、联合、输入类型
标量类型有
Int
:有符号 32 位整数。Float
:有符号双精度浮点值。String
:UTF‐8 字符序列。Boolean
:true
或者false
。ID
:ID 标量类型表示一个唯一标识符,通常用以重新获取对象或者作为缓存中的键。ID 类型使用和 String 一样的方式序列化;然而将其定义为 ID 意味着并不需要人类可读型。
当然,还可以实现自定义标量类型
枚举类型
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
列表和非空
type Character {
name: String!
appearsIn: [Episode]!
}
!
表示非空字段,如果它结果得到了一个空值,那么事实上将会触发一个 GraphQL 执行错误,以让客户端知道发生了错误。
myField: [String!]表示非空内容,内容不能为null
myField: [String]!表示非空列表,列表不能为null
接口
interface Character {
id: ID!
name: String!
friends: [Character]
}
实现接口
type Human implements Character {
id: ID!
name: String!
friends: [Character]
#其他类型
otherFiled1: Int
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
otherFiled2: String!
}
联合类型
union SearchResult = Human | Droid | Starship
注意,联合类型的成员需要是具体对象类型;你不能使用接口或者其他联合类型来创造一个联合类型。
输入类型
从客户端传递复杂类型
input ReviewInput {
stars: Int!
commentary: String
}
#通过输入的$review去查询内容
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
输入类型示例(示例来源[1])
type Account {
name: String
age: Int,
sex: String,
salary(city: String): Int
}
input AccountInput {
name: String
age: Int,
sex: String
}
type Mutation {
createAccount(input: AccountInput): Account
}
那如何传参呢?如下:
mutation {
createAccount(input: {
name: "李四"
age: 10
sex: "女"
}) {
name
}
}
其实这里和上述的传参方式没啥区别,唯一的不同就是类型的转变,这里变成了对象方式的传参。
在 @apollo/client
客户端中如何传递数据呢?下面是react中的实例代码(参考[2]):
import { ApolloClient, InMemoryCache } from '@apollo/client'
import { THEGRAPH_URL } from '../services/config'
export const client = function (url: string) {
return new ApolloClient({
uri: '...',
cache: new InMemoryCache({
typePolicies: {
Token: {
// Singleton types that have no identifying field can use an empty
// array for their keyFields.
keyFields: false,
},
Pool: {
// Singleton types that have no identifying field can use an empty
// array for their keyFields.
keyFields: false,
},
},
}),
queryDeduplication: true,
defaultOptions: {
watchQuery: {
fetchPolicy: 'no-cache',
},
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
},
})
}
const result = client(url).query({
query: graphSql,
variables: {}, //这里传参
})
[1] GraphQL从入门到起飞.https://juejin.cn/post/6897173001373483021#heading-33
[2] uniswap_v3项目
内省
内省能干啥?用于查询GraphQL支持哪些东西
询问哪些类型是可用的
#询问哪些类型是可用的
{
__schema {
types {
name
}
}
}
#回答
{
"data": {
"__schema": {
"types": [
{
"name": "Query"
},
{
"name": "String"
},
{
"name": "ID"
},
...
{
"name": "ReviewInput"
},
{
"name": "__Type"
},
...
{
"name": "__DirectiveLocation"
}
]
}
}
}
说明:__Directive - 这些有着两个下划线的类型是内省系统的一部分。
询问所有查询开始的地方
{
__schema {
queryType {
name
}
}
}
#回答
{
"data": {
"__schema": {
"queryType": {
"name": "Query"
}
}
}
}
询问特定的类型
{
__type(name: "Droid") {
name
kind #更深入了解类型
}
}
#回答
{
"data": {
"__type": {
"name": "Droid",
"kind": "OBJECT"
}
}
}
询问它有哪些字段,列出它的 名称
以及 类型的名称
和 类型的种类
{
__type(name: "Droid") {
name
fields {
name
type {
name
kind
}
}
}
}
#回答
{
"data": {
"__type": {
"name": "Droid",
"fields": [
{
"name": "id",
"type": {
"name": null,
"kind": "NON_NULL"
}
},
{
"name": "name",
"type": {
"name": null,
"kind": "NON_NULL"
}
},
{
"name": "friends",
"type": {
"name": null,
"kind": "LIST"
}
},
]
}
}
}
ofType可以查询包装类型
ofType {
name
kind
}
#回答
"ofType": {
"name": "String",
"kind": "SCALAR"
}
17 fetch使用方法
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
⚠️ 注意要从.json中拿到数据
const res = await fetch('http://example.com/movies.json')
const data = await res.json()
//要解析为json格式
18 Apollo客户端配置异步uri
总体思想为:利用 fetch
属性支持异步函数,来进行异步获取uri
const customFetch = async (uri, options) => {
//异步获取uri
const { operationName } = JSON.parse(options.body);
return fetch(`${uri}/graph/graphql?opname=${operationName}`, options);
};
const link = new HttpLink({ fetch: customFetch });
⚠️ 注意:customFetch每次请求都会进来,所以建议不要在customFetch内部进行请求,而是请求好,放入全局变量(或者状态管理器)中,在customFetch内部阻塞获取已请求好的uri即可
19 在nestjs中使用graphql
TODO
有一些问题:
1.在resolver中导入的类型,可以来自实体
import { Post } from './post.entity';
@Resolver((of) => Post)
2.@Qeury()装饰器
@Query(() => Post, { name: 'post' })
它一共有三个重载函数,第二个参数可以对该字段进行 描述
(字段名、描述、弃用原因、复杂的)
export interface QueryOptions extends BaseTypeOptions {
name?: string;
description?: string;
deprecationReason?: string;
complexity?: Complexity;
}
export declare function Query(): MethodDecorator;
export declare function Query(name: string): MethodDecorator;
export declare function Query(typeFunc: ReturnTypeFunc, options?: QueryOptions): MethodDecorator;
同理,mutation也有几个重载方法,MutationOptions选项与QueryOptions一致:
export declare function Mutation(): MethodDecorator;
export declare function Mutation(name: string): MethodDecorator;
export declare function Mutation(typeFunc: ReturnTypeFunc, options?: MutationOptions): MethodDecorator;