1. 程式人生 > >一步一步架構 react 伺服器渲染同構框架

一步一步架構 react 伺服器渲染同構框架

一個能夠支援前後端分離並支援中間層同構的完整框架,或許現在它還不夠完善,但是我會把構建該框架中遇到的問題都列出來,以方便其他人遇到問題不在需要去到處搜尋問題,希望為自己搭建框架的人有一些幫助,文件也會不斷更新和優化,你可以watch專案隨時看到文件的更新,也希望最後成為一個完整而又完美的框架,如果這些問題對你有幫助,請點個star吧,感謝~ ~

框架名字

為什麼叫這個名字?

因為這是一份送給一隻名叫Fairy Mo(美人)的貓的禮物 ~

計劃執行

  •  路由同步 React-router及Koa-router同步
  •  模板同步 View層同步,使用react-dom/server實現
  •  資料同步 使用Redux及React-redux實現
  •  css-modules同步 保證前後端生成的css-modules相同
  •  webpack熱載入元件優化

怎麼安裝

開啟本地資料庫Mysql,並使用phpmyadmin類似的工具在mysql中建立資料庫(名字隨意之後要填寫),之後將mysql中的資料夾sql檔案匯入資料庫, 最後在server/config/db.json中配置mysql的資料庫名稱和使用者名稱密碼即可

npm i
npm start

框架優勢

  • 路由同步(前後端共用一套路由)
  • 模板同步(前後端共用一套模板)
  • 資料同步(前後端公用一套資料狀態機)

同構對比之前非同構載入對比, 可以明顯看到白屏時間更少, 頁面總計載入速度更快

非同構 VS 同構

前端開發中也支援react,react-router,樣式及Redux的動態更新

也想從頭到尾構建一個這樣的框架? Well, 我把構建過程儘量詳細的寫下來

架構

對於一個框架, 最重要是架構, 我們如果需要構建一個前後端中間層同構的外掛, 就需要在一個資料夾中. 考慮架構時,我為了讓前後端所使用的環境相對獨立, 前端部分可以單獨提取出來進行製作, 也希望後端部分也能更清晰的展現和管理. 我們決定將框架內容分成兩大部分, Cliet和 Server 兩個資料夾分別儲存.對於前端資料夾目錄結構相對比較固定了, 不需要考慮太多東西, 按照官方的推薦目錄即可, 將View, Router和Store區分出來即可. 而伺服器端部分, 我們考慮後還是使用最經典的MVC架構, 這樣可以將控制層, 資料層和展示層區分出來, 即利於後臺業務的解耦, 也利於我們之後的維護修改和新增新業務.

目錄結構如下:

├── client 前端開發資料夾
│   ├── assets 前端自測試打包資源生成地址
│   │   └── dist 打包生成的資原始檔, 包含js,img,css
│   │       └── js
│   │       └── css
│   │       └── img
│   ├── config webpack配置檔案目錄
│   └── src 開發目錄
│       ├── data 測試資料存放檔案
│       ├── redux
│       │   ├── actions redux的action檔案存放目錄
│       │   ├── constants 將所有action放在一起便於管理
│       │   ├── reducers redux的reducers檔案存放目錄
│       │   └── store 前端redux狀態控制存放目錄
│       ├── dist 資原始檔存放目錄
│       │   ├── css
│       │   └── img
│       │   └── js
│       ├── route 前端路由存放地址
│       └── view 前端檢視存放目錄
├── public 伺服器所使用的前端打包資料夾
│   └── dist
│       ├── css
│       ├── img
│       └── js
└── server 後端開發目錄夾
    ├── auth 許可權驗證目錄 用來存放使用者驗證部分
    ├── config 後端例如資料庫等配置檔案的存放目錄
    ├── containers 後端控制層 C 層的程式碼存放目錄
    ├── models 後端資料庫控制程式碼存放目錄
    ├── route 後端路由存放目錄
    └── view 後端頁面生成外套層存放目錄,由於介面同步, 後端只負責生成頁面時的外套巢狀

前言

為什麼要用中間同構?中間同構是什麼?

在出現同構之前,我們會讓後端輸出API的json資料, 而前端接收到這些資料以後, 進行封裝和拼裝,這樣會出現一個問題,就是如果業務變更了,那麼介面變更,這時候前端和後端人員都需要重新修改位元組的程式碼和業務邏輯,之前的主要問題如下:

  • 1. 前後端需要進行各自的開發, 並以json介面對接
