入门学习 React 少量实例
这是几个入门学习 React 的小 Demo,帮助自己学习理解 React 的运行机制,结合 React官方文档,会更佳噢…
DEMO 目录
- ReactDOM.render()
- Use Array in JSX
- 组件
- this.props.children
- PropTypes
- 获取真实的 DOM 节点
- this.state
- 表单
- 组件的生命周期
- 使用 Promise 获取 Github 的数据
- Todo List
- 井字棋(Tic Tac Toe)
引入资源
- With babel-standalone
<div id="output"></div><!-- Load Babel --><!-- v6 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> --><script src="https://unpkg.com/@babel/standalone/babel.min.js"></script><!-- Your custom script here --><script type="text/babel">const getMessage = () => "Hello World";document.getElementById('output').innerHTML = getMessage();</script>Demo01: ReactDOM.render()
Demo / Source
初始化咱先 Hello 一下,使用 jsx 语法,碰到代码块使用({ })包起来,碰到 html 标签,就使用(< />):
var names = ["AAA", "BBB", "CCC"];ReactDOM.render( <div> {names.map(function(name) { return <h2>Hello, {name}!</h2>; })} </div>, document.getElementById("example"));Demo02: Use Array in JSX
Demo / Source
假如 JavaScript 的变量是个数组,会开展这个数组的所有项.
var arr = [<h1 key="h1">Hello,</h1>, <h2 key="h2">React is awesome!</h2>];ReactDOM.render(<div>{arr}</div>, document.getElementById("example"));Demo03: 组件
Demo / Source
变量 HelloMsg 是一个组件类。模板插入 <HelloMsg /> 时,会自动生成 HelloMsg 的一个实例。所有组件类都必需有自己的 render 方法,用于输出组件。
class HelloMsg extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; }}ReactDOM.render( <HelloMsg name="Dataozi" />, document.getElementById("example"));Demo04: this.props.children
Demo / Source
this.props 对象的属性与组件的属性逐个对应,但是有一个例外,就是 this.props.children 属性。
ps: 注意大小写 React.Children、React.Component
class NotesList extends React.Component { render() { return ( <ol> {React.Children.map(this.props.children, function(child) { return <li>{child}</li>; })} </ol> ); }}ReactDOM.render( <NotesList> <span>Hello</span> <span>World</span> <span>React</span> </NotesList>, document.getElementById("example"));Demo05: PropTypes
Demo / Source
- 使用 PropTypes 进行类型检查
React 内置了少量类型检查的功能。要在组件的 props 上进行类型检查,你只要配置特定的 propTypes 属性:
var data = { tilte: "Hello", age: 19, isStudent: true};class MyTitle extends React.Component { static propTypes = { tilte: PropTypes.string, age: PropTypes.number, isStudent: PropTypes.bool }; render() { return ( <div> <h1>{this.props.data.tilte}</h1> <h2>{this.props.data.age}</h2> <h3>{this.props.data.isStudent ? "Yes" : "No"}</h3> </div> ); }}ReactDOM.render(<MyTitle data={data} />, document.getElementById("root"));还可以通过配置特定的 defaultProps 属性来定义 props 的默认值:
class DefaultTitle extends React.Component { render() { return <h4>{this.props.title}</h4>; }}//指定 props 的默认值:DefaultTitle.defaultProps = { title: "Hello React!"};ReactDOM.render(<DefaultTitle />, document.getElementById("root2"));Demo06: 获取真实的 DOM 节点
Demo / Source
- Refs and the DOM
Refs 提供了一种方式,允许我们访问 DOM 节点或者在 render 方法中创立的 React 元素。
- 创立 Refs: Refs 是由
React.createRef()创立的,并通过 ref 属性附加到 React 元素(比方 input) - 访问 Refs: 当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问,
this.myTextFocus.current.focus();
你不能在函数组件上使用 ref 属性,由于它们没有实例
组件 MyComponent 的子节点有一个文本输入框,用于获取客户的输入。这时就必需获取真实的 DOM 节点,虚拟 DOM 是拿不到客户输入的。
class MyComponent extends React.Component { constructor(props) { super(props); // 创立一个 ref 来存储 myTextFocus 的 DOM 元素 this.myTextFocus = React.createRef(); this.handerClick = this.handerClick.bind(this); } handerClick() { // 直接使用原生 API 使 text 输入框取得焦点 // 通过 "current" 来访问 DOM 节点 this.myTextFocus.current.focus(); } render() { // 告诉 React 我们想把 <input> ref 关联到 // 构造器里创立的 `myTextFocus` 上 return ( <div> <input type="text" ref={this.myTextFocus} /> <input type="button" value="点击聚焦" onClick={this.handerClick} /> </div> ); }}ReactDOM.render(<MyComponent />, document.getElementById("root"));Demo07: this.state
Demo / Source
- State & 生命周期
学习如何封装真正可复用的 Clock 组件。它将设置自己的计时器并每秒升级一次。
class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; //为 this.state 赋初值 } componentDidMount() { // Clock首次被渲染到DOM时,为?其挂载一个计时器 this.timerID = setInterval(() => this.tick(), 1000); } componentWillUnmount() { // Clock被删除时,卸载其计时器 clearInterval(this.timerID); } tick() { // 使用 this.setState() 来时刻升级组件 state this.setState({ date: new Date() }); } render() { return ( <div> <h1>Hello, React!</h1> <h2>现在是北京时间:{this.state.date.toLocaleTimeString()}</h2> </div> ); }}ReactDOM.render(<Clock />, document.getElementById("root"));Demo08: 表单
Demo / Source
- 表单
受控组件:渲染表单的 React 组件还控制着客户输入过程中表单发生的操作,被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
即:表单数据是由 React 组件来管理的。
class NameForm extends React.Component { constructor(props) { super(props); this.state = { // 唯一数据源 value: "" }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({ value: event.target.value // 显示的值将随着客户输入而升级 }); } handleSubmit(event) { if (this.state.value) { alert("接受到的name值是:" + this.state.value); } event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" value={this.state.value} onChange={this.handleChange} /> <input type="submit" value="提交" /> </form> ); }}ReactDOM.render(<NameForm />, document.getElementById("root"));非受控组件:表单数据将交由 DOM 节点来解决,即便用 ref 来从 DOM 节点中获取表单数据
Demo / Source
class NameForm extends React.Component { constructor(props) { super(props); this.input = React.createRef(); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(event) { alert("接受到的name值是:" + this.input.current.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" ref={this.input} /> <input type="submit" value="提交" /> </form> ); }}ReactDOM.render(<NameForm />, document.getElementById("root"));Demo09: 组件的生命周期
Demo / Source
- 组件的生命周期
- 生命周期图谱速查表
- React 的生命周期 — Ant Design 语雀
主要路线顺序:挂载 – 升级 – 卸载 – 错误解决
挂载
当组件实例被创立并插入 DOM 中时,其生命周期调用如下:
- consctructor() — React 组件的构造函数,不初始化 state 或者不进行方法绑定,则不需要
- static getDerivedStateFromProps() — 不常用
- render() — 唯一必需实现的方法,并且应该是纯函数
- componentDidMount() — 依赖于 DOM 节点的初始化应该在这里
升级
当组件的 props 或者 state 发生变化时,会触发升级:
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate() — 不常用
- componentDidUpdate() — 在升级后会被立即调用
卸载
当组件从 DOM 中移除时:
- componentWillUnmount() — 会在组件卸载及销毁之前直接调用
错误解决
当渲染过程,生命周期,或者子组件的构造函数中抛出错误时:
- static getDerivedStateFromError()
- componentDidCatch()
过期的生命周期方法:
- UNSAFE_componentWillMount() — 挂载前调用,目前使用 constructor()初始化 state
- UNSAFE_componentWillReceiveProps()
- UNSAFE_componentWillUpdate()
class Hello extends React.Component { constructor(props) { super(props); this.state = { fontSize: 12, opacity: 0.01 }; } componentDidMount() { this.timerID = setInterval(() => { let opacity = this.state.opacity; let fontSize = this.state.fontSize; opacity += 0.02; fontSize += 1; if (opacity >= 1) { opacity = 0.01; } if (fontSize >= 63) { fontSize = 12; } this.setState({ fontSize, opacity }); }, 100); } componentWillUnmount() { clearInterval(this.timerID); } render() { return ( <h1 style={{ opacity: this.state.opacity, fontSize: this.state.fontSize }} > Hello, {this.props.name} </h1> ); }}ReactDOM.render(<Hello name="React" />, document.getElementById("root"));Demo10: 使用 Promise 获取 Github 的数据
Demo / Source
ReactDOM.render( <ReportList promise={$.getJSON( "https://api.github.com/search/repositories?q=javascript&sort=stars" )} />, document.getElementById("root"));从 Github 的 API 抓取数据,而后将 Promise 对象作为属性,传给 ReportList 组件。
假如 Promise 对象正在抓取数据(pending 状态),组件显示”loading…”;
假如 Promise 对象报错(rejected 状态),组件显示报错信息;
假如 Promise 对象抓取数据成功(fulfilled 状态),组件显示获取的数据。
在这里查看完整 Demo/源码 — 谷歌浏览器有时候会报跨域的问题,可以使用火狐等浏览器试看
接下来来几个混合实战吧
Demo11: Todo List
Demo / Source
- React todo list
主要练习使用 props 和 state,使用 state 保存现有的待办事项列表及客户的少量操作(删除、完成)等。
class TodoApp extends React.Component { constructor(props) { super(props); this.state = { items: [] }; this.addItem = this.addItem.bind(this); this.deleteItem = this.deleteItem.bind(this); this.doneItem = this.doneItem.bind(this); } addItem(item) { const newItem = { text: item.text, id: Date.now(), done: false }; this.setState({ items: this.state.items.concat(newItem) }); } deleteItem(index) { this.state.items.splice(index, 1); this.setState({ items: this.state.items }); } doneItem(index) { const items = this.state.items; const todo = items[index]; items.splice(index, 1); todo.done = !todo.done; todo.done ? items.unshift(todo) : items.push(todo); this.setState({ items }); } render() { return ( <div className="container"> <h1>TODO</h1> <TodoList items={this.state.items} deleteClick={this.deleteItem} doneClick={this.doneItem} /> <TodoForm addItem={this.addItem} items={this.state.items} /> </div> ); }}Demo12: 井字棋(Tic Tac Toe)
Demo / Source
- Tic Tac Toe
- 井字棋游戏教程文档
- React 的井字过三关
tic-tac-toe(三连棋)游戏的功能
- [x] 能够判定玩家何时获胜
- [x] 能够记录游戏进程
- [x] 允许玩家查看游戏的历史记录,也可以查看任意一个历史版本的游戏棋盘状态
- [x] 在游戏历史记录列表显示每一步棋的坐标,格式为 (列号, 行号)
- [x] 在历史记录列表中加粗显示当前选择的项目
- [ ] 使用两个循环来渲染出棋盘的格子,而不是在代码里写死(hardcode)
- [ ] 增加一个可以升序或者降序显示历史记录的按钮
- [ ] 每当有人获胜时,高亮显示连成一线的 3 颗棋子
- [x] 当无人获胜时,显示一个平局的消息
学习资料
- React 入门实例教程 — 阮一峰
- react-demos
Github地址:戳我
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 入门学习 React 少量实例