React官网首页demo(单文件实现版)

本博客实现React官网首页上展示的demo, 为了方便直接采用单文件的形式, 如果想完整集成
在自己的项目中, 可以参考React官网的安装指南, 安装Create React App.

hello-world

请移步至我写的这篇博客: 单文件快速体验使用react输出hello_world

A Stateful Component

React组件除了通过this.props传入参数, 还在内部维护this.state, 该数据只能在组件
才能访问. 一旦组件的this.state发生改变, React将通过调用render()重新渲染该组件.

下面的实例, 演示了利用React.Component API的事件绑定, 实现一个简单的计数器.
完整代码如下:

<!-- filename: a-stateful-component.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>A Stateful Component</title>
    <script src="https://unpkg.com/react@15.6.1/dist/react.min.js"></script>
    <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</head>

<body>
<div id="root"></div>
<script type="text/babel">

class Timer extends React.Component {
    constructor(props) {
        super(props); // ES特性
        this.state = {secondsElapsed: 0}; // elapse 流逝
    }
    
    tick() {
        this.setState(
            (prevState) => ({
                secondsElapsed: prevState.secondsElapsed + 1
            })
        );
        // 要根据以前的state值, 改变现在的state值, 需要使用函数, 上面函数
        // 的参数prevSate不是固定, 可以换成任意其它名称.
        // 传入的参数不管叫什么名称, 都将自动成为指向以前state的引用
    }
    
    componentDidMount() {
        // 这个事件将会在React成功渲染Timer组件时, 被触发
        // 其为React.Component提供的API, 名称为固定写法
        this.interval = setInterval(() => this.tick(), 1000);
        // 这里必须使用箭头函数, 直接使用this.tick, 将发生
        // 找不到this的情况
    }
    
    componentWillUnmount() {
        // 这个事件将会在Timer组件被从页面移除时被触发
        // 其为React.Component提供的API, 名称为固定写法
        clearInterval(this.interval);
    }
    
    render() {
        return (
            <div>时间流逝: {this.state.secondsElapsed}</div>
        );
    }
}

ReactDOM.render(<Timer />, document.getElementById('root'));

</script>
</body>
</html>

运行分析:

  1. 执行Timer组件的render()函数进行页面渲染, 随后执行constructor构造函数.
  2. 页面渲染完毕后执行componentDidMount().

An Application

利用stateprops, 实现一个TodoList的小应用.
完整代码如下:

<!-- filename: an-application.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World</title>
    <script src="https://unpkg.com/react@15.6.1/dist/react.min.js"></script>
    <script src="https://unpkg.com/react-dom@15.6.1/dist/react-dom.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</head>

<body>
<div id="root"></div>
<script type="text/babel">

class TodoApp extends React.Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this); // this绑定, 标配
        this.handleChange = this.handleChange.bind(this); // this绑定, 标配
        this.state = {items: [], text: ''};
    }
    render() {
        return (
            <div>
                <h3>TODO APP</h3>
                <TodoList items={this.state.items} />
                <form onSubmit={this.handleSubmit}>
                    <input value={this.state.text} onChange={this.handleChange} />
                    <button>增加第 {this.state.items.length + 1} 项</button>
                    <p>单击button, 就意味着表单被提交</p>
                </form>
            </div>
        );
    }

    handleChange(e) {
        this.setState({
            text: e.target.value
        });
    }

    handleSubmit(e) {
        e.preventDefault();
        var newItem = {
            text: this.state.text,
            id: Date.now()  
            // 获取当前时间作为list key
            // 这是react推荐用法
        };
        this.setState(
            (prevState) => ({
                items: prevState.items.concat(newItem),
                text: '' // 单击提交, 就把当前输入框清空
            })
        );
        // console.log(this.state);
    }
}

class TodoList extends React.Component {
    render() {
        return (
            <ul>
                {this.props.items.map(
                    item => 
                    <li key={item.id}>{item.text}</li>  
                )}
            </ul>
        );
    }
}

ReactDOM.render(
    <TodoApp />,
    document.getElementById('root')
);

</script>
</body>
</html>

代码运行分析:

  1. 当我们编辑输入框时, 实时的把录入内容, 同步到this.sate.text. 为此我们为输入框,
    绑定onChange事件. 输入框的value始终和this.sate.text保持同步.
  2. 当我们单击提交按钮时, 我们把当前输入框的值, 追加到this.state.items中, 为此,
    我们为提交按钮绑定onSubmit事件.
  3. 我们把用户输入的内容数组, 也就是this.state.items数组, 作为参数, 传给子组件TodoList,
    也就是给TodoListitems={this.state.items}属性, 我们在子组件里this.props.items,
    拿到从父组件里得到的用户输入数组, 使用map循环遍历, 并输出.
posted @ 2017-09-09 11:00  阿胜4K  阅读(612)  评论(0编辑  收藏  举报