後端用自己的業務實現業務邏輯和json資料的拼接,前端接收到json資料,完成資料到介面的轉換,成本很大
  • 2. SEO問題
非同步載入的SEO優化問題,沒有服務端渲染,蜘蛛抓取不到資料,無SEO可言

其實理由很簡單,就是為了減少開發成本,並增加整體專案的可維護性, 而且通過使用該技術可以有效減少網頁載入速度,並提供優良的SEO優化能力,還能夠利用Nodejs的高併發能力的特性,讓Nodejs處理它最擅長的方面,從而增加整體架構的負載能力,節約硬體成本,提升專案的的負載能力

一. Nodejs的環境安裝和配置

構建一個這樣的框架 肯定用的是NodeJS環境, 畢竟無論是後端伺服器, 程式碼打包優化等工作,都是由Nodejs負責製作的

怎麼安裝?很簡單~ ~ 官方地址直接下載 Nodejs官網

Window: 直接下載官方安裝包安裝即可,請下載最新版本,這樣可以支援新的一些特性,例如async和await等,之後會用到

Mac: 不建議用安裝包安裝 一個是升級不方便,切換版本也不方便,而且解除安裝非常麻煩,mac使用brew安裝或者nvm來安裝,攻略大家自己搜尋吧

二.webpack及babel環境工具的搭建

當完成了Nodejs環境, 我們會遇到一個大坑, 就是需要一些自動化工具的使用, 主要是webpack和babel,webpack我們使用2.0版本,也是最近釋出的

Webpack 是當下最熱門的前端資源模組化管理和打包工具。它可以將許多鬆散的模組按照依賴和規則打包成符合生產環境部署的前端資源。還可以將按需載入的模組進行程式碼分隔,等到實際需要的時候再非同步載入。通過 loader 的轉換,任何形式的資源都可以視作模組,比如 CommonJs 模組、 AMD 模組、 ES6 模組、CSS、圖片、 JSON、Coffeescript、 LESS 等。

可以看到官方介紹,更多是將該工具定義為一個模組化管理和打包工具,也正是這樣的,它在我們前端工作中負責的就是自動打包的功能,它能幫助我們自動合併打包js,刪除重複的js程式碼,自動處理一些樣式檔案等工作,等於是一個自動化棧,完成各種之前需要手動操作的工作

Babel是一個轉換編譯器,它能將ES6轉換成可以在瀏覽器中執行的程式碼。Babel由來自澳大利亞的開發者Sebastian McKenzie建立。他的目標是使Babel可以處理ES6的所有新語法,併為它內建了React JSX擴充套件及Flow型別註解支援。

在當下瀏覽器標準尚未統一,對ES6和ES7支援性未到時候 我們需要babel自動將我們所使用的ES6,7的新特性進行轉換,並變成我們瀏覽器都相容的ES5語法,並可以讓你的程式碼更規範和整齊.

我當時使用這2個工具時候,webpack覺得配置很麻煩,還要一堆loader(載入器),各種配置,覺得非常麻煩,但是適應了以後就覺得非常簡單了

如何配置webpack2的配置和怎麼讓環境支援熱載入

這部分由於是客戶端環境的工具配置, 不會講解的特別細, 大家可以去官方中文網進行閱讀和學習,但是會將一些遇到的坑,和如何配置,我們來看下webpack2的配置都是幹什麼的,當前環境的配置 Webpack配置檔案

為什麼要2個配置檔案?devServer.js是什麼?

開發環境配置檔案(webpack.config.dev.js & devServer.js)

嗯很簡單, 一個配置檔案(webpack.config.dev.js)是用來開發環境用的, 它支援一些熱載入熱替換功能, 不需要我們在刷洗頁面就可以看到隨時修改的變化, 並且會支援source map的支援,方便我們除錯頁面和指令碼. 自然需要實現這些需要我們搭配一個伺服器一起執行

我們看下程式碼片段:

	//載入webpack模組
    webpack = require('webpack'),
    //載入自動化HTML自動化編譯外掛
    HtmlWebpackPlugin = require('html-webpack-plugin'),
    autoprefixer = require('autoprefixer'),
    precss = require('precss'),
    postcsseasysprites = require('postcss-easysprites'),
    //載入公用元件外掛
    CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin

