预备知识
- Node.js: 基于Chrome V8引擎的JavaScript 运行环境,使用了事件驱动、非阻塞I/O的模式
 - npm: node包管理工具
 - webpack:前端资源加载、打包工具,根据模块的依赖生成静态资源
 - ES6: js语言标准
 
React核心思想:声明式编程(注重结果而非实现),组件化(自定义label),虚拟DOM(减少渲染次数,diff算法)
环境搭建
利用脚手架create-react-app来安装react
1  | npm install -g create-react-app //安装脚手架  | 
1  | create-react-app my-app //会自动创建好Server Webpack 和 Babel  | 
此时报错:bash: create-react-app: command not found
应该是路径问题 改用命令npx create-react-app my-app , 还是不行
用npm root命令寻找npm 的根目录发现是 C:\Users\18771\node_modules  解决方法参考
1  | npm config set prefix /usr/local  | 
又报错 Unexpected end of JSON input while parsing near '...5mVz30VuXnFvjkEbnA5Oc'
进入 C:\Users\18771\AppData\Roaming\npm-cache 目录 执行 npm cache clean --force  解决方法参考
重新安装
切换到要创建项目的目录,执行 npx create-react-app my-app
报错 :
1  | npm ERR! code EINTEGRITY  | 
似乎是package-json 文件的问题
执行 npm cache verify 
再次尝试成功创建
1  | npx create-react-app my-app  | 
执行start 会自动在本地3000端口打开一个页面
在VS Code中安装 Simple React Snippets 和 Prettier插件
同时在setting.json中添加一行"editor.formatOnSave": true,  自动格式化后保存
在Chrome中添加插件 React Developer Tools 
实践
Babel 可以将 JSX 翻译为 react
boostraps
为了设计CSS ,安装bootstrap ,直接在VS Code 的集成终端输入 npm i bootstrap@4.1.1
在index.js 中导入 import "bootstrap/dist/css/bootstrap.css"; 
components
基本用法
新建counter.jsx文件写入组件代码
1  | import React, { Component } from "react"; //imrc  | 
- 由于装了插件,可以直接用简写;因为render()只能默认产生一个元素,所以多个标签要用<React.Fragment>包起来;
 - {}可以引用类中的成员或方法;
 - className=”btn btn-secondary btn-sm”是bootstrap中的样式;
 - style={this.styles} 自定义样式;
 - classes += this.state.count === 0 ? “warning” : “primary”; 可按数值变化样式
 - {this.state.tags.map(tag =>
 - {tag} )} map是一种遍历方法,为每个值设置一个key是为了react能区分出元素
 - 除了用class,还可以用stateless funciton 来写组件(sfc) 这也是一种比较常用的写法,只是不能用this关键字
 
然后在index.js中引用
1  | import Counter from "./components/counter";  | 
按不同条件进行渲染
1  | import React, { Component } from "react";  | 
- this.state.tags.length === 0 && “Please create a new tags!” 在js中 &&结果为真时,返回最后一个表达式
 - 新增一个方法用于条件判断
 
交互
1  | import React, { Component } from "react"; //imrc  | 
- button 中添加 *onClick= {this.handleIncrement} —注意没有跟() 并写好handleIncrement() 方法
 - this.handleIncrement = this.handleIncrement.bind(this); 主要是为了将this与当前的Counter 对象绑定—-还可以用箭头函数
 - this.setState({ count: this.state.count + 1 }); 需要用setstate显式更改状态才能显示在页面上
 
复合组件
props可以作为一个参数传入,将任意类型的数据传给组件,但是不能修改,定义时也要声明为static
state是在组件内部使用并可以修改的
父组件和子组件通信可以通过props进行信息传递,当子组件要更新父组件时,可以让父组件传一个回调函数给子组件,子组件通过调用实现父组件更新——很常用的一种做法
同级之间如果要相互通信,可以将一个的函数上升为共同的父组件的回调函数;或者采用react的上下文方式,子组件可以直接访问祖先组件的属性和方法
为避免写太多this.props ,可以定义 const {func1, func2...} = this.props  选出要用的方法,之后就可以不加this.props前缀了 
分清是模块控制还是全局控制
lifecycle&hooks
- 挂载期:constructor()—先调用super() ; render() —所有父子组件渲染完后才会挂载; componentDidMount() —常用于Ajax与Server交互
 - 更新期:componentDidUpdate()
 - 卸载期: componentWillUnmount() —从DOM树中删除组件之前调用,用于做一些数据清零工作避免内存泄露
 
每个阶段都有对应的钩子函数,按序执行
只能用于class组件不能用于stateless funciton组件
tips
- 同时修改前后标签,选中标签,Ctrl+d
 - 为了更好的封装,选中要转为方法的语句,右键,vscode提供了一个refactor功能,可以自动抽取出一个方法
 - true && ‘hi’ —> ‘hi’ 在js中 &&结果为真时,返回最后一个表达式
 - bootstrap一些设计案例,甚至可以直接搜索如“Navbar”, 会给出很多例子
 - react同时在内存保存有新和旧两份virtualDOM,通过比对,决定只需要对哪些部分进行更新