一、前言:
React的主要内容:
二、React的一些注意的知识点
- 1、serviceWorker用于离线情况下可以访问
- 2、pwa === Progressive web application 渐进式web应用。根据
manifest.json
来访问 - 3、React 16以上版本,使用Fragment 占位符,就不用外层再包裹一层div,比如:
<Fragment>
<div>xxx</div>
<ul>xxxx</ul>
</Fragment>
- 4、react中的响应式设计思想和事件绑定
- 5、class 类中就有一个constructor构造函数。组件在创建时,第一个执行的函数就是constructor函数。
- 6、immutable state不允许做任何改变
- 7、jsx写注释的方法
{/* xxxx */}
{
// 下面是一个input框
}
- 8、在jsx中,希望可以对标签内容不进行转译,需要使用到
dangerouslySetInnerHTML
进行设置,比如:
return (
<li
key={index}
onClick={this.handleItemClick.bind(this, index)}
dangerouslySetInnerHTML={{__html: item}}
>
</li>
)
- 9、在jsx中,样式要用
className
来定义css的名字,防止和class类冲突 - 10、在jsx中,label的for标签要替换为
htmlFor
,然后使用label的for属性来绑定到input上,如以下代码:
<label htmlFor="insertArea">输入内容</label>
// 把光标放在label上,就会自动聚焦到input上。
<input
id="insertArea"
className='input'
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
- 11、react衍生的思考
- (1)、声名式开发:不用直接操作dom,对比于命令式开发(jquery,原生js都是直接操作dom)
- (2)、可以与其他框架并存。
// 在html文件 <body> <div id="root"></root> // 这里挂载的是react代码。 <div>123123</div> // 这里可以挂载其他框架比如vue、angular、jquery的代码 </body>
- (3)组件化
- 【1】、组件的定义:通过class.Component来定义组件
- 【2】、组件: 首字母大写的,组件是树状结构,父组件通过属性向子组件传值。通过父组件向子组件传递一个方法,子组件调用这个方法间接的来操作父组件的方法,从而实现子组件和父组件的通信。
- (4) 单向数据流
- 【1】、父组件可以向子组件传值,但是子组件不能去改变这个值。
- (5) 视图层框架
- (6) 函数式编程
- [1]、好处:维护起来比较容易;给自动化测试带来很大的便捷性;
- 12、react扩展工具:React developer tools
- 13、propTypes与defaultProps
- propTypes对组件接收过来的属性做类型校验使用
TodoItem.propTypes = { test: PropTypes.string.isRequired, content: PropTypes.string, deleteItem: PropTypes.func, index: PropTypes.number }
- defaultProps 可以在里面定义组件传过来的默认值
- propTypes对组件接收过来的属性做类型校验使用
- 14、props、state与render函数
- 当组件的state或者props发生改变的时候,render函数就会重新执行。
- 当父组件的render函数被运行时,它的子组件的render都将被重新运行一次
- 15、react中的虚拟dom
- 虚拟dom就是一个js对象,用它来描述真实的dom
- 用js生成一个js对象比js生成一个dom的代价比较小。因为js直接生成dom需要调用createElementById等属性,所以性能消耗比较高。(减少了对正式dom的创建和对比,直接对比的是js对象,所以性能发生了极大的改进)
- 虚拟dom的底层原理:
1、state数据 2、jsx模版 3、数据+模版生成虚拟dom(虚拟dom就是一个js对象,用它来描述真实dom)(损耗了性能)。 ['div', {id: 'abc'}, ['span', {}, 'hello world']] 4、用虚拟dom的结构生成真实dom来显示 <div id="abc"><span>hello world</span></div> 5、state发生变化 6、数据+模版生成新的虚拟dom(极大的提升了性能) ['div', {id: 'abc'}, ['span', {}, 'bye bye']] 7、比较原始虚拟dom和新的虚拟dom的区别,找到区别中是span的内容(极大的提升了性能) 8、直接操作dom,改变span中的内容。
- jsx -> createElement -> 虚拟dom(js对象)-> 真实的dom
return <div>item</div> 等价于 return React.createElement('div', {}, 'item')
- 虚拟dom带来的好处
1、提升了性能 2、它使得跨端应用得以实现,React Native
- 虚拟dom中的diff算法
1、同层虚拟dom的比对算法,如果最上层的发生了改变,就不会继续对比了,直接用新的替换掉旧的 2、在循环的过程中,最好不要用index值做key值来进行标识,因为当key值发生变化的时候,index就发生了变化,从而使key值不唯一,增加对比的难度。要使用稳定的值作为key值。
虚拟dom中的同层比对算法。在进行虚拟dom的对比的时候,会先生成一个一样的虚拟dom,然后同层进行对比,当第一层的虚拟dom改变的时候,下面所有的虚拟dom都要被重新渲染,然后替换掉。虽然会增加多余的dom的渲染,但是这样可以简化dom的对比算法。
-
16、react中的ref
- 可以获取页面中dom元素(尽量不要用ref,在做动画的时候可能会不得不用到)
<input id="insertArea" className='input' value={this.state.inputValue} onChange={this.handleInputChange} ref={(todoInput) => { this.input = todoInput}} // ref在这里是一个回调函数,返回一个数值 /> handleInputChange() { // const value = e.target.value const value = this.input.value // 这里就可以直接使用ref的引用了。 this.setState(() => { return { inputValue: value } }) }
- ref使用经常遇到的一个问题
handleBtnClick() { this.setState((prevState) => ({ list: [...prevState.list, prevState.inputValue], inputValue: '' }), () => { console.log(this.ul.querySelectorAll('div').length) // 这里要写在setState的回调函数里面,因为setState是一个异步函数。 }) console.log() // 写在这里,会发现setState没运行完就执行了。 }
-
17、react中的生命周期函数
- 生命周期函数指在某一个时刻组件会
自动调用
执行的函数。 - initialization // 在state和props被改变,初始化时使用
- mounting---componentWillMount() // 在组件即将被挂载到页面的时刻自动执行
- mounting---render() // 在组件挂载在页面时执行
- mounting---componentDidMount() // 组件被挂载到页面之后,自动被执行
- 以上2个生命周期将在v17.0之后启用,取而代之的是getDerivedStateFromProps、getSnapshotBeforeUpdate这2个生命周期。
- updation 当数据发生变化的时候,页面的更新会被执行。
- updation---shouldComponentUpdate() // 组件被更新之前,他会自动被执行,含义是你的组件需要被更新吗?返回boolean类型,true则执行后面的,否则不执行,
- updation---componentWillUpdate() //组件被更新之前,它会自动执行,但是他在shouldComponentUpdate之后被执行。shouldComponentUpdate返回true才会执行,否则不会被执行。
- updation---componentDidUpdate() // 组件更新完成之后,它会被执行
- updation---componentWillReceiveProps() // 一个组件要从父组件接收参数,如果这个组件第一次存在于父组件中,不会执行,如果这个组件之前已经存在于父组件中,才会执行。
- unmounting---componentWillUnmount() // 当这个组件即将被从页面中剔除的时候会被执行。
- 生命周期函数指在某一个时刻组件会
-
18、在react中做性能提升
- (1)、利用shouldComponentUpdate生命周期做性能优化
shouldComponentUpdate(nextProps, nextState) { if (nextProps.content !== this.props.content) { // 如果传过来的内容和当前内容不同,则需要做数据的更新即render return true } else { return false } }
// 利用生命周期中shouldComponentUpdate的方法,先提前判断数据有没变化,再做比较,再看下是否要继续执行下去,从而可以避免过多不必要的render.
- (2)、将函数的作用域绑定都统一写在constructor函数中,这样保证整个函数的作用域绑定只会执行1次,可以避免组件的多次渲染
constructor(props) { super(props) this.handleClick = this.handleClick.bind(this) // 作用域的绑定 }
- (3)、setState,是一个异步函数,可以把多次的操作搞成1次来做,降低数据改变的频率。
- (4)、react的底层使用了虚拟dom的概念,还有同层对比和虚拟值来提升虚拟dom的比对速度,从而提升react的性能。
-
19、在componentDidMount中做ajax数据的请求。
componentDidMount() { axios.get('/api/todolist').then((res) => { console.log(res.data) this.setState(() => { return { list: [...res.data] } }) }).catch(() => { alert('error') }) }
-
20、使用react-transition-group实现动画
<TransitionGroup> { this.state.list.map((item, index) => { return ( <CSSTransition timeout={1000} classNames='fade' unmountOnExit onEntered={(el) => { el.style.color='blue'}} appear={true} key={index} > <div>{item}</div> </CSSTransition> ) }) } </TransitionGroup>
-
21、在使用css3做样式animation的时候,使用
forwards
可以让动画停留在最后一帧animation: hide-item 2s ease-in forwards;
-
22、redux
- (1)、Redux = Reducer + Flux
- (2)、redux 工具: redux devtools
- (3)、设计和使用的三个原则:
- 【1】、store是唯一的
- 【2】、只有store能够改变自己的内容
- 【3】、Reducer必须是纯函数数据(纯函数指的是给定固定的输入,就一定有固定的输出,而且不会有任何的副作用)
- 【4】、Redux核心API
- <1>、createStore 可以创建一个store
- <2>、store.dispatch 可以派发action,action会传递给store
- <3>、store.getState 可以帮助获取store的所有内容
- <4>、store.subscribe 可以订阅store的改变
- (4)、使用Redux-thunk中间件进行ajax请求
- (5)、什么是Redux中间件?
首先来看Redux工作流程
首先React Components就是View相当于借书的人,发出了Action Creators借书这个行为,然后通过dispatch去订阅Store(相当于图书管理员),Store需要借助Reducers这个记录本,去记录放在哪里,拿到数据后,就返回给Store.Store再把State给到React Component.
而中间件,就是在Dispatch这个过程中,加入进来对Store进行修改最后返回数据给View.