頭部這些主要是一些需要使用到的外掛元件, 註釋也寫得很清楚了, 引用了這些外掛, 我們才能實現對應的功能 我一個一個解釋下吧

webpack = require('webpack'),

這個不說了

HtmlWebpackPlugin = require('html-webpack-plugin'),

當引用這個元件時,我們就可以完成自動將模板轉化為HTML頁面並將頁面所使用的css經過webpack打包後的連結自動載入在頁面原始碼中,是不是很方便,我們看下配置

new HtmlWebpackPlugin({
            template: 'src/index.html',
			//頁面模板的地址, 支援一些特殊的模板, 比如jade, ejs, handlebar等
            inject: true,
			//檔案插入的位置, 可以選擇在 body 還是 head 中
            hash: true,
			//是否給頁面的資原始檔後面增加hash,防止讀取快取
            minify: {
                removeComments: true,
                collapseWhitespace: false
            },
			//精簡優化功能 去掉換行之類的
            chunks: ['index','vendor','manifest'],
			//檔案中插入的 entry 名稱,注意必須在 entry 中有對應的申明,或者是使用 CommonsChunkPlugin 提取出來的 chunk. 簡單理解即頁面需要讀取的js檔案模組
            filename: 'index.html'
			//最終生成的 html 檔名稱,其中可以帶上路徑名
}),
 CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin

當webpack打包時,如果不進行分包工作, 他會打包成一個js檔案,名字就是入口你給的名字,比如:

entry: {
        index:  './src/index.js'
		}

如果不使用該元件, 打包完成生成的就只有一個index,js檔案,所以我們還是為了將一些公用的包提取出來, 就需要記性分支打包,這樣做為什麼? 還是為了利用瀏覽器快取, 也可以在專案新部署時, 完成只對更新的包進行替換, 而公用那部分不進行替換, 這樣使用者就不需要再下載公用的js, 從減小伺服器或者CDN壓力, 對吧 省錢~ 伺服器不要錢啊, CDN不收費啊?

怎麼用咧? 我們不說直接上程式碼

入口配置

entry: {
        index:
          './src/index.js',
        vendor: [
            'react',
            'react-dom',
            'redux',
            'react-redux',
            'react-router',
            'axios'
        ]
    }

我們可以看到vendor模組將所有用的一些公用模組寫在了這裡, 為了就是讓這些公共模組方便之後的外掛配置,讓它們單獨打包, index模組則是我們單頁面應用時所用的指令碼,都是我們自己寫得指令碼啦~

模組配置js

new webpack.optimize.CommonsChunkPlugin({
            names: [
                'vendor', 'manifest'//需要分包的對應的名字
            ],
            filename: jsDir+'[name].js' //配置輸出結構,這裡配置的是按路徑和模組名進行生成
        }),

這裡為什麼多了個manifest? 這個是個啥東西, 說簡單點, 就是webpack2 用來儲存一些關係啦, 連結啦之類的東西, 如果不提取這個模組, 每次打包之後vendor 都會有變化, 就失去了我們替換資源時不替換vendor包的意義了, 對吧~ ~ 所以每次專案更新下,只需要替換index.js和mainifest.js就可以了, 很黑科技吧~ 哈哈 go on go on

    autoprefixer = require('autoprefixer'),
	//自動加瀏覽器相容方案, 主要是css3的相容方案
    precss = require('precss'),
	//可以讓postCSS支援一些SASS的語法特性
    postcsseasysprites = require('postcss-easysprites'),
	//支援前端CSS精靈的功能 即背景圖自動拼接和合成為一張圖片, 減少請求

這幾個外掛其實都是postCss的外掛, PostCSS和LESS, SASS都是CSS預載入器, 主要是為了讓我們更加快捷和簡單的編寫CSS 並讓CSS支援一些程式設計的特性, 例如迴圈, 變數等功能 這裡我們構建選擇了postCSS, 原因很簡單, 1.非常快 2. 外掛可以支援Sass和Less的功能

我們看看webpack是如何處理檔案的, webpack採用的是**loader(載入器)**來處理, 用各種loader進行檔案的細化處理和特性的執行,看下程式碼:

