预备知识
- 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,通过比对,决定只需要对哪些部分进行更新