一、构建项目

脚手架:自动一个大型项目的目录 但不能直接运行 还需要脚手架进行编译
React官方提供一个脚手架工具:


把上次访问的网页存储在浏览器里

二、React基本使用

在子组件中 解构赋值:

在index.js中 使用ReactDOM把APP 组件 挂载到 id=root 的DOM节点上



是一个JSX语法 为了正常运行JSX语法 必须引入React 必须

JSX语法:

可以使用HTML5标签 
也可以使用自己组件的自定义标签  不用再标签外面包裹单引号' '
如果要使用自己创建的组件 可以通过自定义的标签(开头必须大写)<App />


使用React编写todoList功能

首先创建这个组件

在render函数里,return回来的内容在最外层必须包裹一个标签 如:

如果想要在外面包裹一层 又不想显示出来 可以使用占位符Fragment

引入,使用Fragment替代div 既能包裹 又不显示 真好 


React中的响应式设计思想和事件绑定
不是直接操作DOM 而是操作数据 不用关注DOM操作
React要把数据定义在状态state里

并且可以调用这些数据 在JXS中使用JS表达式要加上{ }

React可以感应数据的变化,并且响应
可是此时input框的值没法改变,被写死为inputValue 成了个单向绑定 如果想要双向绑定 就需要绑定onChange事件  并执行对应的事件处理程序

e.target:input框对应的DOM节点

但此时有一个问题:

这个时候this的指向undifined 为了让this指向该组件,需要进行绑定(这个思路需要牢记 )

想改变State里面的数据,需要使用setState方法:

1.用state存储组件数据
2.JSX里使用JS表达式 需要 { }
3.事件绑定里需要bind改变指向作用域
4.改变state数据需要setState( )函数来改变

实现列表新增功能,通过改变list数据内容:





实现删除功能
要注意两点
1.利用bind可以往回调函数里传递一些参数

2.修改state时要拷贝出来一个副本 修改这个副本 而不能直接修改state


JSX细节语法:

1.写注释


2.增加样式
单独创建一个.css文件 并在.js文件里引入 但此时使用的类选择器 class 会报错 
需要改为:

3.不对标签进行转义 直接按照<h1>的格式显示内容

4.label 扩大点击范围 但此时for也会报错  需要写成htmlFor


组件拆分与组件传值

在父组件中使用子组件 通过JSX语法

父组件向子组件传值,是通过属性的方式传递:

子组件通过props得到数据:

子组件调用父组件方法,修改父组件的值:
其实就是把父组件的方法传给子组件 子组件就可以调用这个方法了
注意:要用bind改变指向,将this绑定

在子组件中调用该方法,同样也需要bind绑定:
但为了提高性能,在constructor里进行bind绑定



代码优化

1.利用解构赋值美化代码

2.setState可以写成函数形式


也可以写成 还需要把target.value保存在外层

prevState 代表之前的数据 可以直接使用


对React的思考:

React是声明式的开发 而jQuery则是命令式的开发 
React只是一个视图层的框架,而不是大型完整的框架,只做页面上的一些渲染
React里 父组件可以给子组件传值 但是子组件不能修改值 这就是单向数据流 所以子组件只能通过调用父组件的方法来修改数据 本质上还是父组件在修改数据

三、Reacgt高级内容

PropTypes DefaultProps


PropTypes 对父组件传来的属性做校验 规定类型 不能乱穿


如果不传 就不会校验 
可以强制必须要传


DefaultProps 默认值


props State render(原理)

当组件的state 或 props 发生改变的时候 render就会重新执行
当父组件的render函数重新执行时,它的子组件中的render也会跟着重新运行

React中的虚拟DOM

真实DOM的思路:

但存在缺陷:生成太多次完整DOM 耗费性能
改进思路:

但性能提升并不明显
而在React中,使用虚拟DOM:

所以,整体思路是:
J
下图就是一个JSX模板:

下图 方法1:JSX模板 方法2:createElement方法


Diff算法:
两个虚拟DOM比对的方式:Diff算法
Diff进行同层比对 比较出不同后 就把下面的重新替换掉:
循环中需要key值 将新旧值对应起来 如果没有key值比对会麻烦,
但要求原始和新的key值一致 所以不建议使用index作为key值 应该使用更为稳定的值作为key值

React中的ref

ref是一个引用,使用ref来操作DOM
可以使用e.target获取DOM节点 也可以使用ref获得DOM节点
在React中 ref 是一个函数 this.input指向此时的input标签对应的DOM元素

可用用this.input来替换e.target

但并不推荐使用ref 
因为setState是一个异步函数,如下代码,console.log可能在setState之前执行,因此获得的DOM结果可能出错

如果想要在页面更新完成后获取DOM 则需要把console写在setState的第二个函数里:


生命周期函数

生命周期函数指某一个时刻组件自动执行调用的函数
render就是一个生命周期函数,在数据发生变化时自动执行

Initialization:页面初始化
Mounting:第一次挂载时
componentWillMount:组件即将被挂栽到页面上时执行
componentDidMount:组件被挂在到页面之后被执行
Updation:组件被更新时
props或states
shouldComponentUpdate:组件被更新之前自动执行 返回一个布朗值  返回true 页面将会更新  返回false 就不更新
componentWillUpdate:组件被更新之前,会自动执行,但在shouldComponentUpdate返回true之后才被执行
componentDidUpdate:组件更新之后,会被执行

特殊的componentWillReceiveProps:
当一个组件从父组件接受了参数,只要父组件的render函数被重新执行,子组件的componentWillReceiveProps就会执行
如果这个组件第一次存在于父组件中,不会执行
如果这个组件之前就已经存在于父组件中了,才会被执行
Unmounting:把组件从页面上去除
componentWillUnmount:当这个组件即将从页面上剔除的时候,执行

生命周期函数是针对组件而言的,每个组件都有自己的生命周期函数

生命周期函数使用场景:

由于父组件render执行时,子组件也会重新渲染,造成了浪费,可以使用生命周期函数进行优化:
在子组件里:

React请求AJAX

把AJAX放在componentDidMount (因为该函数只被执行一次)但React本身没有封装AJAX请求模块 需要使用扩展工具  npm add axios
并且引入

使用Charles实现本地数据mock

模拟接口数据:
1.创建文件 todolist.json
2.在json里写个数组
3.使用Charles配置 当向外发送请求时 把本地的数据返回回去

4.将返回的数据挂载上


react-transition-group动画框架

是个第三方模块 需要添加