module: {
        //載入器配置
        rules: [
            {
                test: /\.css$/,

                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true,
                            camelCase: true,
                            localIdentName: "[name]_[local]_[hash:base64:3]",
                            importLoaders: 1,
                            sourceMap: true
                        }
                    }, {
                        loader: "postcss-loader",
                        options: {
                            sourceMap: true,
                            plugins: () => [
                                precss(),
                                autoprefixer({
                                    browsers: ['last 3 version', 'ie >= 10']
                                }),
                                postcsseasysprites({imagePath: '../img', spritePath: './assets/dist/img'})
                            ]
                        }
                    }
                ]
            }, {
                test: /\.css$/,
                exclude: [path.resolve(srcDir, cssDir)],
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            importLoaders: 1,
                            sourceMap: true
                        }
                    }, {
                        loader: "postcss-loader",
                        options: {
                            sourceMap: true,
                            plugins: () => [
                                precss(),
                                autoprefixer({
                                    browsers: ['last 3 version', 'ie >= 10']
                                }),
                                postcsseasysprites({imagePath: '../img', spritePath: './assets/dist/img'})
                            ]
                        }
                    }
                ]

            }, {
                test: /\.js$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: "babel-loader",
                        options: {
                            presets: ['react-hmre']
                        }
                    }
                ]
            }, {
                test: /\.(png|jpeg|jpg|gif|svg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            name: 'dist/img/[name].[ext]'
                        }
                    }
                ]
            }
        ]
    },

非常長 我們拆分來看:

CSS的處理, 具體格式不說了, 直說都是幹什麼的, 為什麼這麼做

{
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader" //用來處理最基礎的css樣式
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true, //是否支援css-modules
                            camelCase: true,//是否支援 -(中缸線)寫法的class,id名稱
                            localIdentName: "[name]_[local]_[hash:base64:3]",//css-modules的生成格式
                            importLoaders: 1, // 是否支援css import方法
                            sourceMap: true //是否生成css的sourceMap, 主要用來方便除錯
                        }
                    }, {
                        loader: "postcss-loader", //postCSS載入模組,可以使用postCSS的外掛模組
                        options: {
                            sourceMap: true,
                            plugins: () => [
                                precss(), //支援Sass的一些特性
                                autoprefixer({
                                    browsers: ['last 3 version', 'ie >= 10']
                                }),//CSS3 自動化相容方案
                                postcsseasysprites({imagePath: '../img', spritePath: './assets/dist/img'}) //支援css精靈功能
                            ]
                        }
                    }
                ]
            }, {
                test: /\.css$/,
                exclude: [path.resolve(srcDir, cssDir)],
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            importLoaders: 1,
                            sourceMap: true
                        }
                    }, {
                        loader: "postcss-loader",
                        options: {
                            sourceMap: true,
                            plugins: () => [
                                precss(),
                                autoprefixer({
                                    browsers: ['last 3 version', 'ie >= 10']
                                }),
                                postcsseasysprites({imagePath: '../img', spritePath: './assets/dist/img'})
                            ]
                        }
                    }
                ]

            },

看完程式碼, 我們主要說下css-modules, 引用它的主要原因是為了讓樣式可以自動加上標識和hash, 這樣就可以做到讓樣式永遠不會衝突的功能了, 這樣做的好處顯而易見, 就是可以讓團隊一起開發時, 不在糾結樣式名衝突的問題, 而且也可以通過使用css-modules減少樣式的層疊, 減少父級的引用, 這樣的低層級有利於樣式的複用和利用, 讓樣式更加通用和增強複用性.

為什麼這裡寫了2個css loader模組, 原因很簡單, 因為為了防止其他外掛,模組的樣式被增加css-modules的變化, 所以需要加另一個loader讓其他不在指定資料夾中的css樣式不在受到css-modules的影響, 所以多加了一句 exclude: [path.resolve(srcDir, cssDir)], 刪掉了對應css-modules的配置部分, 詳細的見上面的程式碼.

我們再看看輸出的配置

output: {
        path: assetsDir,//path代表js檔案輸出的路徑
        filename: jsDir + '[name].js', //用來配置輸出檔名格式
        publicPath: '/' //公共路徑, 用來配置所有資源前面增加的路徑,之後在生成目錄會講解該路徑的具體用途
    },

最後我們看下開發工具, 通過使用該工具,可以自動載入source-map,方便我們的除錯開發, 畢竟壓縮過的程式碼是無法進行除錯的, 而source-map可以還原之前程式碼並指向位置, 這樣方便我們操作

  devtool: 'source-map',

