mac使用记录
1. Homebrew
tip
mac安装软件使用brew,安装完brew后注意终端的提示,需要操作两步设置brew的path node、git等尽量都别手动安装,不然卸载很痛苦~
- brew help
- brew list
- brew install
- brew update
- brew uninstall
2. vscode的code命令
- 打开VSCode –> command+shift+p –> 输入shell command –> 点击提示Shell Command: Install ‘code’ command in PATH运行
- 打开终端,cd到要用VSCode打开的文件夹,然后输入命令
code .
即可打开
3. 右键打开终端
在文件(夹)上右键--->服务--->新建位于文件夹位置的终端窗口
4. 显示(或者隐藏)隐藏的文件
Shift+Command+(.)
5. 卸载手动安装的node
运行如下命令:
sudo rm -rf /usr/local/{lib/node{,/.npm,_modules},bin,share/man}/{npm*,node*,man1/node*}
您必须注意,如果您运行此特定命令,您并没有实现完整的卸载 Node 任务。 那是因为主目录或主目录不会受到影响。 因此,通过这种方式,您仍然必须删除在您的主目录中找到的相关文件和文件夹。
之后,您必须删除使用 NPM 安装的每个全局包。 为此,请在终端上运行以下命令
rm –rf ~/.npm
。 键入引号中的命令后,您将完成在 Mac 上卸载 Node 和卸载 NPM 的任务。
6. 远程连接
- ssh 连接远程服务器
- 执行
ssh 服务器用户名@服务器ip
,然后输入密码
- 执行
sftp 可以上传文件到远程或者从远程下载文件,例如:要将本地的b文件夹(a/b/c.txt) 放到 远程e/f下面
- 在远程e/f下 mkdir b
- 在本地cd a
- 执行
sftp 服务器用户名@服务器ip
,然后输入密码 - cd e/f/
- 执行 put -pr b (要保留修改时间、访问时间以及被传输的文件的模式,请使用 -p 标志;-r 参数允许拷贝子目录和子文件)
- 退出 sftp: 使用 bye 或者 quit 或者 exit
sftp的一些命令
get remotefile [localfile]
远程文件传输到本地。mkdir directory
创建一个远程目录。rmdir path
删除一个远程目录。
warning
使用 put 命令,如果目录名称不存在于远程主机上的工作目录中,可能会报错。所以,首先在远程主机上创建一个具有相同名称的目录,然后从本地主机上传它。
7. kill端口号
sudo lsof -i :<PortNumber>
kill -9 <PID>
8. 鼠标方向调整
tip
系统偏好设置--->鼠标--->勾掉 滚动方向:自然
9. vscode快捷键
- Shift + Option + F 格式化代码
- Ctrl + - 返回上一步
10. 可视化查看/usr /tmp /var /etc等目录
进入“访达”的偏好设置,选择“边栏”,勾中“硬盘”,再使用Shift+Command+(.)
显示隐藏文件
11. 截屏
Shift ⇧ + Command ⌘ + 5
12. 快速查看
若要在不打开文件的情况下查看其预览,请选择文件,然后按下空格键。
meteor
Meteor是一个强大的JavaScript全栈开发平台,它允许开发者使用单一语言(JavaScript)来构建实时Web和移动应用。以下是Meteor的详细介绍:
核心特性:
a. 实时数据同步:Meteor使用DDP(Distributed Data Protocol)协议,实现客户端和服务器之间的实时数据同步。
b. 响应式编程:通过响应式编程模型,UI会自动更新以反映数据的变化。
c. 全栈反应性:从数据库到模板,整个栈都是反应式的。
开发环境:
a. 集成的构建工具:Meteor提供了内置的构建系统,简化了开发流程。
b. 热代码推送:代码更改后自动更新运行中的应用,无需手动刷新。
数据库集成:
a. MongoDB集成:Meteor默认使用MongoDB,并提供了方便的API进行数据操作。
b. 最小化延迟补偿:客户端可以立即看到更改,而不必等待服务器响应。
前端集成:
a. Blaze:Meteor的原生模板引擎,简单易用。
b. React和Angular支持:可以与这些流行的前端框架无缝集成。
包管理:
a. Atmosphere:Meteor专用的包管理系统,提供了大量的Meteor特定包。
b. npm支持:可以使用npm包,增加了可用资源的范围。
安全性:
a. 内置安全措施:如自动XSS保护。
b. 方法和发布/订阅模式:有助于控制客户端对数据的访问。
移动开发:
a. Cordova集成:可以使用Web技术构建原生移动应用。
b. 响应式设计支持:便于创建适应不同设备的应用。
部署:
a. Galaxy:Meteor官方的托管平台,简化了部署过程。
b. 可部署到其他平台:如Heroku、DigitalOcean等。
社区和生态系统:
a. 活跃的社区:提供支持和资源。
b. 丰富的第三方包和工具。
学习曲线:
a. 对于初学者来说相对友好。
b. 对于有JavaScript经验的开发者尤其容易上手。
性能考虑:
a. 实时特性可能在大规模应用中带来挑战。
b. 需要careful优化以处理高负载。
使用场景:
a. 实时应用:如聊天应用、协作工具。
b. 快速原型开发。
c. 中小型Web应用和移动应用。
总的来说,Meteor是一个强大而灵活的全栈框架,特别适合需要实时功能的应用开发。它的主要优势在于开发速度快、学习曲线平缓,以及强大的实时数据同步能力。然而,对于某些大规模或特殊需求的项目,可能需要考虑其他更专门的解决方案。
packageJson
package.json
官方配置
main
main
字段指定了当包被引入时(例如,通过require
或import
语句)应该默认加载的模块文件。这个字段通常用于指向包的主入口点。
如下,当用户执行require('some-package')
或import
相应的模块时,Node.js将会默认加载index.js
文件。如果main
字段没有被指定,Node.js会默认查找包根目录下的index.js
文件。
{
"name": "some-package",
"version": "1.0.0",
"main": "index.js"
}
main
字段是可选的,但是指定它可以让你的包更加清晰地表明其入口点是哪个文件,尤其是当你的主文件不叫index.js
时。
files
在package.json
文件中,files
字段是一个数组,它指定了哪些文件和目录应该包含在你的npm包中。当你发布一个包到npm时,files
数组可以用来过滤包含在你的包中的内容,确保只有重要的文件被上传,而不必要的或敏感的文件(如配置文件、测试文件、文档等)被排除在外。
如下,当你运行npm publish
发布你的包时,只有lib
目录和index.js
文件会被包含在你的npm包中。所有其他文件和目录都会被忽略。
{
"name": "your-package",
"version": "1.0.0",
"files": [
"lib/",
"index.js"
]
}
如果你没有在package.json
中指定files
字段,npm会默认包含所有目录下的文件,除了那些通过.npmignore
文件或.gitignore文件
(如果没有.npmignore
文件)明确忽略的文件。还有一些文件和目录总是会被忽略,比如.git
、node_modules
等。
bin
bin
字段用于定义一个或多个可执行文件的映射。这些可执行文件是项目提供的命令行工具或脚本。当你的包被安装为全局包(使用npm install -g
)或者作为其他项目的依赖时,这些可执行文件会被链接到系统的路径中,使得用户可以直接通过命令行调用它们。
如下,当my-cool-package
被安装后,my-cool-command
将会被链接到系统路径。用户可以在命令行中直接运行my-cool-command
来执行./bin/my-cool-command.js
文件。
{
"name": "my-cool-package",
"version": "1.0.0",
"bin": {
"my-cool-command": "./bin/my-cool-command.js"
}
}
如果你只有一个可执行文件,你也可以直接提供一个字符串而不是对象,在这种情况下,可执行命令的名称将默认使用包的名称。
{
"name": "my-cool-package",
"version": "1.0.0",
"bin": "./bin/my-cool-command.js"
}
private
如果你在 package.json
中设置了 "private": true
,那么 npm 将拒绝发布它。
这是防止意外发布私人存储库的一种方法。如果您想确保给定的包仅发布到特定registry(例如内部registry),请使用 publishConfig
在发布时覆盖registry的配置参数。
publishConfig
npm 包在发布时使用的配置值。比如在安装依赖时指定了 registry 为 taobao 镜像源,但发布时希望在公网发布,就可以指定 publishConfig
:
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}
请参阅配置以查看可以覆盖的配置选项列表。
engines
peerDependencies
在 npm 版本 3 到 6 中,peerDependencies
不会自动安装,如果在依赖树中发现对等依赖项的无效版本,则会发出警告。从 npm v7 开始,默认安装peerDependencies
。
peerDependencies 的作用:
- 版本一致性:确保多个包使用相同版本的依赖。例如,多个 React 组件库可能需要确保它们使用相同版本的 React。
- 避免重复安装:防止在项目中安装多个版本的同一个依赖,从而减少包的体积和潜在的冲突。
- 明确依赖关系:让使用你包的开发者明确知道需要安装哪些额外的依赖。
第三方配置
一些第三方库或应用在进行某些内部处理时会依赖这些字段,使用它们时需要安装对应的第三方库。
module
module
字段是一个非官方的约定,用于指定一个包含ES6模块语法(即import
和export
语句)的入口点。这个字段主要用于构建工具和包管理器,以便它们可以在打包应用程序时优先使用ES模块版本的代码,这可能允许更好的摇树优化(tree-shaking)和其他模块化优势。
如下,main
字段指向了一个CommonJS模块版本的入口点,而module
字段指向了一个ES模块版本的入口点。当使用支持ES模块的工具(如Webpack、Rollup或其他现代JavaScript工具)时,这些工具可能会查找module
字段以获取ES模块版本的代码。
{
"name": "my-es6-module",
"version": "1.0.0",
"main": "dist/my-es6-module.cjs.js",
"module": "dist/my-es6-module.esm.js"
}
请注意,module字段不是Node.js官方支持的字段,它是社区约定的一个扩展。因此,Node.js本身在运行代码时不会使用这个字段,它主要是为了打包和构建工具设计的。
该字段来自关于如何将 ECMAScript 模块集成到 Node 中的提案。因此,用于指定 包的ECMAScript 模块的文件路径。比如,如果您的包名为 foo
,并且用户安装了它,然后执行 import {xxx} from 'foo
,那么将返回module
指定的文件的导出对象。
resolutions
在package.json
文件中,resolutions
字段是一个Yarn特有的功能,它允许你覆盖依赖项的子依赖项的版本。这意味着你可以指定项目中使用的特定包的版本,即使这些包是作为其他包的依赖项安装的。这在解决版本冲突或强制使用某个修复版本的包时非常有用。
例如,如果你想要为一个子依赖项指定一个版本,你可以在package.json
中这样写:
{
"resolutions": {
"some-sub-dependency": "1.2.3"
}
}
这将确保无论你的项目依赖树中的哪个包依赖some-sub-dependency
,Yarn都会安装版本1.2.3。
请注意,resolutions
字段是Yarn的一个特性,不是所有的包管理器都支持它。例如,npm就没有内置的等效功能。如果你使用的是npm,你可能需要使用其他工具或方法来解决依赖项版本的问题。
types
typings
指定 TypeScript 的类型定义的入口文件
"types": "./es/index.d.ts",
"typings": "./es/index.d.ts",
unpkg
unpkg是一个快速的全球内容交付网络(CDN),它可以为任何在npm上发布的包提供文件。
在package.json
文件中,unpkg
字段指定当用户通过unpkg CDN请求你的npm包时应该提供哪个文件,这通常是一个已经被转译和压缩的浏览器友好版本的文件,一般为UMD(Universal Module Definition)构建版本的文件。
例如:
{
"name": "your-package-name",
"version": "1.0.0",
"main": "index.js",
"unpkg": "dist/your-package.min.js"
}
在这个例子中,当用户通过unpkg CDN请求这个包时,CDN将提供位于dist/your-package.min.js
的文件。这使得用户可以很容易地在网页中通过一个<script>
标签直接引入这个包<script src="https://unpkg.com/your-package-name@1.0.0"></script>
,而不需要自己构建或打包。这个URL将会解析到你在package.json
文件的unpkg
字段中指定的文件。
如果没有指定unpkg
字段,unpkg CDN默认会提供main
字段指定的文件。
sideEffects
sideEffects
不是npm官方的标准,是Webpack 官方推出的私有属性。Rollup 也适配了这个属性。sideEffects
除了能设置 boolean 值, 还可以设置为数组, 传递需要保留副作用的代码文件。
sideEffects
字段是一个告诉打包工具(如Webpack)哪些模块是“有副作用”的。这个字段主要用于优化打包过程,如下表明包中的所有模块都没有副作用,因此打包工具可以自由地进行树摇(tree shaking),移除未使用的代码。
{
"name": "your-package",
"version": "1.0.0",
"sideEffects": false
}
实际项目中, 通常并不能简单的设置为 "sideEffects": false
, 有些副作用是需要保留的, 比如引入样式文件。比如在项目中整体引入 Ant Design 组件库的 css 文件。
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
如果 Ant Design 的 package.json
里不设置 sideEffects
,那么 webapck 构建打包时会认为这段代码只是引入了但并没有使用,可以 tree-shaking 剔除掉,最终导致产物缺少样式。
所以 Ant Design 在 package.json
里设置了如下的 sideEffects
,来告知 webpack,这些文件具有副作用,引入后不能被删除。
"sideEffects": [
"dist/*",
"es/**/style/*",
"lib/**/style/*",
"*.less"
]
lint-staged
commitlint
exports
在 package.json
文件中,exports
字段用于定义包的导出路径,以便消费者可以通过不同的入口点导入包的不同部分。这个字段在 Node.js 和现代打包工具(如 Webpack 和 Rollup)中非常有用,因为它允许你更精细地控制包的导出结构。
exports
字段是一个对象,其中键是导出路径,值是导出路径的目标。你可以使用不同的条件来定义不同的导出路径,例如 require
、import
、node
、default
等。
下面是一个示例,展示如何在 package.json
中使用 exports
字段:
{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"exports": {
".": {
"import": "./esm/index.js",
"require": "./cjs/index.js"
},
"./feature": {
"import": "./esm/feature.js",
"require": "./cjs/feature.js"
},
"./package.json": "./package.json"
}
}
"."
:表示包的主入口点。"import"
:用于 ES 模块导入(import
)。"require"
:用于 CommonJS 模块导入(require
)。
"./feature"
:表示包的一个子模块。"import"
:用于 ES 模块导入(import
)。"require"
:用于 CommonJS 模块导入(require
)。
"./package.json"
:允许消费者直接导入package.json
文件。
假设你有以下文件结构:
my-package/
├── cjs/
│ ├── index.js
│ └── feature.js
├── esm/
│ ├── index.js
│ └── feature.js
└── package.json
在你的项目中,你可以这样导入 my-package
:
// 使用 ES 模块导入
import { mainFunction } from 'my-package';
import { featureFunction } from 'my-package/feature';
// 使用 CommonJS 模块导入
const { mainFunction } = require('my-package');
const { featureFunction } = require('my-package/feature');
你还可以使用条件导出来根据不同的环境导出不同的模块。例如,你可以为浏览器和 Node.js 环境定义不同的导出路径:
{
"name": "my-package",
"version": "1.0.0",
"main": "index.js",
"exports": {
".": {
"browser": "./dist/browser/index.js",
"node": "./dist/node/index.js",
"default": "./dist/index.js"
}
}
}
在这个示例中:
"browser"
:用于浏览器环境。"node"
:用于 Node.js 环境。"default"
:用于默认导出路径。
通过这种方式,你可以更精细地控制包的导出结构,以便在不同的环境中使用不同的模块。
prepublishOnly
prepublishOnly
是 package.json
中的一个脚本钩子,它在 npm publish
和 npm install
(仅当安装的是本地包时)命令运行之前执行。这个钩子非常适合用于在发布包之前执行一些必要的构建或验证步骤。
你可以在 package.json
文件的 scripts
字段中定义 prepublishOnly
脚本。例如:
{
"name": "my-package",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "jest",
"prepublishOnly": "npm run build && npm test"
},
"devDependencies": {
"webpack": "^5.0.0",
"jest": "^26.0.0"
}
}
在这个示例中:
build
:定义了一个构建脚本,使用 Webpack 进行构建。test
:定义了一个测试脚本,使用 Jest 进行测试。prepublishOnly
:在发布包之前运行构建和测试脚本。
什么时候运行 prepublishOnly
:
npm publish
:当你运行npm publish
命令时,prepublishOnly
脚本会在发布包之前执行。npm install
:当你在本地安装包(例如npm install ./path/to/package
)时,prepublishOnly
脚本也会执行。
假设你有一个简单的项目结构:
my-package/
├── src/
│ └── index.js
├── dist/
│ └── index.js
├── package.json
└── webpack.config.js
你可以在 package.json
中定义 prepublishOnly
脚本,以确保在发布包之前进行构建和测试:
{
"name": "my-package",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "jest",
"prepublishOnly": "npm run build && npm test"
},
"devDependencies": {
"webpack": "^5.0.0",
"jest": "^26.0.0"
}
}
当你运行 npm publish
命令时,以下步骤将依次执行:
prepublishOnly
:首先执行prepublishOnly
脚本,即npm run build && npm test
。- 发布包:如果
prepublishOnly
脚本成功执行,包将被发布到 npm 注册表。
通过这种方式,你可以确保在发布包之前进行必要的构建和测试步骤,从而提高包的质量和可靠性。
使用package.json
const packageJson = require('./package.json')
const name = packageJson.name
patch-package
patch-package
是一个用于管理和应用对 node_modules
目录中依赖包进行补丁修改的工具。这对于在项目中临时修复第三方库中的问题或进行定制修改非常有用,而无需等待库的官方更新或发布。
安装 patch-package
首先,你需要将 patch-package
安装为开发依赖:
npm install patch-package --save-dev
或者使用 Yarn:
yarn add patch-package --dev
使用 patch-package
修改依赖包
在你的
node_modules
目录下找到需要修改的依赖包,并进行所需的更改。例如,假设你需要修改node_modules/some-package/index.js
文件。生成补丁文件
在完成修改后,运行以下命令来生成补丁文件:
npx patch-package some-package
这将在项目根目录下创建一个
patches
目录,并在其中生成一个名为some-package+<version>.patch
的文件。应用补丁文件
为确保补丁在每次安装依赖时都能自动应用,你需要在
package.json
文件中添加一个postinstall
脚本:"scripts": {
"postinstall": "patch-package"
}这样,当你运行
npm install
或yarn install
时,patch-package
会自动应用所有的补丁。
示例
假设你需要修改 some-package
的代码,以下是完整的步骤:
修改代码
打开并修改
node_modules/some-package/index.js
文件。生成补丁
运行以下命令生成补丁文件:
npx patch-package some-package
添加
postinstall
脚本在你的
package.json
文件中添加postinstall
脚本:{
"scripts": {
"postinstall": "patch-package"
}
}验证补丁
你可以删除
node_modules
目录并重新安装依赖,以验证补丁是否正确应用:rm -rf node_modules
npm install或者使用 Yarn:
rm -rf node_modules
yarn install
注意事项
- 版本控制:将生成的补丁文件(
patches
目录)提交到版本控制系统(如 Git),以确保团队成员都能应用相同的补丁。 - 依赖更新:如果第三方库更新了版本,你可能需要重新生成补丁文件,因为新的版本可能会覆盖或改变你之前的修改。
- 审查补丁:定期审查和管理补丁文件,确保它们是必要的,并且尽可能少地依赖于补丁。
patch-package
提供了一种简便的方法来管理对第三方依赖的临时修改,使你的项目在等待官方修复的过程中保持正常运行。
pixijs
polyfill和转译器
JavaScript 语言在稳步发展。也会定期出现一些对语言的新提议,它们会被分析讨论,如果认为有价值,就会被加入到 https://tc39.github.io/ecma262/ 的列表中,然后被加到 规范 中。
查看语言特性的当前支持状态的一个很好的页面是 https://kangax.github.io/compat-table/es6/
如何让我们现代的代码在还不支持最新特性的旧引擎上工作?有两个工作可以做到这一点:
- 转译器(Transpilers)
- 垫片(Polyfills)
转译器(Transpilers)
转译器 是一种可以将源码转译成另一种源码的特殊的软件。它可以解析(“阅读和理解”)现代代码,并使用旧的语法结构对其进行重写,进而使其也可以在旧的JavaScript引擎中工作。例如,在 ES2020 之前没有“空值合并运算符”。所以,如果访问者使用过时了的浏览器访问我们的网页,那么该浏览器可能就不明白
height = height ?? 100
这段代码的含义。转译器会分析我们的代码,并将height ?? 100
重写为(height !== undefined && height !== null) ? height : 100
。通常,开发者会在自己的计算机上运行转译器,然后将转译后的代码部署到服务器。
Babel 是最著名的转译器之一。
现代项目构建系统,例如 webpack,提供了在每次代码更改时自动运行转译器的方法,因此很容易将代码转译集成到开发过程中。
垫片(Polyfills)
新的语言特性可能不仅包括语法结构和运算符,还可能包括内建函数。例如,
Math.trunc(n)
是一个“截断”数字小数部分的函数,例如Math.trunc(1.23)
返回 1。在一些(非常过时的)JavaScript 引擎中没有Math.trunc
函数,所以这样的代码会执行失败。对于新增函数这类的新特性,由于不是语法更改或者新增运算符,因此无需转译任何内容,而是需要声明缺失的函数,进而使其也可以在旧的JavaScript引擎中工作。
更新/添加新函数的脚本被称为“polyfill”,它“填补”了空白并添加了缺失的实现。
Math.trunc
的 polyfill 是一个实现它的脚本,如下所示:if (!Math.trunc) { // 如果没有这个函数
// 实现它
Math.trunc = function(number) {
// Math.ceil 和 Math.floor 甚至存在于上古年代的 JavaScript 引擎中,所以在该polyfill中可以使用这俩函数
return number < 0 ? Math.ceil(number) : Math.floor(number);
};
}两个有趣的 polyfill 库:
- core js 支持了很多特性,允许只包含需要的特性。
- polyfill.io 提供带有 polyfill 的脚本的服务,具体取决于特性和用户的浏览器。
pv&uv
PV具体是指网站的是页面浏览量或者点击量,页面被刷新一次就计算一次,UV指访问网站的一台电脑客户端为一个访客。UV访客的统计是24小时内相同的客户端只被计算一次。一个UV可以用很多PV,一个PV也只能对应一个IP。PV是和IP的数量是成正比的,因为页面被刷新一次那么PV就会被记录一次,所以IP越多,说明网站的PV数据也就随之增多。但是需要注意的是PV并不是网站的页面的访问者数量,而是网站被访问的页面数量。因为一个访问者可以多次刷新页面,增加PV数量。
react-spring
react-spring 是一个用于构建交互式、数据驱动和动画 UI 组件的库。它可以为 HTML、SVG、Native Elements、Three.js 等制作动画。
yarn add @react-spring/web
pnpm add @react-spring/web
animated
组件
处理动画的实际组件是animated
组件,其是一个高阶组件 (HOC)。(高阶组件是一个接受一个组件并返回一个新组件的函数)
import { animated } from '@react-spring/web'
export default function MyComponent() {
return (
<animated.div
style={{
width: 80,
height: 80,
background: '#ff6d6d',
borderRadius: 8,
}}
/>
)
}
API
Globals
Globals
是一个内部对象,用于配置全局属性,比如默认的弹簧配置或插值器。这些全局设置会影响所有 react-spring 动画的默认行为。请注意,Globals
的使用应该谨慎,因为它会影响你应用中所有的 react-spring 动画。通常,它只在应用初始化时设置一次,并且很少需要修改。
skipAnimation
: 如果skipAnimation
设置为true
,那么动画将“跳转”到目标值,类似于immediate
属性为true
时。
import { useRef, useEffect } from 'react'
import { useSpring, animated, Globals } from '@react-spring/web'
export default function MyApp() {
const isRight = useRef(false)
const [springs, api] = useSpring(
() => ({
x: 0,
}),
[]
)
const handleClick = () => {
api.start({
x: isRight.current ? 0 : 200,
onRest: () => {
isRight.current = !isRight.current
},
})
}
useEffect(() => {
Globals.assign({
skipAnimation: true,
})
return () => {
Globals.assign({
skipAnimation: false,
})
}
})
return (
<animated.div onClick={handleClick} className="spring-box" style={springs}>
Click me!
</animated.div>
)
}
Hooks
useSpring
useSpring
实际上并没有为任何东西设置动画。它只是返回我们传递给animated
组件的 SpringValues
。以下是一些常用的属性:
from
: 定义动画开始时的样式或状态。to
: 定义动画结束时的样式或状态。config
: 定义动画的配置,如弹簧的张力(tension)、摩擦力(friction)等。delay
: 设置动画延迟开始的时间(以毫秒为单位)。reset
: 如果设置为 true,动画将重置到from
状态并重新开始。reverse
: 如果设置为 true,动画将从to
状态反向运行到from
状态。immediate
: 如果设置为 true 或一个函数返回 true,动画将立即跳转到结束状态,不会有过渡效果。onStart
: 动画开始时的回调函数。onRest
: 动画静止时的回调函数。onUpdate
: 动画更新时的回调函数。loop
: 如果设置为 true 或一个函数,动画将循环播放。pause
: 如果设置为 true,动画将暂停。
如下将useSpring
返回的springs
应用于animated
组件,则初始化时发生动画(向右移动):
import { useSpring, animated } from '@react-spring/web'
export default function MyComponent() {
const springs = useSpring({
from: { x: 0 },
to: { x: 100 },
})
return (
<animated.div
style={{
width: 80,
height: 80,
background: '#ff6d6d',
borderRadius: 8,
...springs,
}}
/>
)
}
useSpring
接收两种类型的参数,一种是如上的config对象,另一种是函数。当其参数是函数时,它返回一个数组:
import { useSpring, animated } from '@react-spring/web'
export default function MyComponent() {
const [springs, api] = useSpring(() => ({ // api用于控制springs
from: { x: 0 },
}))
const handleClick = () => {
api.start({ // api有许多不同的方法,我们可以使用它们来控制动画。
from: {
x: 0,
},
to: {
x: 100,
},
})
}
return (
<animated.div
onClick={handleClick}
style={{
width: 80,
height: 80,
background: '#ff6d6d',
borderRadius: 8,
...springs,
}}
/>
)
}
cancel
属性
当cancel
设置为true时,动画将停止工作,设置为false时,动画将重新开始。
useReducedMotion
rxjs
RxJS(Reactive Extensions for JavaScript)是一个强大的库,用于处理异步和事件驱动的编程。它基于观察者模式和迭代器模式,并融合了函数式编程的概念。以下是对 RxJS 的详细介绍:
核心概念
a. Observable:表示一个可观察的数据流 b. Observer:订阅 Observable 并响应其发出的值 c. Subscription:表示 Observable 的执行 d. Operators:用于处理数据流的纯函数 e. Subject:特殊类型的 Observable,可以多播给多个 Observer f. Schedulers:控制并发并且是中央调度员
主要特性
a. 声明式:以声明式而非命令式的方式处理异步操作 b. 可组合:使用操作符可以轻松组合复杂的异步操作 c. 可预测:通过使用纯函数使代码更加可预测 d. 更少的状态:通过流的方式处理数据,减少对状态的依赖 e. 流式:数据以流的形式处理,便于转换和组合
常用操作符
a. 创建操作符:of, from, fromEvent, interval b. 转换操作符:map, pluck, switchMap, mergeMap, concatMap c. 过滤操作符:filter, take, takeUntil, distinct, debounceTime d. 组合操作符:combineLatest, merge, concat, zip e. 错误处理:catchError, retry, retryWhen f. 多播操作符:share, shareReplay, publish
使用场景
a. 处理复杂的异步操作 b. 管理应用状态 c. 处理用户输入和事件 d. 实现实时功能(如自动完成、实时搜索) e. 处理 WebSocket 和 Server-Sent Events f. 实现可取消的 HTTP 请求
优点
a. 强大的操作符集合,可以处理各种复杂场景 b. excellent 的错误处理机制 c. 可以轻松实现背压(backpressure)处理 d. 便于测试,因为是基于纯函数的 e. 与其他库和框架(如 Angular)良好集成
挑战
a. 学习曲线较陡 b. 对于简单场景可能过于复杂 c. 调试可能较为困难 d. 性能问题(如果使用不当)
最佳实践
a. 使用适当的操作符,避免过度使用 mergeMap b. 正确处理订阅和取消订阅 c. 使用 pipeable 操作符以提高树摇(tree-shaking)效率 d. 适当使用 Subject 进行多播 e. 使用 takeUntil 操作符管理组件生命周期
与其他技术的比较
a. Promises:RxJS 更适合处理多个异步事件 b. Async/Await:RxJS 提供了更多的操作符和组合能力 c. Redux:RxJS 可以与 Redux 结合使用,处理副作用 d. MobX:RxJS 提供了更细粒度的控制
工具和扩展
a. RxJS Marbles:用于可视化 RxJS 操作符 b. RxJS DevTools:用于调试 RxJS 应用 c. RxJS-hooks:用于在 React 中使用 RxJS d. NgRx:Angular 的状态管理库,基于 RxJS
未来发展
a. 持续优化性能 b. 改进类型系统 c. 简化 API,降低学习曲线 d. 更好地支持响应式编程范式
RxJS 是一个强大而复杂的库,掌握它需要时间和实践。然而,一旦熟悉,它可以极大地提高处理复杂异步逻辑的能力,使代码更加清晰、可维护。