前言
React(有时叫React.js或ReactJS),是一个为数据提供渲染为HTML视图的开源JavaScript 库。React视图通常采用包含以自定义HTML标记规定的其他组件的组件渲染。React为程序员提供了一种子组件不能直接影响外层组件(”data flows down”)的模型,数据改变时对HTML文档的有效更新,和现代单页应用中组件之间干净的分离。(维基百科)
引入依赖
1 2
| <script src="https://cdn.jsdelivr.net/npm/react@16/umd/react.development.js"></script> <script src="https://cdn.jsdelivr.net/npm/react-dom@16/umd/react-dom.development.js"></script>
|
快速入门
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> </head> <body>
<div id="app"> ... </div>
</body> <script type="text/babel"> let dom = <div></div>; ReactDOM.render(dom, document.getElementById("app")); </script> </html>
|
React的内置函数
创建一个标签
- 也可以通过jsx代码直接创建一个组件,返回一个DOM对象
第一个参数:标签名
第二个参数:标签属性
第三个参数:标签内容
1
| React.createElement("div", null, "hello");
|
为标签添加内容
第一个参数:内容
第二个参数:绑定的标签
1 2 3
| let html = <div>hello</div>; ReactDOM.render(html, document.getElementById("app"));
|
React中的组件
定义类组件
1 2 3 4 5 6 7
| class Person extends React.Component { render() { return <div>hello</div>; } }
ReactDOM.render(<Person/>, document.getElementById("app"));
|
定义函数组件
1 2 3 4 5
| function Person() { return <div>hello</div>; }
ReactDOM.render(<Person/>, document.getElementById("app"));
|
组件嵌套
- 组件当作标签使用时,如果使用双标签要有结束标签,如果使用单标签要有闭合标签
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Son extends React.Component { render() { return <div><p>这是子组件</p></div> } }
class Father extends React.Component { render() { return <div><p>这是父组件</p><Son></Son></div> } }
ReactDOM.render(<Father/>, document.getElementById("app"));
|
在组件内调用数据
- 在调用组件时传递参数,可以使用props属性中的对应属性来传递参数
- 在组件内部的props是只读的,不可以修改
- 如果props的数据源被修改,那么组件内得到的数据也会被修改
类组件
1 2 3 4 5 6 7 8
| class Person extends React.Component { render() { console.log(this.props); return <div>hello {this.props.name}</div>; } }
ReactDOM.render(<Person name="world"/>, document.getElementById("app"));
|
函数组件
1 2 3 4 5 6
| function Person(props) { console.log(props); return <div>hello {props.name}</div>; }
ReactDOM.render(<Person name="world"/>, document.getElementById("app"));
|
设置props的初始值
类组件
- 通过定义defaultProps来定义props的初始值
1 2 3 4 5 6 7 8 9 10 11
| class Person extends React.Component { static defaultProps = { name: "world" }; render() { console.log(this.props); return <div>hello {this.props.name}</div>; } }
ReactDOM.render(<Person/>, document.getElementById("app"));
|
函数组件
- 直接在组件中添加一个defaultProps属性,就可以初始化props值
1 2 3 4 5 6 7 8 9
| function Person(props) { return <div>hello {props.name}</div>; }
Person.defaultProps = { name: "world" };
ReactDOM.render(<Person/>, document.getElementById("app"));
|
双标签内的子标签
- 通过调用props.children属性来调用双标签内的子标签
类组件
1 2 3 4 5 6 7
| class Person extends React.Component { render() { return <div>hello {this.props.children}</div>; } }
ReactDOM.render(<Person><span>world</span></Person>, document.getElementById("app"));
|
函数标签
1 2 3 4 5
| function Person(props) { return <div>hello {props.children}</div>; }
ReactDOM.render(<Person><span>world</span></Person>, document.getElementById("app"));
|
this绑定
- 当通过子组件的函数调用父组件的函数时,需要使用构造器constructor进行this绑定,把父组件的this绑定到子组件的this上,否则函数中的this都是undefined
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Child extends React.Component { constructor() { super(); this.click = this.click.bind(this); } click() { this.props.onCli(); } render() { return <div><button onClick={this.click}>按钮</button></div>; } }
class Father extends React.Component { fn() { console.log("hello world"); } render() { return <div><Child onCli={this.fn}></Child></div>; } }
ReactDOM.render(<Father/>, document.getElementById("app"));
|
组件的状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class App extends React.Component { constructor() { super(); this.state = { name: "hello world" } this.click = this.click.bind(this); } click(){ this.setState({ name: "hello" }); } render() { return <div>{this.state.name}<button onClick={this.click}>点击更改state</button></div>; } }
ReactDOM.render(<App/>, document.getElementById("app"));
|
数据双向绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class App extends React.Component { constructor() { super(); this.state = { name: "hello world" } this.change = this.change.bind(this); } change(event){ this.setState({ name: event.target.value }); } render() { return <div>{this.state.name}<input type="text" value={this.state.name} onChange={this.change}/></div>; } }
ReactDOM.render(<App/>, document.getElementById("app"));
|
组件生命周期
Mounting
constructor():构造器函数。
render():返回一个虚拟DOM
componentDidMount():DOM插入后立即调用。
Updating:当状态数据发生改变时触发
render():再次插入DOM
componentDidUpdate():数据状态更新之后调用
Unmounting
componentWillUnmount():组件卸载之前调用
- 手动卸载组件:
ReactDOM.unmountComponentAtNode(container)
- 清除timer计时器
- 取消网络请求
- 清除
componentDidMount()中创建的订阅
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
| class App extends React.Component { constructor() { super(); this.state = { name: "hello world" } console.log("constructor()"); this.click = this.click.bind(this); } click() { this.setState({ name: "hello" }); } componentDidMount() { console.log("componentDidMount()") } componentDidUpdate() { console.log("componentDidUpdate()") } componentWillUnmount() { console.log("componentWillUnmount()"); } render() { console.log("render()"); return <div> <p>{this.state.name}</p> <button onClick={this.click}>更新组件</button> <button onClick={()=>{ReactDOM.unmountComponentAtNode(document.getElementById("app"))}}>卸载组件</button> </div> } }
ReactDOM.render(<App/>, document.getElementById("app"));
|
完成
参考文献
哔哩哔哩——Python小清风