因為是開發環境, 所以我們需要一個重要的功能, 就是react的熱載入, 什麼是熱載入呢? 就是我們在開發中可以不重新整理頁面就可以完成頁面的變化, 包括樣式,react指令碼的變化, 還有對應redux的狀態控制變化等, 這裡我們使用的是webpack-dev-serverreact-hot-loader3, 通過它們的使用, 就可以完成頁面的熱載入和替換功能. 我們看下配置方法:

建立一個devServer.js, 用來執行伺服器的執行和具體配置, 並附加上react-hot-loader3外掛, code如下:

//載入Node的Path模組
const path = require('path');
//載入webpack模組
const webpack = require('webpack');
// const express = require('express');
const WebpackDevServer = require('webpack-dev-server');
//載入webpack配置檔案
const config = require('./webpack.config.dev');

//配置及初始化Koa伺服器
var creatServer = () => {
    //初始化webpack應用
    let compiler = webpack(config);
    //呼叫webpack熱載入模組及對應引數
    let app = new WebpackDevServer(webpack(config), {
        publicPath: config.output.publicPath, //檔案的輸出路徑,由於是都是在記憶體中執行的, 所以是看不到具體的檔案的
        hot: true, //是否開啟熱載入功能
        historyApiFallback: true,//是否記錄瀏覽器歷史,配合react-router使用
        stats: {
            colors: true // 用顏色標識
        }
    });
    //呼叫開啟5000埠用來測試和開發
    app.listen(5000, function(err) {
        if (err) {
            console.log(err);
        }
        console.log('Listening at localhost:5000');
    });
};

//呼叫建立koa伺服器方法
creatServer();

配置文件含有註釋, 不在詳細介紹, 只說下webpack-dev-server的功能, 這個伺服器等於一個微型的express或者koa框架, 使用它可以使用nodejs完成一個簡單的本地伺服器, 並支援熱替換功能, 主要是檢測webpack打包過程和讓程式支援熱載入, 但是應用了這個外掛並不會完成所有熱載入效果, 比如我們在使用redux時, 就會出問題, 因為這個熱替換並不能保留state(狀態), 所以使用時, 每次儲存, react元件的狀態就不會保留, 所以需要引入另一個外掛react-hot-loader來解決這個問題, 我們看下如何使用這個外掛, 外掛的使用方法很多, 我選擇了一個最簡單的方法來實現,見code

第一步: 在入口檔案哪裡加上最上面3句話

entry: {
    index: [
      'react-hot-loader/patch',
      'webpack-dev-server/client?http://0.0.0.0:5000',
      'webpack/hot/only-dev-server',
      './src/index.js'
    ]
}

第二部: 增加webpack中的熱更新外掛

new webpack.HotModuleReplacementPlugin(),

第三部: 在babel中增加對應的熱載入模組

我們需要在根目錄中增加一個檔案.babelrc,用來配置babel的配置

我們只需要增加一個熱載入外掛

{
    "plugins": [ "react-hot-loader/babel" ]
}

那麼我們之後看下, Babel的配置

{
    "presets": ["react", "es2015", "stage-0", "stage-1", "stage-2", "stage-3"],
    "plugins": ["transform-class-properties", "transform-es2015-modules-commonjs", "transform-runtime","react-hot-loader/babel"]
}

我們在Babel中使用了很多的轉換器和外掛, 安裝也很簡單,我們使用的包有以下這些,具體功能不在闡述了, 大家自己Search吧~

"babel-cli": "^6.23.0",
"babel-core": "^6.6.5",
"babel-eslint": "^6.1.0",
"babel-loader": "^6.2.4",
"babel-plugin-transform-class-properties": "^6.11.5",
"babel-plugin-transform-es2015-modules-commonjs": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.23.0",
"babel-plugin-transform-require-ignore": "^0.0.2",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-0": "^6.22.0",
"babel-preset-stage-1": "^6.22.0",
"babel-preset-stage-2": "^6.13.0",
"babel-preset-stage-3": "^6.22.0",
"babel-register": "^6.23.0",
"babel-runtime": "^6.23.0",

最後我們看下打包生成的webpack配置檔案

ExtractTextPlugin = require('extract-text-webpack-plugin'),

