React 指引

React 指引

最近在学 React, 看到一篇博客写的不错,可惜是英文版,正巧无事,翻译过来吧。

原文地址: https://www.taniarascia.com/getting-started-with-react/


准备

在开始使用 React 之前,有一些事情需要准备好:

  1. 对 HTML & CSS 有一个基本的了解;
  2. 了解 JavaScript;
  3. 对 DOM 有基本的认识;
  4. 熟悉 ES6 语法和特征;
  5. 安装好 Node.js 和 npm.

注:HTML, CSS, JS, DOM 可以通过 W3School 学习;Node.js 和 npm 的安装教程网上一大堆。

目标

  1. 掌握基本的 React 概念和有关的组件,例如 Babel, Webpack, JSX, components, props, state, lifecycle.
  2. 通过以上概念建立一个简单的React app.

什么是 React

  • React 是 JavaScript 中最流行的库;
  • 不同于 Angular, React 并不是一个框架;
  • React 是 Facebook 创建的一个开源项目;
  • React 用来构建 UI 界面;
  • React 是 MVC 的视图层;

安装

两种安装方式:

  1. 静态 HTML 文件

首先要明白,这种方式并不常用,但可以帮助我们快速使用 React.

首先,我们建立一个index.html文件,通过head标签下的三个script,可将 React, React DOM, Babel 加载到其中。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>

  <body>
    <div id="root"></div>

    <script type="text/babel">
      // React code will go here
    </script>
  </body>
</html>

<div>标签下的<script>,可以输入代码,不妨写一个 Hello World:

class App extends React.Component{//使用ES6类来创建React组件
    render() {
        return <h1>Hello World</h1>;//JSX语法
    }
}

ReactDOM.render(//使用该方法来调用 App 类
    <App/>,
    document.getElementById('root')
)

用浏览器打开上述 html 文件,结果为:

在这里插入图片描述

  1. 创建 React App

方法 1 并不高效,这里介绍更常用的方法。

首先确保电脑安装了 Node.js

打开终端(Windows下的cmd),输入指令 npx create-react-app react-tutorial, 稍等,安装好后,会出现一个 react-tutorial文件夹,用指令cd react-tutorial打开该文件夹,在该文件下,输入指令npm start便启动了该项目,随后,会弹出一个地址为localhost:3000的浏览器窗口。

样式如下:

在这里插入图片描述

下面,来看文件夹 react-tutorial的结构。

在这里插入图片描述

/public,最重要的文件是index.html.
/src文件夹中存放了 React 代码。

现在,为了编写我们自己的项目,需要删除/src文件夹下的所有文件,然后在该目录下创建我们自己的代码文件:index.cssindex.js.

css格式是负责样式,因此对于index.css文件,可以自己写一个布局,也可以直接copy别人的代码,并无大碍。这里选择原作者给的样式,地址为:https://taniarascia.github.io/primitive/css/main.css 将该文本的内容直接拷贝到index.css中即可。

对于index.js,首先需要导入一些头文件:

import React,{Component} from "react";
import ReactDOM, {render} from "react-dom"
import './index.css'    //调用index.css

下面开始编辑内容,从Hello React开始:

注意,在下属代码中,我们用className取代HTML中的class.这是因为以下代码皆为 JavaScript 代码,而不是HTML代码。

class App extends React.Component{
    render() {
        return(
            <div className="App">   
                <h1>Hello React</h1>
            </div>
        );
    }
}

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

此时,在浏览器中输入地址http://localhost:3000/将会看到:
在这里插入图片描述

插件:React Developer Tools

为了更好地在浏览器中调试 React 代码,建议使用浏览器插件 React Developer Tool. 例如Chrome中,直接打开Chrome商店下载即可。

下载完成后,当使用 F12 进入调试界面即可。

在这里插入图片描述

JSX: JavaScript + XML

在上述index.js中,我们使用了一种类似于 HTML 的代码:

<div className="App">   
	<h1>Hello React</h1>
</div>

但它并不是HTML, 而是JSX: JavaScript XML.

首先,需要讲清楚的是:JSX 在 React 中是可用可不用的,但是为了方便,我们采用 JSX 格式。

这里给出使用 JSX 时需要注意的几点:

  1. className用来代替class,因为class在JS中是一个关键字。
  2. JSX 采用骆驼明明法,例如: onclick在JSX中应该变为onClick.
  3. 单括号必须用’/'结束,例如<img/>.
  4. 在JSX中,可以使用’{}'来代表变量。

Components

index.js中,我们创建了App组件。

但是对于许多 React 而言,通常存在多个小组件,为了方便,每个组件通常都有自己对应的文件,我们的项目也需要改一下:

在同目录下(即/src目录下)新建一个App.js, 将index.js中的 class App extends React.Component移动到App,js中,最后,两个文件的代码如下:

App.js:

