ReactJS入門

1、前端開發的演變

到目前爲止,前端的開發經歷了四個階段,目前處於第四個階段。這四個階段分別是:

階段一:靜態頁面階段

在第一個階段中前端頁面都是靜態的,所有前端代碼和前端數據都是後端生成的。前端只是純粹的展示功能,js腳本的作用只是增加一些特殊效果,比如那時很流行用腳本控制頁面上飛來飛去的廣告。

那時的網站開發,採用的是後端 MVC 模式。

  • Model(模型層):提供/保存數據
  • Controller(控制層):數據處理,實現業務邏輯
  • View(視圖層):展示數據,提供用戶界面

前端只是後端 MVC 的 V。

階段二:ajax階段

2004年,A JAX 技術誕生,改變了前端開發。Gmail 和 Google地圖這樣革命性的產品出現,使得開發者發現,前端的作用不僅僅是展示頁面,還可以管理數據並與用戶互動。

就是從這個階段開始,前端腳本開始變得複雜,不再僅僅是一些玩具性的功能。

階段三:前端MVC階段

2010年,第一個前端 MVC 框架 Backbone.js 誕生。它基本上是把 MVC 模式搬到了前端,但是隻有 M (讀寫數據)和 V(展示數據),沒有 C(處理數據)。

有些框架提出了MVVM模式,用 View Model 代替 Controller。Model 拿到數據以後,View Model 將數據處理成視圖層(View)需要的格式,在視圖層展示出來。

階段四:SPA階段

前端可以做到讀寫數據、切換視圖、用戶交互,這意味着,網頁其實是一個應用程序,而不是信息的純展示。這種單張網頁的應用程序稱爲 SPA(single-page-application)。

2010年後,前端工程師從開發頁面(切模板),逐漸變成了開發“前端應用”(跑在瀏覽器裏面的應用程序)。

目前,最流行的前端框架 Vue、Angular、React 等等,都屬於 SPA 開發框架。

2、ReactJS簡介

官網: https://reactjs.org/ image.png

官方一句很簡單的話,道出了什麼是ReactJS,就是,一個用於構建用戶界面的JavaScript框架,是Facebook開發的一款的JS框架。

ReactJS把複雜的頁面,拆分成一個個的組件,將這些組件一個個的拼裝起來,就會呈現多樣的頁面。ReactJS可以用於 MVC 架構,也可以用於 MVVM 架構,或者別的架構。

ReactJS圈內的一些框架簡介:

  • Flux
    • Flux是Facebook用戶建立客戶端Web應用的前端架構,它通過利用一個單向的數據流補充了React的組合視圖組件,這更是一種模式而非框架。
  • Redux
    • Redux 是 JavaScript狀態容器,提供可預測化的狀態管理。Redux可以讓React組件狀態共享變得簡單。
  • Ant Design of React
    • 阿里開源的基於React的企業級後臺產品,其中集成了多種框架,包含了上面提到的Flux、Redux。
    • Ant Design提供了豐富的組件,包括:按鈕、表單、表格、佈局、分頁、樹組件、日曆等。

3、搭建環境

3.1、創建項目

我們依然選擇使用UmiJS作爲構建工具。

創建工程: 1

2

3

輸入命令,進行初始化:

tyarn init -y

4

在命令輸入如下命令:

tyarn add umi --dev #項目中添加umi的依賴

5

可以看到,相關的依賴已經導入進來了。

3.2、編寫HelloWorld程序

第一步,在工程的根目錄下創建config目錄,在config目錄下創建config.js文件。

在UmiJS的約定中,config/config.js將作爲UmiJS的全局配置文件。 在umi中,約定的目錄結構如下:

├─ dist/                            // 默認的 build 輸出目錄
├─ mock/                            // mock 文件所在目錄,基於 express
├─ config/
    ├─ config.js                    // umi 配置,同 .umirc.js, 二選一
