JSX
实验目的
- 掌握 JSX 基本语法
操作步骤
- 浏览器打开
demos/jsx-demo/index.html
,仔细查看源码。
注意事项
ReactDOM.render
方法接受两个参数:一个虚拟 DOM 节点和一个真实 DOM 节点,作用是将虚拟 DOM 挂载到真实 DOM。
练习
- 修改源码,将显示文字变为 ”Hello React!“。
React 组件语法
实验目的
- 掌握 React 组件的基本写法
操作步骤
- 浏览器打开
demos/react-component-demo/index1.html
,仔细查看源码。
注意事项
class MyTitle extends React.Component
是 ES6 语法,表示自定义一个MyTitle
类,该类继承了基类React.Component
的所有属性和方法。- React 规定,自定义组件的第一个字母必须大写,比如
MyTitle
不能写成myTitle
,以便与内置的原生类相区分。 - 每个组件都必须有
render
方法,定义输出的样式。 <MyTitle/>
表示生成一个组件类的实例,每个实例一定要有闭合标签,写成<MyTilte></MyTitle>
也可。
React 组件的参数
实验目的
- 学会向 React 组件传参数
操作步骤
- 浏览器打开
demos/react-component-demo/index2.html
,仔细查看源码。
注意事项
- 组件内部通过
this.props
对象获取参数。
练习
- 将组件的颜色,从红色(
red
)换成黄色(yellow
)。
React 组件的状态
实验目的
- 学会通过状态变动,引发组件的重新渲染。
操作步骤
- 浏览器打开
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 组件实战
实验目的
- 学会自己写简单的 React 组件。
操作步骤
- 浏览器打开
demos/react-component-demo/index4.html
。 - 点击
Hello World
,看看会发生什么。
练习
修改源码,使得点击
Hello World
后,会显示当前的日期,比如Hello 2016年1月1日
。请在上一步练习的基础上,进一步修改。现在
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 组件的生命周期
实验目的
- 掌握钩子方法的基本用法
- 掌握组件如何通过 Ajax 请求获取数据,并对数据进行处理
操作步骤
- 打开
demos/react-lifecycle-demo/index.html
,仔细查看源码。
注意事项
componentDidMount() {
const url = "...";
$.getJSON(url)
.done()
.fail();
}
componentDidMount
方法在组件加载后执行,只执行一次。本例在这个方法里向服务器请求数据,操作结束前,组件都显示Loading
。$.getJSON
方法用于向服务器请求 JSON 数据。本例的数据从 Github API 获取,可以打开源码里面的链接,看看原始的数据结构。
练习
- 本例的 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
实验目的
- 了解如何使用第三方组件库。
操作步骤
- 浏览器打开
demos/recharts-demo/index.html
,查看效果。
MobX
实验目的
- 理解 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
实验目的
- 理解 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
组件在应用的最外面,包裹一层。