webpack在打包程式碼時,可以看到樣式直接生成在頁面的, 所以我們如果想讓這些樣式單獨為一個檔案引用時, 就需要用這個的外掛, 當使用這個外掛的時候, 就可以讓頁面以link模式引用css了, 在一些比較大的樣式時 還是讓css樣式儲存在瀏覽器cache裡面比較能減輕伺服器資料吞吐壓力,配置如下:

new ExtractTextPlugin('dist/css/style.css'),

這裡我們將所有樣式壓縮為一個style.css檔案,當然,也可以實現分開打包

new ExtractTextPlugin(cssDir + '[name].css'),
    //載入JS模組壓縮編譯外掛
    UglifyJsPlugin = webpack.optimize.UglifyJsPlugin,

載入壓縮模組, 可以將js壓縮為最精簡的程式碼, 大幅度減小生成的檔案大小, 配置如下:

new UglifyJsPlugin({
    // 最緊湊的輸出
    beautify: false,
    // 刪除所有的註釋
    comments: false,
    compress: {
      // 在UglifyJs刪除沒有用到的程式碼時不輸出警告  
      warnings: false,
      // 刪除所有的 `console` 語句
      // 還可以相容ie瀏覽器
      drop_console: true,
      // 內嵌定義了但是隻用到一次的變數
      collapse_vars: true,
      // 提取出出現多次但是沒有定義成變數去引用的靜態值
      reduce_vars: true,
    }
})

OK, 我們完成了webpack和Babel的配置, 就可以開始開發了, 這部分主要還是資料的稀缺,現在有了中文官方站好一些, 之前很多配置並不是很找, 看了後希望大家能夠明白這些配置是幹什麼的而不只是按照別人的配置完成即可.

三.react的引用

react作為實現的核心框架,主要的黑科技也是靠它給出的一些方法來實現的,我們先看下react的生命週期

ReactJS的生命週期

IMG

ReactJS的生命週期可以分為三個階段來看:例項化、存在期、銷燬期

例項化

首次例項化

  • getDefaultProps
  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

例項化之後更新,這一過程和上面一樣,但沒有getDefaultProps這個過程 簡單記憶:props => state => mount => render => mounted

存在期

元件已經存在,狀態發生改變時

  • componetWillReceiveProps
  • shouldComponentUpdate
  • ComponentWillUpdate
  • render
  • componentDidUpdate

簡單記憶:receiveProps => shouldUpdate => update => render => updated

銷燬期

componentWillUnmount

生命週期中10個API的作用說明

  • getDefaultProps 作用於元件類,只調用一次,返回物件用於設定預設的props,對於引用值,會在例項中共享

  • getInitialState 作用於元件例項,在例項建立時呼叫一次,用於初始化每個例項的state,此時可以訪問this.props

  • componentWillMount 在完成首次渲染之前呼叫,此時可以修改元件的state

  • render 必選方法,建立虛擬DOM,該方法具有特殊規則:

只能通過this.props 和this.state訪問資料
可以返回nullfalse或任何React元件
只能出現一個頂級元件,陣列不可以
不能改變元件的狀態
不能修改DOM
  • componentDidMount 真實的DOM被渲染出來後呼叫,可以在此方法中通過 this.getDOMNode()訪問真實的DOM元素。此時可以使用其它類庫操作DOM。服務端不會被呼叫

  • componetWillReceiveProps 元件在接收到新的props時呼叫,並將其作為引數nextProps使用,此時可以更改元件的props及state

  • shouldComponentUpdate 元件是否應當渲染新的props或state,返回false表示跳過後續的生命週期方法,通常不需要使用以避免出現bug。在出現應用效能瓶頸時,是一個可以優化的點。

  • componetWillUpdate 接收新props或state後,進行渲染之前呼叫,此時不允許更新props或state

  • componetDidUpdate 完成渲染新的props或state之後呼叫 ,此時可以訪問DOM元素。

  • componetWillUnmount 元件被移除之前呼叫,可以用於做一些清理工作,在componentDidMount方法中新增的所有任務都需要在該方法中撤銷,比如建立的定時器或新增的事件監聽器。

var React = require("react");
var ReactDOM = require("react-dom");

var NewView = React.createClass({
    //1.建立階段
    getDefaultProps:function() {
        console.log("getDefaultProps");
        return {};
    },
    //2.例項化階段
    getInitialState:
            
           

相關推薦

架構 react 伺服器渲染框架

一個能夠支援前後端分離並支援中間層同構的完整框架,或許現在它還不夠完善,但是我會把構建該框架中遇到的問題都列出來,以方便其他人遇到問題不在需要去到處搜尋問題,希望為自己搭建框架的人有一些幫助,文件也會不斷更新和優化,你可以watch專案隨時看到文件的更新,也希望最後成為一個完整而又完美的框架,如果這些問題

React 伺服器渲染原理解析與實踐(同步更新)

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端 第2章 React中的伺服器端渲染本章將藉助Node.js

2018最新React 伺服器渲染原理解析與實踐

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器端渲染本章將藉助Nod

React 伺服器渲染原理解析與實踐目前最全

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器端渲染本章將藉助Nod

React 伺服器渲染原理解析與實踐》雲盤下載

第1章 伺服器端渲染基礎 本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學 1-2 什麼是伺服器端渲染 1-3 什麼是客戶端渲染 1-4 React 客戶端渲染的優勢與弊端 第2章 Re

React 伺服器渲染原理解析與實踐目全最新

第1章 伺服器端渲染基礎 本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學 1-2 什麼是伺服器端渲染 1-3 什麼是客戶端渲染 1-4 React 客戶端渲染的優勢與弊端 第2章 Re

React 伺服器渲染原理解析與實踐(資源連結)

第1章 伺服器端渲染基礎 本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學 1-2 什麼是伺服器端渲染 1-3 什麼是客戶端渲染 1-4 React 客戶端渲染的優勢與弊端 第2章 Re

某課最新《React 伺服器渲染原理解析與實踐》資源

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器

React 伺服器渲染原理解析與實踐

第4章 在SSR框架中引入路由機制 本章將給大家講解如何在當前的SSR框架中引入React-Router,從而使得我們的伺服器端渲染框架能夠支援路由跳轉,SSR的路由跳轉比前端路由或後端路由都要複雜一些,這張我們將細緻的講解整個SSR路由的執行流程。 4-1 伺服器端渲染中的路由 4-2 多頁

React 伺服器渲染原理解析與實踐資源

第1章 伺服器端渲染基礎 本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學 1-2 什麼是伺服器端渲染 1-3 什麼是客戶端渲染 1-4 React 客戶端渲染的優勢與弊端 第2章 React中

React 伺服器渲染原理解析與實踐(完整版)

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器

React 伺服器渲染原理解析與實踐分享

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器

React 伺服器渲染原理解析與實踐(目前最全)

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器

某課React 伺服器渲染原理解析與實踐(9章全)

第1章 伺服器端渲染基礎 本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。 1-1 課程導學 1-2 什麼是伺服器端渲染 1-3 什麼是客戶端渲染 1-4 React 客戶端渲染的優勢與弊端 第2章 React中的伺服器端渲染 本

React 伺服器渲染原理解析與實踐(最新最全)

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器端渲染本章將藉助Nod

React 伺服器渲染原理解析與實踐(已完結)2018(最全)

之前我的認知是,這是一個generator的語法糖,是用來解決非同步問題的,看起來寫起來是同步程式碼,但實際執行還是非同步的,感覺和他說的有點偏差,有偏差就說明至少有個人錯了;於是我打算重新認識一遍這個東西,說不定會有新收穫。 TALK IS CHEAP, SHOW YOU THE CODE.

淺談React前後端防止重複渲染

什麼叫前後端同構? 為了解決某些問題(比如SEO、提升渲染速度等)react 提供了2個方法在服務端生成一個HTML文字格式的字串。在得到了這個HTML格式的字串之後,通常會將其組裝成一個頁面直接返回給使用者的瀏覽器。 到這裡,服務端的活已經幹完了,然後就是瀏覽器這邊幹活

mysql 架構篇系列 2 復制架構從搭建(異復制)

stat 如果 rep 目的 end com version none 3.6 一. 環境準備   1.1 主庫環境(172.168.18.201) 環境 說明 查看腳本 操作系統版本 CentOS Linux release 7.4.1708

spring-boot react實現增刪改查 元件化

在 spring-boot react一步一步實現增刪改查 中,用一個元件實現了表格和表單功能,所以現在需要將其拆分成元件獨立出來 拆分表格 建立Table.js import React, {Component} from 'react' class Tab

spring-boot react實現增刪改查

maven繼承spring-boot <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-paren