├─ src/                             // 源碼目錄,可選
    ├─ layouts/index.js             // 全局佈局
    ├─ pages/                       // 頁面目錄,裏面的文件及路由
        ├─ .umi/                    // dev 臨時目錄,需添加到 .gitignore
        ├─ .umi-production/         // build 臨時目錄,會自動刪除
        ├─ document.ejs             // HTML 模板
        ├─ 404.js                   // 404 頁面
        ├─ page1.js                 // 頁面1,任意命名,到處 react 組件
        ├─ page1.test.js            // 用例文件,umi test 會匹配所有 .test.js 和 .e2e.js 結尾文件
        ├─ page2.js                 // 頁面2,任意命名
    ├─ global.css                   // 約定的全局樣式文件,自動引入,也可以用global.less
    ├─ global.js                    // 可以在這裏加入 polyfill
├─ .umirc.js                        // umi 配置,同 config/config.js, 二選一
├─ .env                             // 環境變量
├─ package.json

在config.js文件中輸入以下內存,以便後面使用:

//導出一個對象,暫時設置爲空對象,後面再填充內容
export default {};

第二步,創建HelloWorld.js頁面文件

在umi中,約定存放頁面代碼的文件夾是在src/pages,可以通過singular:false來設置單數的命名方式,我們採用默認即可。 6

在HelloWorld.js文件中輸入如下內容:

export default () => {
    return <div>hello world</div>;
}

在這裏,可以會比較奇怪,怎麼可以在js文件中寫html代碼,其實,這是react自創的寫法,叫JSX,後面我們再細說。

第三步,啓動服務查看頁面效果

#啓動服務
umi dev

7

可以看到,通過/HelloWorld路徑即可訪問到剛剛寫的HelloWorld.js文件。

在 umi 中,可以使用約定式的路由,在 pages 下面的 JS 文件都會按照文件名映射到一個路由,比如上面這個例子,訪問 /helloworld 會對應到HelloWorld.js。

當然了,也可以自定義路由,具體的路由配置在後面講解。

3.3、添加umi-plugin-react插件

umi-plugin-react插件是umi官方基於react封裝的插件,包含了13個常用的進階功能。

具體可查看:https://umijs.org/zh/plugin/umi-plugin-react.html

#添加插件
tyarn add umi-plugin-react --dev

添加成功: 8

接下來,在config.js文件中引入該插件:

export default {
    plugins: [
        ['umi-plugin-react', {
        //暫時不啓用任何功能
        }]
    ]
};

3.4、構建和部署

現在我們寫的js,必須通過umi先轉碼後才能正常的執行,那麼我們最終要發佈的項目是普通的html、js、css,那麼應該怎麼操作呢?

其實,通過umi是可以進行轉碼生成文件的,具體操作如下:

umi build

9

10

可以看到,已經生成了index.html和umi.js文件。我們打開umi.js文件看看。 11

首先,看到的是umi.js文件是一個已經壓縮過的文件,然後搜索“hello world”,可以找到,我們剛剛寫的代碼已經被轉碼了。

至此,開發環境搭建完畢。

4、React快速入門

4.1、JSX語法

JSX語法就是,可以在js文件中插入html片段,是React自創的一種語法。

JSX語法會被Babel等轉碼工具進行轉碼,得到正常的js代碼再執行。

使用JSX語法,需要2點注意:

  1. 所有的html標籤必須是閉合的,如:
<div>hello world</div>
# 寫成這樣是不可以的:
<div>hello world
  1. 在JSX語法中,只能有一個根標籤,不能有多個。
const div1 = <div>hello world</div> //正確
const div2 = <div>hello</div> <div>world</div> //錯誤

SX語法中,如果想要在html標籤中插入js腳本,需要通過{}插入js腳本。

export default () => {
    function name() {
        return "李四";
    }
    // 引用js腳本 使用 { } 插入腳本
    return <div>hello world {name()}</div>;
}

4.2、組件

件是React中最重要也是最核心的概念,一個網頁,可以被拆分成一個個的組件, 像這樣: 12React中,這樣定義一個組件:

import React from 'react'; //第一步,導入React
class HelloWorld extends React.Component { //第二步,編寫類並且繼承 React.Component
    render(){ //第三步,重寫render()方法,用於渲染頁面
        return <div>hello world!</div> //JSX語法
    }
}
export default HelloWorld; //第四步,導出該類

查看效果: 13

4.2.1、導入自定義組件

創建Show.js文件,用於測試導入組件:

import React from 'react'
import HelloWorld from './HelloWorld' //導入HelloWorld組件
class Show extends React.Component {
    render() {
        return <HelloWorld/>; //使用HelloWorld組件
    }
}