import React,{Component} from "react";

class App extends React.Component{
    render() {
        return(
            <div className="App">
                <h1>Hello React</h1>
            </div>
        );
    }
}

export default App

index.js:

import React,{Component} from "react";
import ReactDOM, {render} from 'react-dom'
import './index.css'    //调用index.css
import App from './App.js'

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

Class Components

下面,我们创建一个 Table 组件。

首先,在 src 目录下创建 Table.js, 其代码如下所示:

import React,{Component} from "react";

class Table extends React.Component{
    render() {
        return (
            <table>
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Job</th>
                </tr>
                </thead>
                <tbody>
                <tr>
                    <th>张三</th>
                    <th>码农</th>
                </tr>
                <tr>
                    <th>李四</th>
                    <th>程序员</th>
                </tr>
                </tbody>
            </table>
        );
    }
}

export default Table

返回到 App.js中,为了加载 Table.js, 在导入头文件的代码上添加一行import Table from './Table'.
添加上述代码后,在 App.js中可以使用 <Table/>.

在之前,我们输出了 “Hello React”, 现在删除App类中的<h1>Hello React</h1>,将其内容更改为<Table/>.

此时,App.js全部内容为:

import React,{Component} from "react";

import Table from './Table'


class App extends React.Component{
    render() {
        return(
            <div className="App">
                <Table/>
            </div>
        );
    }
}

export default App

再登入http://localhost:3000/,展示的内容为:
在这里插入图片描述

到目前为止,我们创建了一个表格 Table。

Simple Components

Components 包含两类:1. Class Components; 2. Simple Components.

上一节我们介绍了Class Components, 这一节我们介绍 Simple Components.

Simple Components 是一个函数,不使用关键字class.

例如,对于上一小节的Table.js,使用 Class Components 时有一个class Table.

我们使用 Simple Components 可以将其更改为两个函数: table header 和 table body.

更改后的Table.js:

import React,{Component} from "react";

const TableHeader = () =>{
    return (
        <thead>
        <tr>
            <th>Name</th>
            <th>Job</th>
        </tr>
        </thead>
    )
};

const TableBody = () =>{
    return(
        <tbody>
        <tr>
            <th>张三</th>
            <th>码农</th>
        </tr>
        <tr>
            <th>李四</th>
            <th>程序员</th>
        </tr>
        </tbody>    
    )
};

class Table extends Component {
    render() {
        return (
            <table>
                <TableHeader />
                <TableBody />
            </table>
        )
    }
}

export default Table

此时,在网页上现实的结果并不发生变化。正如你所看到的,simple/class components 可以混合使用。

Props

现在,我们有了 Table 组件,但数据是不可修改的。React 的使用 props 和 states 操控数据,现在我们首先来看 props.

首先,将组件 TableBody 中的数据全部剪贴:

const TableBody = () =>{
    return <tbody/>
};

然后数据以列表的形式移动到App.js

class App extends React.Component{
    render() {
        const characters = [
            {
                name: '张三',
                job: '码农',
            },
            {
                name: '李四',
                job: '程序员',
            },
        ];

        return(
            <div className="container">
                <Table/>
            </div>
        );
    }
}

现在,我们要将数据传递给 Table, 我们将传递的属性名定义为 characterData, 它的作用是传递变量characters.

App.js中的return语句更改为如下:

return(
	<div className="container">
		<Table characterData={characters}/>
	</div>
);

现在,数据已经传递到Table中了,我们需要在Table.js中访问这些数据。

Table.js中,我们将其中 Table 类的代码更改为如下:

class Table extends Component {
    render() {
        const {characterData} = this.props;
        return (
            <table>
                <TableHeader />
                <TableBody characterData={characterData}/>
            </table>
        );
    }
}

现在,登入到浏览器中,使用 React 开发者工具,可以看到:
在这里插入图片描述
这表明数据已经以虚拟DOM的形式存储下来,但是并不是真正的DOM. 因此,此时在浏览器上无法显示表格。

为了显示表格,我们应该在 TableBody 中接受数据,在这里,我们使用map来返回一个表格航。

更改后的 Table.js 的 TableBody 如下:

const TableBody = props =>{
    const rows = props.characterData.map((rows, index)=>{
        return (
            <tr key={index}>
                <td>{rows.name}</td>
                <td>{rows.job}</td>
            </tr>
        )
    })
    return <tbody>{rows}</tbody>
}

此时再看前端网页,数据已经显示上了:
在这里插入图片描述

props 是一个高效的传递数据的方法,但可惜,这样传递数据的方式仅仅是只读的。

State

在上一节中,我们将数据以序列变量的形式通过 props 传递。但是,如果我们想删除从表格中删除一行,props 是无法做到的。

因此我们需要 state.

首先,我们在App.js中创建一个 state对象:

class App extends React.Component{
    state = {
		characters: [],
	};
}

