🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## JSX ### 实验目的 1. 掌握 JSX 基本语法 ### 操作步骤 1. 浏览器打开`demos/jsx-demo/index.html`,仔细查看源码。 ### 注意事项 1. `ReactDOM.render`方法接受两个参数:一个虚拟 DOM 节点和一个真实 DOM 节点,作用是将虚拟 DOM 挂载到真实 DOM。 ### 练习 1. 修改源码,将显示文字变为 ”Hello React!“。 ## React 组件语法 ### 实验目的 1. 掌握 React 组件的基本写法 ### 操作步骤 1. 浏览器打开`demos/react-component-demo/index1.html`,仔细查看源码。 ### 注意事项 1. `class MyTitle extends React.Component`是 ES6 语法,表示自定义一个`MyTitle`类,该类继承了基类`React.Component`的所有属性和方法。 2. React 规定,自定义组件的第一个字母必须大写,比如`MyTitle`不能写成`myTitle`,以便与内置的原生类相区分。 3. 每个组件都必须有`render`方法,定义输出的样式。 4. `<MyTitle/>`表示生成一个组件类的实例,每个实例一定要有闭合标签,写成`<MyTilte></MyTitle>`也可。 ## React 组件的参数 ### 实验目的 1. 学会向 React 组件传参数 ### 操作步骤 1. 浏览器打开`demos/react-component-demo/index2.html`,仔细查看源码。 ### 注意事项 1. 组件内部通过`this.props`对象获取参数。 ### 练习 1. 将组件的颜色,从红色(`red`)换成黄色(`yellow`)。 ## React 组件的状态 ### 实验目的 1. 学会通过状态变动,引发组件的重新渲染。 ### 操作步骤 1. 浏览器打开`demos/react-component-demo/index3.html`,仔细查看源码。 ### 注意事项 ~~~ class MyTitle extends React.Component { constructor(...args) { super(...args); this.state = { name: '访问者' }; } // ... ~~~ `constructor`是组件的构造函数,会在创建实例时自动调用。`...args`表示组件参数,`super(...args)`是 ES6 规定的写法。`this.state`对象用来存放内部状态,这里是定义初始状态。 ~~~ <div> <input type="text" onChange={this.handleChange.bind(this)} /> <p>你好,{this.state.name}</p> </div>; ~~~ `this.state.name`表示读取`this.state`的`name`属性。每当输入框有变动,就会自动调用`onChange`指定的监听函数,这里是`this.handleChange`,`.bind(this)`表示该方法内部的`this`,绑定当前组件。 ~~~ handleChange(e) { let name = e.target.value; this.setState({ name: name }); } ~~~ `this.setState`方法用来重置`this.state`,每次调用这个方法,就会引发组件的重新渲染。 ## React 组件实战 ### 实验目的 1. 学会自己写简单的 React 组件。 ### 操作步骤 1. 浏览器打开`demos/react-component-demo/index4.html`。 2. 点击`Hello World`,看看会发生什么。 ### 练习 1. 修改源码,使得点击`Hello World`后,会显示当前的日期,比如`Hello 2016年1月1日`。 2. 请在上一步练习的基础上,进一步修改。现在`Hello World`点击一次,会改变内容,再点击就不会有反应了。请将其改成,再点击一次变回原样。 ### 提示 练习一、下面的代码可以得到当前日期。 ~~~ var d = new Date(); d.getFullYear() // 当前年份 d.getMonth() + 1 // 当前月份 d.getDate() // 当前是每个月的几号 ~~~ 练习二、可以在`this.state`里面设置一个开关变量`isClicked`。 ~~~ this.state = { text: 'World', isClicked: false }; ~~~ 然后,在`this.handleClick`方法里面,做一个`toggle`效果。 ~~~ let isClicked = !this.state.isClicked; this.setState({ isClicked: isClicked, text: isClicked ? 'Clicked' : 'World' }); ~~~ ## React 组件的生命周期 ### 实验目的 1. 掌握钩子方法的基本用法 2. 掌握组件如何通过 Ajax 请求获取数据,并对数据进行处理 ### 操作步骤 1. 打开`demos/react-lifecycle-demo/index.html`,仔细查看源码。 ### 注意事项 ~~~ componentDidMount() { const url = '...'; $.getJSON(url) .done() .fail(); } ~~~ * `componentDidMount`方法在组件加载后执行,只执行一次。本例在这个方法里向服务器请求数据,操作结束前,组件都显示`Loading`。 * `$.getJSON`方法用于向服务器请求 JSON 数据。本例的数据从 Github API 获取,可以打开源码里面的链接,看看原始的数据结构。 ### 练习 1. 本例的 JSON 数据是 Github 上面最受欢迎的 JavaScript 项目。请在网页上显示一个列表,列出这些项目。 ### 提示 (1) `this.state.loading`记录数据加载是否结束。只要数据请求没有结束,`this.state.loading`就一直是`true`,网页上显示`loading`。 (2) `this.state.error`保存数据请求失败时的错误信息。如果请求失败,`this.state.error`就是返回的错误对象,网页上显示报错信息。 (3) `this.state.data`保存从服务器获取的数据。如果请求成功,可以先用`console.log`方法,将它在控制台里打印出来,看看数据结构。 ~~~ render() { // 加一行打印命令,看看数据结构 console.log(this.state.data); return { // ... ~~~ (4) `this.state.data`里面的`this.state.data.items`应该是一个数组,保存着每个项目的具体信息。可以使用`forEach`方法进行遍历处理。 ~~~ var projects = this.state.data.items; var results = []; projects.forEach(p => { var item = <li>{p.name}</li>; results.push(item); }); ~~~ (5)然后,将上一步的`results`插入网页即可。 ~~~ <div> <ul>{results}</ul> </div> ~~~ ## ReCharts ### 实验目的 1. 了解如何使用第三方组件库。 ### 操作步骤 1. 浏览器打开`demos/recharts-demo/index.html`,查看效果。 ## MobX ### 实验目的 1. 理解 MobX 框架 ### 操作步骤 (1) 命令行进入`demos/mobx-demo/`目录,执行如下的命令。 ~~~ $ npm install $ npm start ~~~ (2) 打开浏览器,访问 http://localhost:8080,查看结果,并仔细研究代码。 ### 注意事项 ~~~ @observer class App extends React.Component { render() { // ... } } ~~~ `@observer`是一种新的语法,表示对整个类执行指定的函数。 数据保存在`Store`里面。`Store`的属性分成两种:被观察的属性(`@observable`),和自动计算得到的属性`@computed`。 ~~~ class Store { @observable name = 'Bartek'; @computed get decorated() { return `${this.name} is awesome!`; } } ~~~ `Store`的变化由用户引发。组件观察到`Store`的变化,自动重新渲染。 ~~~ <p> {this.props.store.decorated} </p> <input defaultValue={this.props.store.name} onChange={ (event) => this.props.store.name = event.currentTarget.value } /> ~~~ ## Redux ### 实验目的 1. 理解 Redux 架构 ### 操作步骤 (1) 命令行下进入`demos/redux-demo`目录,执行如下的命令。 ~~~ $ npm install $ npm start ~~~ (2)打开浏览器,访问 http://localhost:8080,查看结果,并仔细研究代码。 ### 注意事项 (1) Redux 要求 UI 的渲染组件都是纯组件,即不包含任何状态(`this.state`)的组件。 ~~~ <div className="index"> <p>{this.props.text}</p> <input defaultValue={this.props.name} onChange={this.props.onChange} /> </div> ~~~ (2) 进行数据处理、并包含状态的组件,称为”容器组件“。Redux 使用`connect`方法,自动生成 UI 组件对应的”容器组件“。 ~~~ // MyComponent 是纯的 UI 组件 const App = connect( mapStateToProps, mapDispatchToProps )(MyComponent); ~~~ (3) `mapStateToProps`函数返回一个对象,表示一种映射关系,将 UI 组件的参数映射到`state`。 ~~~ function mapStateToProps(state) { return { text: state.text, name: state.name }; } ~~~ (4) `mapDispatchToProps`函数也是返回一个对象,表示一种映射关系,但定义的是哪些用户的操作应该当作`Action`,传给`Store`。 ~~~ function mapDispatchToProps(dispatch) { return { onChange: (e) => dispatch({ type: 'change', payload: e.target.value }) } } ~~~ (5) `reducer`函数用来接收`action`,算出新的`state`。 ~~~ function reducer(state = { text: '你好,访问者', name: '访问者' }, action) { switch (action.type) { case 'change': return { name: action.payload, text: '你好,' + action.payload }; } } ~~~ `Store`由 Redux 提供的`createStore`方法生成,该方法接受`reducer`作为参数。 ~~~ const store = createStore(reducer); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.body.appendChild(document.createElement('div')) ); ~~~ 为了把`Store`传入组件,必须使用 Redux 提供的`Provider`组件在应用的最外面,包裹一层。