课堂练习(二)

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.statename属性。每当输入框有变动,就会自动调用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组件在应用的最外面,包裹一层。

文章导航