React - 快速入门

目录

 

一.构建项目

– 使用 create-react-app 创建一个React应用

– JSX 混合使用了 HTML 和 JavaScript 在 React 组件的方法中定义它的输出(html + js混编)

– React 中,组件、示例和元素是不同的概念

– ReactDOM.render() 是 React 应用连接 DOM 的入口方法

– JavaScript 内建函数可以在 JSX 中使用

– map 遍历方法,可以被用来把列表成员渲染成 HTML 的元素

– ES6箭头函数简单写法

二.React基础

组件内部状态

ES6 对象初始化

单向数据流

绑定

事件处理

和表单交互

ES6 解构

受控组件

拆分组件

可组合组件

可复用组件

给组件声明样式

回顾基础

• React

• ES6

• General

三.生命周期

componentWillMount()

componentDidMount()

componentWillUpdate(object nextProps, object nextState)

componentDidUpdate(object prevProps, object prevState)

componentWillUnmount()

componentWillReceiveProps(object nextProps):

shouldComponentUpdate(object nextProps, object nextState):

getInitialState

Render

举个栗子,下面是React与Ajax的配合

四.数据交互

数据请求

扩展操作符

条件渲染

客户端处理-服务端搜索


一.构建项目

 

使用 create-react-app 创建一个React应用

npm install -g create-react-app
create-react-app --version
*v1.4.1
create-react-app hackernews
cd hackernews
// 在 http://localhost:3000 启动应用
npm start
// 运行所有测试
npm test
// 构建项目的产品文件
npm run build

 

JSX 混合使用了 HTML 和 JavaScript 在 React 组件的方法中定义它的输出(html + js混编)

ReactDOM.render(
    

Hello React World

,     document.getElementById('root') );

 

React 中,组件、示例和元素是不同的概念

import React, { Component } from 'react';

class App extends Component {   //App为组件

 

ReactDOM.render() 是 React 应用连接 DOM 的入口方法

render() {
    ...
    }

 

JavaScript 内建函数可以在 JSX 中使用

 

– map 遍历方法,可以被用来把列表成员渲染成 HTML 的元素

const list = [
    {
    title: '百度',
    url: 'https://www.baidu.com',
    author: '李彦宏',
    objectID: 0,
    },
    {
    title: 'QQ',
    url: 'https://www.qq.com',
    author: '马化腾',
    objectID: 1,
    },
];

 

使用map方法遍历以上数据

 

list.map( (item,key) =>

 

ES6箭头函数简单写法

原:

{list.map(function(item, key) {
return (
    
...
    ); })

改写为:

{list.map( (item, key)=>
    
)}

 

二.React基础

 

组件内部状态

 

组件内部状态也被称为局部状态,允许你保存、修改和删除存储在组件内部的属性。使用 ES6 类组件可以在构造函数中初始化组件的状态。构造函数只会在组件初始化时调用一次。

class App extends Component {
    constructor(props) {
    super(props);
    }
    this.state = {
        list: list,
    };
}

 

当你使用 ES6 编写的组件有一个构造函数时,它需要强制地调用 super(); 方法,因为这个App 组件是 Component 的子类。

 

你也可以调用 super(props); ,它会在你的构造函数中设置 this.props 以供在构造函数中访问它们。否则当在构造函数中访问 this.props ,会得到 undefined 。

state 通过使用 this 绑定在类上。因此,你可以在整个组件中访问到 state。例如它可以用在 render() 方法中。

例:list.map(function(item, key)    ===》   thislist.map(function(item, key)

ES6 对象初始化

 // ES5
var userService = {
getUserName: function (user) {
return user.firstname + ' ' + user.lastname;
},
};
// ES6
const userService = {
getUserName(user) {
return user.firstname + ' ' + user.lastname;
},
};
//值得一提的是你可以在 ES6 中使用计算属性名。
// ES5
var user = {
name: 'Robin',
};
// ES6
const key = 'name';
const user = {
[key]: 'Robin',
}

 

 

 

单向数据流

通过 JavaScript 内置的 filter 方法来删除列表中的一项。fitler 方法以一个函数作为输入。这个函数可以访问列表中的每一项,因为它会遍历整个列表。通过这种方式,你可以基于过滤条件来判断列表的每一项。如果该项判断结果为 true,则该项保留在列表中。否则将从列表中过滤掉。另外,好的一点是这个方法会返回一个新的列表而不是改变旧列表。它遵循了 React 中不可变数据的约定。

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            list: list,
        };
        this.clickFunc = this.clickFunc.bind(this);
    }

    clickFunc(id) {
        const isNotId = item => item.objectID !== id;
        const updatedList = this.state.list.filter(isNotId);
        this.setState({list: updatedList});
    }

    render() {
        return (
            
{this.state.list.map( (item,key) =>
{item.title} {item.author} {item.num_comments} {item.points} {key}
)}
); } }
this.clickFunc = this.clickFunc.bind(this); } clickFunc(id) { const isNotId = item => item.objectID !== id; const updatedList = this.state.list.filter(isNotId); this.setState({list: updatedList}); } render() { return (
{this.state.list.map( (item,key) =>
{item.title} {item.author} {item.num_comments} {item.points} {key}
)}
); } }

