ES6组件写法:
每个组件实例都有自己的声明周期。
class App extends Component{render(){return (<div>App1</div>);}componentWillMount(){console.log('app1 WillMount');}componentDidMount(){console.log('app1 DidMount');}componentWillUpdate(){console.log('app1 WillUpdate');}componentWillUnmount(){console.log('app1 WillUnmount');}}
函数式组件写法:
可以理解这种写法是ES6组件的一种简写。
const App2 = () => {return (<div>App2</div>);}
JS和HTML混写:
支持字符串,数组等的渲染,不支持对象object的渲染。实例中展示了条件渲染。
import React, {Component} from 'react';class List extends Component {render(){let name = 'David';let arr1 = ['A', 'B', 'C', 'D'];let arr2 = [<p>Nice</p>, <p>Boy</p>];let obj = {a: 1, b: 2};let showTitle = false;return (<div>{arr1.map((item, index) => {if((index+1) % 2 !== 1) {return item;}})}<h2>title</h2><div>{showTitle && <h3>Title</h3>}</div><h2>no title</h2><div>{showTitle ? <h3>Title</h3> : <h3>No Title</h3>}</div></div>);}}export default List;
React虚拟DOM原理:
https://www.cnblogs.com/zhuzhenwei918/p/7271305.html
虚拟DOM:
1. 把jsx编译成js;
- 把浏览器构建DOM树的工作交给JS,让JS去构建DOM树;
- 把结构数据传给React Render方法,将数据渲染出来;
Tree-Diff算法:
虚拟DOM树发生改变的3种情况:
1. DOM标签发生变化:
变为,把DIV标签删掉,把新标签SPAN添加进去;
- 组件发生变化:
变为 组件,把Header组件删掉,然后添加Content组件; - 列表(数组等)渲染:要为组件添加key的属性,而且此属性要唯一,以此优化渲染性能;
import React, {Component} from 'react';import ReactDOM from 'react-dom';import './index.css';import * as serviceWorker from './serviceWorker';import Filter from './filter/index'import List from './list/index'class Header extends Component {render(){return (<div>Header</div>);}componentDidMount(){console.log('Header Mount');}componentWillUnmount(){console.log('Header WillUnmount');}}class Content extends Component {render(){return (<div>Content</div>);}componentDidMount(){console.log('Content Mount');}componentWillUnmount(){console.log('Content WillUnmount');}}class App extends Component{constructor(props){super(props);this.state = {bool: true};}// 修改state 的bool的值,然后Header会被卸载,COntent会被挂载;render(){return (<div>{ this.state.bool ? <Header/> : <Content/> }</div>);}}ReactDOM.render(<App />, document.getElementById('root'));serviceWorker.unregister();
Notes:
渲染Item组件时,如果没有给key,当state按示例中变化时,会有如下的日志输出:
React Will Update
Vue Will Update
Angular WillUnmount
当指定key后,输出日志为:
Vue Will Update
Angular Will Update
React WillUnmount
import React, {Component} from 'react';import ReactDOM from 'react-dom';import './index.css';import * as serviceWorker from './serviceWorker';class Item extends Component {render(){return (<div>{this.props.item}</div>);}componentWillMount(){console.log(this.props.item + ' Will Mount');}componentWillUpdate(){console.log(this.props.item + ' Will Update');}componentDidMount(){console.log(this.props.item + ' Mount');}componentWillUnmount(){console.log(this.props.item + ' WillUnmount');}}class List extends Component {render(){return (<div>{this.props.list.map((item) => <Item key={item} item={item}/>)}</div>);}componentWillMount(){console.log('List Will Mount');}componentDidMount(){console.log('List Mount');}componentWillUnmount(){console.log('List WillUnmount');}}class App extends Component{constructor(props){super(props);this.state = {list: ['Vue', 'Angular', 'React']};}render(){return (<div><List list={this.state.list}/><input type='button' onClick={this.change.bind(this)} value='Change'/></div>);}componentWillMount(){console.log('App Will Mount');}componentDidMount(){console.log('App Mount');}componentWillUnmount(){console.log('App WillUnmount');}change(){this.setState({list: ['Angular', 'React']});}}ReactDOM.render(<App />, document.getElementById('root'));// If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: https://bit.ly/CRA-PWAserviceWorker.unregister();
总结:
1. React通过制定大胆的Diff策略,将O(n3)复杂度的问题转换成O(n)复杂度的问题;
- React 通过分层求异的策略,对tree diff进行算法优化;
- React 通过相同类生成相似树形结构,不同类生成不同树形结构的策略对component diff进行算法优化;
- React 通过设置唯一key的策略,对element diff进行算法优化;
