一.认识React
React 是 Facebook 在 2011 年开发的前端 JavaScript 库。它遵循基于组件的方法,有助于构 建可重用的UI组件。用于开发复杂和交互式的 Web 和移动 UI。
二.React 相关知识
- Real DOM 和 Virtual DOM (真实DOM和虚拟DOM)
- 真实DOM
- 更新缓慢。
- 可以直接更新 HTML。
- 如果元素更新,则创建新DOM。
- DOM操作代价很高。
- 消耗的内存较多。
- 虚拟DOM
- 更新更快。
- 无法直接更新 HTML。
- 如果元素更新,则更新 JSX 。
- DOM 操作非常简单。
- 很少的内存消耗。
- 真实DOM
- Racet JSX语法
- JSX 即Javascript XML,它是对JavaScript 语法扩展,利用HTML语法来创建虚拟DOM。React的核心机制之一就是可以在内存中创建虚拟的DOM元素。以此来减少对实际DOM的操作从而提升性能。
//1.创建虚拟DOM const VDOM = ( <div> <h2 className="title" id={myId.toLowerCase()}> <span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span> </h2> <h2 className="title" id={myId.toUpperCase()}> <span style={{color:'white',fontSize:'29px'}}>{myData.toLowerCase()}</span> </h2> <input type="text"/> </div> ) //2.渲染虚拟DOM到页面 ReactDOM.render(VDOM,document.getElementById('test'))
-
jsx语法规则:
1.定义虚拟DOM时,不要写引号。
2.标签中混入JS表达式时要用{}。
3.样式的类名指定不要用class,要用className。
4.内联样式,要用style={{key:value}}的形式去写。
5.只有一个根标签
6.标签必须闭合
7.标签首字母
(1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
- JSX 即Javascript XML,它是对JavaScript 语法扩展,利用HTML语法来创建虚拟DOM。React的核心机制之一就是可以在内存中创建虚拟的DOM元素。以此来减少对实际DOM的操作从而提升性能。
-
React定义组件(函数式定义组件 和 类式定义组件)
-
函数式定义组件
<script type="text/babel"> //1.创建函数式组件 function MyComponent(){ console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式 return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2> } //2.渲染组件到页面 ReactDOM.render(<MyComponent/>,document.getElementById('test')) /* 执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么? 1.React解析组件标签,找到了MyComponent组件。 2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。 */ </script>
- class类式组件
<script type="text/babel"> //1.创建类式组件 class MyComponent extends React.Component { render(){ //render是放在哪里的?—— MyComponent的原型对象上,供实例使用。 //render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。 console.log('render中的this:',this); return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2> } } //2.渲染组件到页面 ReactDOM.render(<MyComponent/>,document.getElementById('test')) /* 执行了ReactDOM.render(<MyComponent/>.......之后,发生了什么? 1.React解析组件标签,找到了MyComponent组件。 2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。 3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。 */ </script>
-
- React组件三大属性
- state存储React中的状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
class Weather extends React.Component { // state简写方式 state = { isHot: true, wind: '微风' } // 自定义方法 ---- 要用赋值语句的形式+箭头函数 render() { const {isHot, wind} = this.state return ( <h2>今天天气很{isHot ? '炎热' : '凉爽'}, {wind}</h2> ) } } ReactDOM.render(<Weather/>, document.getElementById('test'))
- props属性:react中实现单向数据流值说的就是props,实现组件间的通信
- props属性相关特点:
(1).每个组件对象都会有props属性
(2).组件标签的所有属性都保存在props中
(3).内部读取某个属性值:this.props.属性值
- props属性作用:
(1).作用:通过标签属性从组件外向组件内传递数据(只读 read only)
(2).对props中的属性值进行类型限制和必要性限制
- props属性相关特点:
- ref属性:获取Dom实施交互使用
- 字符串方式定义
class Demo extends React.Component{ showData = ()=>{ const {input1} = this.refs } render(){ return( <div> <input ref="input1" type="text" placeholder="点击按钮提示数据"/> <button onClick={this.showData}>点我提示左侧的数据</button> </div> ) } }
- 回调函数方法
class Demo extends React.Component{ // 类式创建组件 showData = ()=>{ const {input1} = this } render(){ return( <div> <input ref={c => this.input1 = c } type="text" placeholder="点击按钮"/> <button onClick={this.showData}>点我提示左侧的数据</button> </div> ) } }
- 使用creatrRef创建容器方式定义
class Demo extends React.Component{ // React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点 myRef = React.createRef() showData = ()=>{ alert(this.myRef.current.value); } render(){ return( <div> <input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/> <button onClick={this.showData}>点我</button> </div> ) } }
- 字符串方式定义
- state存储React中的状态机,通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
- React受控组件和非受控组件
- 受控组件:
概念: 在React中,每当表单的状态发生变化时,都会被写入到组件的state中,这种组件在React被称为受控组件。 受控组件中,组件渲染的状态与它的value或者checked相对应。 React通过这种方式消除了组件的局部状态。React官方推荐使用受控组件。 受控组件更新流程: 1. 可以通过在初始state中设置表单的默认值。 2. 每当表单的值发生变化时,调用onChange事件处理器。 3. 事件处理器通过合成事件对象e拿到改变后的状态,并更新state。 4. setState触发视图的重新渲染,完成表单组件值得更新。
- 非受控组件
简单的说,如果一个表单组件没有value props(单选按钮和复选框对应的是checked props) 就可以称为非受控组件。我们可以使用defaultValue和defaultChecked来表示组件的默认状态。 在React中,非受控组件是一种反模式,它的值不受组件自身的state或者props控制, 通常需要为其添加ref prop来访问渲染后的底层DOM元素。
- 区别对比
通过defaultValue或者defaultChecked来设置表单的默认值,它仅会被渲染一次,在后续的渲染时并不起作用。 <input value={this.state.value} onChange={e => this.setState({value: e.target.value})} > <input defaultValue={this.state.value} onChange={e => this.setState({value: e.target.value})} > 在受控组件中,可以将用书输入的内容输出展示,而在非受控组件中,如果不绑定onChange事件, 我们在文本框中输入任何内容都不会展示。可以看到受控组件和非受控组件的最大区别就是, 非受控组件状态并不会受应用状态的控制,应用中也多了局部组件状态,而受控组件的值来源于state。 性能问题:在受控组件中,每次表单的值发生变化都会调用一次onChange时间处理器,这会有一些性能消耗
- 受控组件:
- 拓展:函数的柯里化
-
高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
常见的高阶函数有:Promise、setTimeout、arr.map()等
-
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
function sum(a){ return(b)=>{ return (c)=>{ return a+b+c } } }
-
- React组件的生命周期
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
1. constructor() // 完成了React数据的初始化。
2. componentWillMount() //组件已经完成初始化数据,但是还未渲染DOM时执行的逻辑,主要用于服务端渲染。
3. render() // 页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。
4. componentDidMount() // 组件第一次渲染完成时执行的逻辑,此时DOM节点已经生成了。
一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate() 或 父组件render触发componentWillReceiveProps(nextProps)接收父组件新的props时,重新渲染组件执行的逻辑
1. shouldComponentUpdate() // 在setState以后state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false可以阻止组件的更新,主要用于性能优化。
2. componentWillUpdate() // shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑
3. render() // 把jsx编译为函数并生成虚拟dom
4. componentDidUpdate() // 重新渲染后执行的逻辑。
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
1. componentWillUnmount() // 组件的卸载前执行的逻辑
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
- 其他相关React方法