React - 快速入门_第1张图片

 

绑定

当使用 ES6 编写的 React 组件时,了解在 JavaScript 类的绑定会非常重要

如上文的:this.onDismiss = this.onDismiss.bind(this);

 

 

为什么一开始就需要这么做呢?绑定的步骤是非常重要的,因为类方法不会自动绑定this到实例上。如果没有进行绑定,则this会指向undefined。这也是React的主要BUG来源!

 

类方法的绑定也可以写起其他地方,比如写在 render() 函数中。

render() {
    return (
        
        );
}

但是你应该避免这样做,因为它会在每次 render() 方法执行时绑定类方法。总结来说组件每次运行更新时都会导致性能消耗。当在构造函数中绑定时,绑定只会在组件实例化时运行一次,这样做是一个更好的方式。

 

还有别的方法,在构造函数内部改写。但是,构造函数目的只是实例化你的类以及所有的属性。这就是为什么我们应该把业务逻辑应该定义在构造函数之外。

class ExplainBindingsComponent extends Component {
        constructor() {
        super();
            this.doSomething = this.doSomething.bind(this);
            this.doSomethingElse = this.doSomethingElse.bind(this);
        }
        doSomething() {
        // do something
        }
        doSomethingElse() {
        // do something else
        }
        ...
}

提一下,类方法可以使用ES6 的箭头函数做到自动地绑定。

class ExplainBindingsComponent extends Component {
        onClickMe = () => {
            console.log(this);
        }
        render() {
            return (
                
                );
        }
}onClickMe = () => {
            console.log(this);
        }
        render() {
            return (
                
                );
        }
}

如果在构造函数中的重复绑定对你有所困扰,你可以使用这种方式代替。React 的官方文档中坚持在构造函数中绑定类方法。

 

事件处理

传给元素事件处理器的内容必须是函数。作为一个示例,请尝试以下代码:

class App extends Component {
...
    render() {
        return (
            
{this.state.list.map(item =>
              
                 

)}
); }}

 

它会在浏览器加载该程序时执行,但点击按钮时并不会。而下面的代码只会在点击按钮时

执行。它是一个在触发事件时才会执行的函数。

 

和表单交互

第一步,你需要在 JSX 中定义一个带有输入框的表单。

class App extends Component {
    ...
    render() {
        return (
            
{this.state.list.map(item => ... )}
); } }

在下面的场景中,将会使用在输入框中的内容作为搜索字段来临时过滤列表。为了能根据输入框的值过滤列表,你需要将输入的值储存在你的本地状态中,但是如何访问这个值呢?你可以使用 React 的合成事件来访问事件返回值。
让我们为输入框定义一个 onChange 处理程序。

class App extends Component {
    ...
    render() {
        return (
            
...
); } }

又是一个类方法。初始搜索栏为空。

 
class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            list,
            searchTerm: '',
        };
        this.onSearchChange = this.onSearchChange.bind(this);
        this.onDismiss = this.onDismiss.bind(this);
    }
...
        onSearchChange(event) {
            this.setState({ searchTerm: event.target.value });
        }
}

现在列表还没有根据储存在本地状态中的输入字段进行过滤。在 map 映射列表之前,插入一个过滤的方法。

{this.state.list.filter(isSearched(this.state.searchTerm)).map(item =>

在函数外部定义一个方

function isSearched(searchTerm) {
    return function(item) {
        return item.title.toLowerCase().includes(searchTerm.toLowerCase());
    }
}

 

ES6 解构

在 JavaScript ES6 中有一种更方便的方法来访问对象和数组的属性,叫做解构。

比较一下

const user = {
firstname: 'Robin',
lastname: 'Wieruch',
};
// ES5
var firstname = user.firstname;
var lastname = user.lastname;
console.log(firstname + ' ' + lastname);
// output: Robin Wieruch
// ES6
const { firstname, lastname } = user;
console.log(firstname + ' ' + lastname);
//又或者
const users = ['Robin', 'Andrew', 'Dan'];
const [
    userOne,
    userTwo,
    userThree
] = users;
console.log(userOne, userTwo, userThree);

解构,可以让 map 和filter 部分的代码更简短。

render() {
    const { searchTerm, list } = this.state;
    return (
        
... {list.filter(isSearched(searchTerm)).map(item => ... )}
);
const { searchTerm, list } = this.state; return (
... {list.filter(isSearched(searchTerm)).map(item => ... )}
);

贴一个ES5、ES6对比

// ES5
var searchTerm = this.state.searchTerm;
var list = this.state.list;
// ES6
const { searchTerm, list } = this.state;

 

受控组件

 

表单元素比如 ,