React
一、JSX
1、JSX是js的一种扩展语法,既不是字符串又不是html,它是一种特殊的表达式
const element = <div>hello~</div>
2、可以当做参数函数,也可以作为函数的返回值
3、JSX可以防止注入攻击(JSX在渲染之前都是被转转义字符串)
4、JSX实际上是在执行React.createElement(),是通过Babel实现的
二、dom渲染
1、相对浏览器dom渲染,react的dom渲染开销较小,因每次只会重新渲染更新的部分,与其实现原理有关,此时用到diff算法
三、组件分类、props
1、函数式组件
function Func(props){ return <div>{props.name}~<div> }
2、class组件
class Cla extends React.Component{ constructor(props){ super(props) } render(){ return <div>{this.props.name}<div> } }
3、原生dom标签
附加信息:
1、当react元素为自定义组件时,JSX会将组件属性(attributes)转换成props传给组件
const element = <Cla name="Lily"></Cla>
此时,Cla类中的props为:名为props的对象
props = {name: "Lily"}
2、当组件本身很复杂时、复用率较高时,建议提取出可复用的组件,这样便于代码的可维护性,代码更简洁
4、props具有只读性,不可更改
四、state
1、不可变性,不可直接直接修改
2、唯一可定义性,只能在construtor函数中定义,并且每次修改必须通过setstate返回新的对象来实现修改
3、局部性(封装性),仅对当前class有效
4、单项数据流,组件之间的数据通信都是“自上而下”的瀑布形式,子组件无法知道props是来自父组件的state or props or 手写的变量
5、独立性,有状态的组件和无状态的组件之间可以相互嵌套,互不影响
ReactDOM.render( <div> <App /> <App /> <App /> </div>, document.getElementById('root') );
此时,dom会有生成三个独立的计时器,虽然他们的时间是相同的
五、组件的提取与封装
1、定义一个原始的时钟组件(这样,每次都会通过调用ReactDom.render来改变时间)
import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component{ constructor(props){ super(props) } render() { return ( <div> hello,word! <p>{this.props.dateId}</p> </div> ); } } function Clock() { ReactDOM.render( <App dateId={new Date().toLocaleTimeString()}/>, document.getElementById('root') ); } setInterval(()=>{ Clock() },1000)
设想:有没有一种方法可以每次让组件自己自动更新,二只调用一次ReactDom.render函数(答案当然是可以的),于是有了组件的提取与封装,这样,每次可以实现组件的复用性,并且可以实现每次更改让组件自己自动更新
2、封装组件,将自定义组件的attributes写到其函数(class)里面
3、时钟也要写在组件里面,供每次setstate改变内部state,通常改变数据写在componentDidMount函数中(在dom渲染完成后调用),并且,在componentWillUnmount函数中清除时钟编译器
class App extends React.Component{ constructor(props){ super(props) this.state = { dateId: new Date().toLocaleTimeString() } } componentDidMount(){ // 每次页面渲染完成后调用,通常在次函数中,更改下次渲染改变的数据, // 通常异步执行也在此函数中执行 this.timerId = setInterval(()=>{ this.setState({ dateId: new Date().toLocaleTimeString() }) },1000) } componentWillUnmount(){ // clock组件被删除时,应该清楚定时器 clearInterval(this.timerId) } render() { return ( <div> hello,word! <p>{this.state.dateId}</p> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') );
误区:组件封装前后,实际上dom重新渲染的地方相同,此时diff的时间算法复杂度是相同的,并不存在,组件封装之后重新渲染的dom节点更少,当dom树(一般都是数据改变)发生改变时,才会被重新渲染
六、