接着,将数据移动到 characters 中,同时删除 render() 里的 character.

class App extends React.Component{
	state = {
        characters: [
            {
                name: '张三',
                job: '码农',
            },
            {
                name: '李四',
                job: '程序员',
            },
        ],
    };
}

为了实现删除一行的目的,我们在 App 类中添加一个removeCharacter方法:

removeCharacter = index => {
  const { characters } = this.state

  this.setState({
    characters: characters.filter((character, i) => {
      return i !== index
    }),
  })
}

此处,filter的实现和功能不再赘述。

之后,我们需要将函数传递到组件中,具体做法是在render中添加一个 button 来调用者函数。

为实现上述需求,首先将App.js中的removeCharacter函数以 props 的方式传递到Table中,先将App.js的 render() 更改为如下:

render() {
    const { characters } = this.state
    return(
        <div className="container">
            <Table characterData={characters} removeCharacter={this.removeCharacter}/>
        </div>
    );
}

此时,对于Table.js文件,在Table中接受该函数:

class Table extends Component {
    render() {
        const {characterData, removeCharacter} = this.props;
        return (
            <table>
                <TableHeader />
                <TableBody characterData={characterData} removeCharacter={removeCharacter}/>
            </table>
        );
    }
}

之后,需要从 Table 中传递到 TableBody 中,同时添加一个删除的按钮:

const TableBody = props =>{
    const rows = props.characterData.map((rows, index)=>{
        return (
            <tr key={index}>
                <td>{rows.name}</td>
                <td>{rows.job}</td>
                <td>
                    <button onClick={ () => props.removeCharacter(index)}>Delete</button>
                </td>
            </tr>
        )
    })
    return <tbody>{rows}</tbody>
};

登入浏览器后,显示结果如下:
在这里插入图片描述
点击第一个 delete 后的结果为:
在这里插入图片描述

提交表格数据

我们将数据存储到 state 中,并且实现了删除表项,然而,我们如何添加新的数据到 state 中?

首先,为了方便,我们将App.js中App类下的state中的所有表项删除:

    state = {
        characters: [],
    };

接下来我们创建一个Form.js用来存储Form组件,在该组件中,首先使用一个构造函数constructor, 用来接受父亲的props.
另外,给Form中的对象一个初始化,并将该初始化赋值给state.

此时,Form.js的代码如下:

import React, { Component } from 'react'

class Form extends Component {
    constructor(props) {
        super(props)

        this.initialState = {
            name: '',
            job: '',
        }

        this.state = this.initialState
    }
}

export default Form;

我们的目标是,当Form中的state每次发生变化时提交表格,将数据传递给App中的 state, 接着再从App中传递到Table,更新表格。

首先,我们在Form.js中创建一个函数 handleChange,每次有提交时便运行该函数。

handleChange = event =>{
    const {name, value} = event.target

    this.setState({
        [name]:value,
    })
}

之后,在Form.js创建render, 将上述构建的 name, value 转化为 name, job:

render() {
    const { name, job } = this.state;

    return (
        <form>
            <label for="name">Name</label>
            <input
                type="text"
                name="name"
                id="name"
                value={name}
                onChange={this.handleChange} />
            <label for="job">Job</label>
            <input
                type="text"
                name="job"
                id="job"
                value={job}
                onChange={this.handleChange} />
        </form>
    );
}

随后,在App.js中,render更改为如下:

render() {
    const { characters } = this.state
    return(
        <div className="container">
            <Table characterData={characters} removeCharacter={this.removeCharacter}/>
            <Form/>
        </div>
    );
}

此时来看前端页面:
在这里插入图片描述
此时,随便输入一个name 和 job, 在 React 开发者工具中,我们已经可以看到,并没有submit。仅仅是在Form中更新了。
在这里插入图片描述
之后,让我们开始书写submit代码。

在```App.js``中,添加一个 handleSubmit函数:

handleSubmit = character => {
  this.setState({ characters: [...this.state.characters, character] })
}

之后将render中return的<Form>更改为<Form handleSubmit={this.handleSubmit} />.

现在,返回到Form.js,创建一个函数submitForm(),然后将Form的state传递出去。

submitForm = () => {
  this.props.handleSubmit(this.state)
  this.setState(this.initialState)
}

最后,在render中添加一个“提交按钮”:

render() {
    const { name, job } = this.state;

    return (
        <form>
            <label for="name">Name</label>
            <input
                type="text"
                name="name"
                id="name"
                value={name}
                onChange={this.handleChange} />
            <label for="job">Job</label>
            <input
                type="text"
                name="job"
                id="job"
                value={job}
                onChange={this.handleChange} />
            <input type="button" value="Submit" onClick={this.submitForm} />
        </form>

    );
}

最终显示的效果如下:
在这里插入图片描述

随便写两个表格提交后的效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值