最近需要开发前端页面,记录学习笔记
nodejs
nodejs 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
npm
nodejs 的默认包装管理器,可以用于安装 nodejs 的模块。
使用方式
- npm install ${package}
本地安装。将安装包放到当前目录的 ./node_modules 下
加参数 –save 可以同时将包依赖加入到 package.json 的 dependencies
加参数 –save-dev 可以同时将包依赖加入到 package.json 的 devDependencies 节点下 - npm install ${package} -g
全局安装。将安装包放到 /usr/local 或者 nodejs 的安装目录。 - package.json 文件
放到工程目录,可以指定项目需要什么依赖,有哪些运行命令
yarn
也是 nodejs 的包管理工具
- yarn init
初始化一个项目 - yarn install
安装 package.json 中的依赖 - yarn global add xxx
全局安装 - yarn add ${package}
安装依赖,同时加到 package.json 的 dependencies 下 - yarn add ${package} –dev
安装依赖,同时加到 package.json 的 devDependencies 下 - yarn list
列出工程的所有依赖 - yarn global list
列出全局安装包 - yarn config get registry
查看安装源 - yarn config set registry https://registry.npm.taobao.org
切换为淘宝的安装源 - yarn config set registry https://registry.yarnpkg.com
切换为原来的安装源
nodejs 库
typescript
是 javascript 的一个超集,有类型检查
网上比较好的教程 TypeScript 入门教程
生成 typescript 应用的步骤有
- 生成 javascript 应用
- 添加 typescript 依赖
- 运行 node_modules.bin\tsc.cmd -init 生成 tsconfig.json
react
一个用于构建用户界面的 javascript 库,运行在 nodejs 环境
react-JSX
它允许 HTML 与 JavaScript 的混写
1 | // 两个 div 是 html 标签,而标签内用花括号包起来的是 javascript |
react-组件
React 允许将代码封装成组件,然后像插入普通 HTML 标签一样使用组件。组件可以用类定义,必须有一个成员 render 用于渲染页面。
react-组件的 properties 和 state
- props:表示组件的所有属性,属性在组件中是不可变的
- state:react 将组件看成是一个状态机,有一个初始状态,然后用户互动导致状态变化,再渲染 UI。
react-组件生命周期
组件的生命周期分为 3 个状态
- Mounting:已插入真实 DOM
- Unmounting:已移出真实 DOM
- Updating:正在被重新渲染
React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数
- componentWillMount()
- componentDidMount()
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState)
- componentWillUnmount()
create-react-app
用来生成 react 应用,并提供所有依赖和安装一个脚手架工具
全局安装后,可以用命令生成 react 工程
yarn create react-app ${appName}
react-app-rewired
用 create-react-app 生成的工程,在 package.json 会包含 react-scripts 依赖,而 react-scripts 会包含所有 react 的真正依赖以及配置
要想修改其中的配置(例如 webpack 的配置),需要用 eject 命令将所有依赖展开到 package.json 文件(不可逆)
react-app-rewired 的作用,就是在不 eject 的情况下,覆盖 create-react-app 的配置。
使用时,需要覆盖 package.json 中默认的 scripts 配置
1 | { |
接着在工程根目录中创建一个 config-overrides.js 文件,然后在 config-overrides.js 中修改需要的配置。
react-dom
DOM 和 React renderers 的入口
大部分 react 应用由此开始
1 |
|
cross-env
用于跨平台地设置及使用环境变量。Linux 和 Windows 中的环境变量语法不一样,用 cross-env 可以统一起来。
例如下面的代码定义了 PORT 变量
1 | { |
webpack
用于 js 压缩打包
antd
基于 react 的 UI 库
axios
ajax 库,用于 ajax 请求
less
一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展
redux
redux 是 javascript 状态容器,提供可预测化的状态管理,官网
使用 redux 会使应用变得复杂。以下场景适合使用 redux
- 用户的使用方式复杂
- 不同身份的用户有不同的使用方式(比如普通用户和管理员)
- 多个用户之间可以协作
- 与服务器大量交互,或者使用了 WebSocket
- View 要从多个来源获取数据
redux 有两个基本的设计思想
- web 应用是一个状态机,视图与状态是一一对应
- 所有的状态,保存在一个对象里面
基本概念
- store:就是保存数据的地方,可以把它看成一个容器,整个应用只能有一个 store。
- state:是 store 对象包含所有数据。一个 state 对应一个 view,state 的变化,会导致 view 的变化。
注:redux 里的 state 和 react 中的 state 是不同的概念 - action:action 是 view 发出的通知,表示 state 要发生变化。action 有 type 属性的对象。
- action creator:view 要发送多少种消息,就会有多少种 action。如果都手写,会很麻烦。可以定义一个函数来生成 action,这个函数就叫 action creator。
- store.dispatch():调用后发出 action。
- reducer:store 收到 action 以后,必须给出一个新的 state,这种 state 的计算过程就叫做 reducer。reducer 函数需要是一个纯函数。
reducer 可以拆分成多个小的 reducer,由 combineReducers 组合起来。
redux 的一般工作流程如下图:
store 提供一个 subscribe 函数用于注册监听函数,可以在监听函数中重新渲染页面。
react-redux
redux 官方提供的 react 绑定库,详细可看 Redux 中文文档
react-redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。
UI 组件的特性有
- 只负责 UI 的呈现,不带有任何业务逻辑
- 没有状态(即不使用this.state这个变量)
- 所有数据都由参数(this.props)提供
- 不使用任何 Redux 的 API
窗口组件的特性有
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 使用 Redux 的 API
如果一个组件既有 UI 又有业务逻辑,将它拆分成外面是一个容器组件,里面包了一个 UI 组件。
react-redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 react-redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。
react-redux 提供 connect 方法,用于从 UI 组件生成容器组件。connect 的意思,就是将这两种组件连起来。使用 connect 生成的新组件,当属性发生变量时,就会重新渲染页面
例如:
1 | const NewCompent = connect ( |
mapStateToProps 是一个函数,建立一个从(外部的)state 对象到(UI 组件的)props 对象的映射关系。mapStateToProps 执行后应该返回一个对象,里面的每一个键值对就是一个映射
mapStateToProps 会订阅 Store,每当 state 更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。
mapDispatchToProps 建立 UI 组件的参数到 store.dispatch 方法的映射,定义了哪些用户的操作应该当作 Action,传给 Store
如果 mapDispatchToProps 是一个函数,会得到 dispatch 和 ownProps(容器组件的 props 对象)两个参数
如果 mapDispatchToProps 是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出。
Provider 包装 store 对象,使得所有地方都可以获取 store 对象而不需要将 store 对象作参数到处传递。
redux-saga
redux 有一个 middleware 的组件,它提供的是位于 action 被发起之后,到达 reducer 之前的扩展点。而 redux-saga 就是这样的一个扩展的 middleware,用于管理应用程序 Side Effect(副作用,例如异步获取数据,访问浏览器缓存等)。比较好的教程有 redux-saga 中文教程
sage 提供了一套原语用来管理异步操作。在 redux-saga 的世界里,所有的任务都通用 yield Effects 来完成。Effects 都是简单的 Javascript 对象,可以看作是redux-saga 的任务单元。常见的原语有:
Saga 辅助函数,用来在一些特定的 action 被发起到 Store 时派生任务
- takeEvery,表示每次 Action 被发起时,启动任务
- takeLatest,表示只为最新被的 Action 启动任务
redux-saga 框架提供了很多创建 effect 的函数,常见的有
- take(pattern)
take函数可以理解为监听未来的 action,它创建了一个命令对象,告诉 middleware 等待一个特定的 action, Generator 会暂停,直到一个与 pattern 匹配的action 被发起,才会继续执行下面的语句。所以 take 是一个阻塞的 effect。 - put(action)
put 函数是用来发送 action 的 effect,可以简单的把它理解成为 redux 框架中的 dispatch 函数,当 put 一个 action 后,reducer 中就会计算新的 state 并返回。put 是阻塞的 effect。 - call(fn, …args)
call 函数可以把它简单的理解为就是可以调用其他函数的函数,它命令 middleware 来调用 fn 函数, args 为函数的参数。注意:fn 函数可以是一个 Generator 函数,也可以是一个返回 Promise 的普通函数,call 函数也是阻塞 effect。 - fork(fn, …args)
fork 函数和 call 函数很像,都是用来调用其他函数的,但是fork函数是非阻塞函数。 - select(selector, …args)
select 函数是用来指示 middleware 调用提供的选择器获取 Store 上的 state 数据,可以简单的把它理解为 redux 框架中获取 store 上的 state 数据一样的功能:store.getState()
1 | // 创建一个 Redux 中间件,将 Sagas 与 Redux Store 链接起来 |
react-router-dom
react 路由组件,实现页面间的跳转。
其他
redux-saga 使用了 ES6 的 Generator 功能,让异步的流程更易于读取,写入和测试。相关的资料有 Generator 函数的含义与用法