昨天搬家搬了一天,今天继续 b 站 react 学习计划
组件基础
组件是什么
数据和方法的简单封装
函数组件
1 2 3 4 5 6 7 8 9 10 11 12 13
| function Hello() { return <div style={{color:"red"}}>Hello World!</div> }
function App() { return ( <div className="App"> <Hello></Hello> </div> ); }
export default App;
|
一些说明:
- 组件首字母大写:react 判断组件和普通 html 标签的依据
- 函数组件必须有返回值,无需渲染则返回 null
- 函数名为组件标签名,可成对也可自闭合
类组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React from "react";
class Hello extends React.Component{ render(){ return <div>Hello World!</div> } }
function App() { return ( <div className="App"> <Hello /> </div> ); }
export default App;
|
一些说明:
- 同函数组件,类组件必须大写字母开头
- 类组件继承自 React.Component 父类
- 类组件必须提供 render 方法,并必须有返回值
事件绑定
on+事件名称 = {事件处理程序}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function Hello{ const clickHandler = ()=>{ console.log('click') } return <div onClick={clickHandler}>Hello World!</div> }
class Hello extends React.Component { clickHandler = () => { console.log("click") } render () { return <div onClick={this.clickHandler}>Hello World!</div> } }
|
事件对象 e 的使用
1 2 3 4 5 6 7 8 9 10
| class Hello extends React.Component { clickHandler = (e) => { e.preventDefault() console.log("click", e) } render () { return <div><a href="http://www.baidu.com/" onClick={this.clickHandler}>百度</a></div> } }
|
额外参数传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Hello extends React.Component { clickHandler = (msg) => { console.log("click", msg) } render () { return <div><a href="http://www.baidu.com/" onClick={() => this.clickHandler('Hello World')}>百度</a></div> } }
class Hello extends React.Component { clickHandler = (e, msg) => { e.preventDefault() console.log("click", msg) } render () { return <div><a href="http://www.baidu.com/" onClick={(e) => this.clickHandler(e, 'Hello World')}>百度</a></div> } }
|
组件状态
在 react hook 出现前,函数组件是没有状态的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class TestComponent extends React.Component { state = { name: 'current name' } changeName = () => { this.setState({ name: 'name was changed' }) } render () { return ( <div> this is TestComponent 当前名字为{this.state.name} <button onClick={this.changeName}>change</button> </div> ) } }
|
类组件修改 counter
咱直接在上一段代码中修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class TestComponent extends React.Component { state = { name: 'current name', count: 0 } changeName = () => { this.setState({ count: this.state.count + 1, name: `name was changed ${this.state.count + 1} times` }) } render () { return ( <div> this is TestComponent 当前名字为{this.state.name} <button onClick={this.changeName}>change</button> </div> ) } }
|
this 指向相关问题
如果在组件中并不使用箭头函数,而是直接使用函数的话,会出现 this 的指向问题
1 2 3 4 5 6 7 8 9 10
| class Test extends React.Component { handler(){ console.log(this) } render () { return ( <button onClick={this.handler}>click to test</button> ) } }
|
如上述代码会出现 this 输出为 undefine 的问题
如果一定要采用非箭头函数的写法,有以下修正方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class Test extends React.Component { constructor() { super() this.handler = this.handler.bind(this) } handler () { console.log(this) } render () { return ( <button onClick={this.handler}>click to test</button> ) } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
class Test extends React.Component { handler () { console.log(this) } render () { return ( <button onClick={() => this.handler()}>click to test</button> ) } }
|
表单处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Test extends React.Component { state = { msg: 'this is message' } inputChange (e) { this.setState({ msg: e.target.value }) } render () { return ( <> <div>{this.state.msg}</div> <input type='text' value={this.state.msg} onChange={(e) => this.inputChange(e)} /> </> ) } }
|
非受控组件:手动操作 dom 来获取文本框的值,文本框状态不受 state 中的状态控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React, { createRef } from "react"
class Test extends React.Component { msgRef = createRef() getValue = () => { console.log(this.msgRef.current.value) } render () { return ( <> <input type='text' ref={this.msgRef} /> <button onClick={this.getValue}>点击获取变化的值</button> </> ) } }
|
组件通信
父传子
- 父组件提供需要传递的数据 state
- 给子组件标签添加属性值为 state 中的数据
- 子组件通过 props 接收父组件中传过来的值
|—类组件使用 this.props 获取 props 对象
|—函数式组件直接通过参数获取 props 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import React from "react"
function SonA(props){ return ( <div>SonA,{props.msg}</div> ) } class SonB extends React.Component{ render(){ return ( <div>SonB, {this.props.msg}</div> ) } }
class App extends React.Component{ state = { msg: 'this is message' } render(){ return ( <> {} <SonA msg={this.state.msg}/> <SonB msg={this.state.msg}/> </> ) } }
export default App
|
props 可以传递任何数据:数字、字符串、布尔值、数组、对象、函数、JSX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import React from "react"
function SonA (props) { props.getMsg() return ( <div>SonA, {props.list.map(item => <div key={item}>{item}</div> )}, {props.child}</div> ) } class SonB extends React.Component { render () { return ( <div>SonB, {this.props.msg}</div> ) } }
class App extends React.Component { state = { msg: 'this is message', list: [1, 2, 3] } getMsg = () => { console.log('success') } render () { return ( <> {} <SonA msg={this.state.msg} list={this.state.list} getMsg={this.getMsg} child={<span>helloworld</span>} /> <SonB msg={this.state.msg} /> </> ) } }
export default App
|
根据单项数据流的要求,子组件只能读取 props 中的数据,不能进行修改
解构 props 可以让代码整体变得更加简单,只解构需要使用的部分即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function SonA (props) { const {list, child} = props return ( <div>SonA, {list.map(item => <div key={item}>{item}</div> )}, {child}</div> ) }
function SonA ({list, child}) { return ( <div>SonA, {list.map(item => <div key={item}>{item}</div> )}, {child}</div> ) }
|
子传父
子传父的本质是子组件调用父组件传递的函数,并将想要传递的数据当成函数的实参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import React from "react"
function SonA({getSonMsg}){ function clickHandler(){ getSonMsg('这是子组件的信息') } return ( <div>this is son <button onClick={clickHandler}>click</button> </div> ) }
class App extends React.Component { getSonMsg = (sonMsg) => { console.log(sonMsg) } render () { return ( <SonA getSonMsg={this.getSonMsg}/> ) } }
export default App
|
兄弟通信
兄弟通信的本质还是借助父子组件通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import React from "react"
function SonA({getSonMsg}){ function clickHandler(){ getSonMsg('这是子组件A的信息') } return ( <div>this is son <button onClick={clickHandler}>click</button> </div> ) }
function SonB({brotherMsg}){ return ( <div>{brotherMsg}</div> ) }
class App extends React.Component { state = { msg:'' } getSonMsg = (sonMsg) => { this.setState({ msg: sonMsg }) } render () { return ( <> <SonA getSonMsg={this.getSonMsg}/> <SonB brotherMsg={this.state.msg}/> </> ) } }
export default App
|
Context 跨组件通信
实现从上往下跨任意层传递信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import React, { createContext } from "react" const { Provider, Consumer } = createContext()
function ComA () { return ( <div> this is ComA <ComB /> </div> ) }
function ComB () { return ( <div> <Consumer> {value => <span>{value}</span>} </Consumer> this is ComB </div> ) }
class App extends React.Component { state = { msg: 'this is a message' } render () { return ( <Provider value={this.state.msg}> <> <ComA /> </> </Provider> ) } }
export default App
|