export default Show;

測試: 14

4.2.2、組件參數

組件是可以傳遞參數的,有2種方式傳遞,分別是屬性和標籤包裹的內容傳遞,具體使用如下,修改Show.js:

import React from 'react'
import HelloWorld from './HelloWorld' //導入HelloWorld組件
class Show extends React.Component {
    render() {
        return <HelloWorld name="zhangsan">shanghai</HelloWorld>; //使用HelloWorld組件
    }
}

export default Show;

其中,name="zhangsan"就是屬性傳遞,shanghai就是標籤包裹的內容傳遞。

那麼,在HelloWord.js組件中如何接收參數呢?

對應的也是2種方法:

  • 屬性:this.props.name 接收;
  • 標籤內容:this.props.children 接收;

使用如下,修改HelloWorld.js:

import React from 'react'; //第一步,導入React
class HelloWorld extends React.Component { //第二步,編寫類並且繼承 React.Component
    render(){ //第三步,重寫render()方法,用於渲染頁面
        return <div>hello world! name={this.props.name}, address= {this.props.children}</div> //JSX語法
    }
}
export default HelloWorld; //第四步,導出該類

測試: 1516

4.2.3、組件的狀態

每一個組件都有一個狀態,其保存在this.state中,當狀態值發生變化時,React框架會自動調用render()方法,重新渲染頁面。

其中,要注意兩點:

一: this.state值的設置要在構造參數中完成;

二:要修改this.state的值,需要調用this.setState()完成,不能直接對this.state進行修改;

下面通過一個案例進行演示,這個案例將實現:通過點擊按鈕,不斷的更新this.state,從而反應到頁面中。

新建一個List.js 文件:

import React from 'react'

class List extends React.Component {
    constructor(props) { // 構造參數中必須要props參數
        super(props); // 調用父類的構造方法
        this.state = { // 初始化this.state
            dataList: [1, 2, 3],
            maxNum: 3
        };
    }

    render() {
        return (
            <div>
                <ul>
                    {
                        // 遍歷值
                        this.state.dataList.map((value, index) => {
                            return <li key={index}>{value}</li>
                        })
                    }
                </ul>
                <button
                    onClick={() => { //爲按鈕添加點擊事件
                        let maxNum = this.state.maxNum + 1;
                        let list = [...this.state.dataList, maxNum];
                        this.setState({ //更新狀態值
                            dataList: list,
                            maxNum: maxNum
                        });
                    }}>
                    添加
                </button>
            </div>
        );
    }
}

export default List;

初始化狀態: 17

當點擊“添加”按鈕: 18

過程分析: 19

4.2.4、生命週期

組件的運行過程中,存在不同的階段。React爲這些階段提供了鉤子方法,允許開發者自定義每個階段自動執行的函數。這些方法統稱爲生命週期方法(lifecycle methods)。

生命週期示例:

import React from 'react'; //第一步,導入React
class LifeCycle extends React.Component {
    constructor(props) {
        super(props);
        //構造方法
        console.log("constructor()");
    }

    componentDidMount() {
        //組件掛載後調用
        console.log("componentDidMount()");
    }

    componentWillUnmount() {
        //在組件從 DOM 中移除之前立刻被調用。
        console.log("componentWillUnmount()");
    }

    componentDidUpdate() {
        //在組件完成更新後立即調用。在初始化時不會被調用。
        console.log("componentDidUpdate()");
    }

    shouldComponentUpdate(nextProps, nextState) {
        // 每當this.props或this.state有變化,在render方法執行之前,就會調用這個方法。
        // 該方法返回一個布爾值,表示是否應該繼續執行render方法,即如果返回false,UI 就不會更新, 默認返回true。
        // 組件掛載時,render方法的第一次執行,不會調用這個方法。
        console.log("shouldComponentUpdate()");
    }

    render() {
        return (
            <div>
                <h1>React Life Cycle!</h1>
            </div>
        );
    }
}

export default LifeCycle;

測試結果: 20

源代碼獲取

本文首發於公衆號「曉明的30天實驗室」,微信公衆號裏回覆 11299 獲取源代碼地址;

如果你覺得文章還不錯,請大家點贊分享下。你的肯定是我最大的鼓勵和支持。

發佈了25 篇原創文章 · 獲贊 9 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章