- 本地环境搭建(来源于菜鸟教程):
-
$ npm install -g cnpm --registry=https://registry.npm.taobao.org $ npm config set registry https://registry.npm.taobao.org $ cnpm install -g create-react-app $ create-react-app my-app $ cd my-app/ $ npm start
2.为什么用JSX:
- React.createElement是创建虚拟DOM自带函数。
- 解决创建虚拟DOM复杂的问题。
- xml:记录、保存数据。
- Json代替,parase方法、stringfy方法。
- 定义虚拟DOM时,不需要加上引号。
- 标签中混入JS表达式时,需要使用{}。
- 表达式总结:与js语句(代码)的区别,表达式会产生一个值,可以放在任何一个需要值的地方(就是可以拿一个变量去接住它的返回值)。而语句就是没有返回值。
- 样式的类名指定用className指定。
- 内联样式要用双大括号包含起来,并且要用驼峰形式。
- 虚拟dom必须只有一个根标签。
- 标签必须闭合。
- 标签首字母:小写的话则将这个标签转为html中的同名元素,如果大写字母react就会去渲染对应的组件,没有就会报错。
- 给React一个数组,它可以遍历。给它一个对象,它无法识别。
- li必须要一个唯一的key。
3.虚拟DOM:
- 本质是Object类型的一般对象。
- 虚拟DOM比较轻量,真实DOM比较繁杂,因为虚拟DOM只是react内容使用,不需要真实DOM上面那么多的属性。
- 虚拟DOM会被转换为真实DOM,呈现在页面上。
4.模块、组件、模块化、组件化:
- 模块:js文件。复用js代码,提供js运行效率。
- 组件:用来实现局部功能的代码和资源的集合(css、html、js、imag等),简化项目编码,提供项目运行效率。
- 当应用的js以模块来编写,这个应用就是一个模块化应用。
- 当应用是以多组件的模式来编写,这个应用就是一个组件化应用。
5.组件化开发;
-
函数式组件:
-
首字母大写,render里面写标签不是写函数,标签必须闭合。
-
因为被bebel转换后开启了严格模式,所以函数组件中的this没有指向window。
-
函数名就是组件名。
-
render执行了函数式组件标签发生了:
-
React解析函数式组件标签。
-
找到该函数。
-
调用它。
-
将返回的虚拟DOM转为真实DOM,展示出来。
-
类式组件:
-
一般定义不需要构造函数。
-
必须有render且包含return。
-
render执行了类式组件标签发生了:
-
找到这个类。
-
调用new去创建这个类的实例,调用实例的render方法。
-
Vdom转真实dom。
-
显示。
-
有状态的就是复杂组件(function暂时是简单组件,因为它调用时没有成一个类,也就没有实例):
-
组件实例的state:
-
在构造函数中初始化。
-
原生事件的onclick里面是当成JS代码执行,而React里面是传入一个函数名就行了。
-
类组件中定义的 数中的this如果没有指定的话,指向undefined,所以元素调用时,需要将该函数用bind函数绑定this的执行环境,不是通过实例调用的方法没法指向实例。
-
状态不可直接更改,需要调用setState更改。这种更新是合并,不是替换。
-
构造函数调用一次,而render函数调用1+n次,n是指状态改变的次数。
-
需要初始化state状态,需要在构造函数中初始化。
-
类中可以直接写赋值语句。相当于直接给实例定义一个属性和值。
-
直接给类中的方法用箭头函数定义,就可以不用在构造函数中重定向this。
-
组件也被称为状态机。
-
props学习:
-
render里面的return后面是()。
-
...扩展运算符,展开一个数组,连接数组。不能展开对象。
-
{...对象}可以深拷贝一个对象,ES6语法。
-
react+babel可以让开发者使用...去扩展一个对象。但是仅用于标签属性的传递。
-
react元素里的{}是执行js语句的意思,和原生的{}含义不同,注意区别。
-
使用PropTypes插件进行类型检测。
-
使用defaultProps进行默认值设置。
-
简写props可以把类的属性直接用static关键词修饰放到类内部。不然在类里面定义的是放在实例上面的。
-
通常React中构造函数用于以下两种情况:
-
通过给this.state赋值对象来初始化内部state。
-
为事件处理函数绑定实例。
-
构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props。
-
函数式组件使用props:
-
直接解析调用就行。
-
refs属性使用
-
字符串使用模式已经要被弃用,因为其会引起一些效率问题。
-
回调式使用refs。回调函数就是你定义的函数你没去调用。直接在ref属性中写回调函数拿到当前节点使用。内联调用回调函数会出现更新DOM时,调用两次的bug。第一次会输入null,是为了清空之前的函数定义。因为React为了效率问题,先清楚之前的函数定义。而把内联函数改为实例上定义的方法就不会出现这个问题,因为这样React就知道这个方法是之前已经使用过的方法。
-
还可以使用createRef API的调用来创建refs:React.createRef()可以创建一个容器,可以容纳存储ref标识的节点。直接去里面取得节点就行了。该容器独立的,不能多个元素共存。
-
事件处理:
-
自定义事件,是为了更好的兼容性。
-
使用事件委托。
-
同样可以使用event.target拿到事件触发对象。
-
不要过度使用ref。
-
表单默认提交为get方式,表现为query。
-
非受控组件:现用现取输入类组件。
-
preventDefault()是阻止默认事件。
-
受控组件:改变过程中更新state,类似于Vue的双向绑定。可以帮助减少ref的使用。
-
高阶函数和函数柯里化:
-
接受函数作为传入参数或者返回值即为高阶函数。
-
Promise
-
settimeout
-
数组的很多方法是高阶函数
-
函数柯里化:函数作为返回值,最后统一处理所有传入参数。
-
React生命周期学习:
-
挂载组件——mount,卸载组件——unmount。
-
生命周期回调函数,生命周期钩子函数。
-
挂载时:constructor、componentWillMount、render、componentDidMount、componentWillUnmount。
-
更新时:
-
setState、shouldcompentUpdate、componentWillUpdate、render、compentDidUpdate。
-
forceUpdate,不经过shouldcomponentUpdate直接下面的钩子函数。
-
父组件更新引起子组件的生命周期的触发:compeonentWillRecevieProps,第一次不算,后面才算触发。其他钩子是正常的。
-
以上是旧的生命周期,总结如下:
-
用的最多的生命周期函数:
-
render
-
componentDidMount-多用于一些初始化操作:例如开启定时器、定位等
-
componentWillUnmount-多用于停止定时器、释放内存等。
-
新的生命周期对比:
-
componentWillMount、componentWillUpdate、compeonentWillRecevieProps前面必须加上UNSAFE前缀。表示后面版本中这三个函数可能会出现问题。
-
新出现两个生命周期:
-
getDerivedStateFromProps:用于当state由props决定时的场合。
-
getSnapshotBeforeUpdate:用户记录更新之前的一些信息。
-
以上是新的生命周期,总结如下:
-
新增两个生命周期钩子。
-
render
-
componentDidMount-多用于一些初始化操作:例如开启定时器、定位、发起网络请求等等
-
componentWillUnmount-多用于停止定时器、释放内存等。
-
React Diff算法:
-
最小维度是标签。
-
逐层对比:
-
对比的 旧数据的Vdom和新数据的Vdom。
-
Vdom上面标签的属性很少,例如input就没有value属性。
-
key的作用: