本文中涉及到的技術包括:node.js/express服務器的搭建、fetch發送數據請求。
在之前的幾篇文章中,介紹了如何搭建基礎的React項目,以及一些簡單知識,現在,我們還需要掌握如何用React來向后台服務器發起HTTP請求,來獲取數據。因為一個網站光有靜態的頁面是不夠的,只能稱其為靜態網站,我們需要獲取到數據才能讓網頁呈現更為豐富的內容。
現在的網站開發一般都采用前后端分離的開發方式。前端人員負責前端頁面的實現,后端人員負責提供數據,前端頁面將通過訪問api接口的方式來鏈接后台,獲取相應的數據,如下圖所示:
目前很流行的方式是通過JQuery中的 AJAX 方法來獲取數據,引入JQuery后使用 $.ajax() 去訪問特定的url地址,通過GET、POST等方式進行數據通信。本文中采用的方式是通過 Fetch 方法來進行數據通信,同樣可以向后台服務器發起GET、POST等請求。各位也可以直接使用原生的 XMLHttpRequest 方法來實現。
我們現在有了請求數據的方法,那么我們請求的對象在哪里呢,就需要我們親自動手來搭建后台服務器了。用於構建后台服務器的技術有許多, .NET、JAVA、PHP都是不錯的選擇。本文我們將在 node.js 平台中使用 express 框架來搭建本地服務器。為什么選擇node.js呢,因為我們的React項目是就跑在node.js環境中的,各位在搭建React項目的同時對node.js應該已經有所熟悉,我們也不用特地去學習一門后台開發語言(當然,如果你已經掌握了其他的后台開發技術,也可以用自己熟悉的方式來搭建后台服務器,只需要向我們的React項目提供api接口)
下面,我們就來搭建后台服務器,大家可以參照如下鏈接中的教程,其中講得很詳細:
http://www.runoob.com/nodejs/nodejs-express-framework.html
現在我們來開始搭建 node.js 服務器,創建一個項目文件夾,在CMD命令行中輸入:
cnpm install express --save (cnpm需要另行安裝,用npm效果一樣,只是慢一點)
安裝完后我們來查看一下項目文件夾中的內容
express相關的依賴包已經被放在了 node_modules 文件夾下,package.json用於記錄已安裝的項目依賴包等信息。
下面來依次導入依賴包,搭建項目環境。
在CMD命令行中依次輸入:
cnpm install body-parser --save
cnpm install cookie-parser --save
cnpm install multer --save
查看一下package.json文件內容,我們可以看到這些依賴包的信息,json文件不能直接打開,大家可以使用各種文本編輯器,這里本人采用的是VScode,文件內容如下:
{ "dependencies": { "body-parser": "^1.18.2", "cookie-parser": "^1.4.3", "express": "^4.16.3", "multer": "^1.3.0" } }
那么,現在配置好了環境,接下來我們就要開始搭建服務了,創建一個名稱為:myserver.js 的文件,在其中輸入如下代碼
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('This is test message!'); }) var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("應用實例,訪問地址為 http://%s:%s", host, port) })
其中創建了一個對於GET請求的監聽接口,地址為“/”,由於我們是在本地搭建服務器,所以這個接口的完整地址就是 localhost:8081/ ,其中的8081就是服務器在本地環境中的訪問端口號。在res.send()函數中我們放入了一條字符串信息,內容為 'This is test message!' ,也就是api接口返回的信息。
保存這個文件並放在項目主目錄下,在CMD命令行中輸入如下指令:
node myserver.js
然后我們就成功啟動了服務器,端口號為8081,我們可以直接在瀏覽器中輸入 localhost:8081/ 來訪問,內容如下:
我們可以在瀏覽器中看到之前保存在 myserver.js 文件中的字符串。現在我們已經能夠從瀏覽器中看到api接口給出的數據,然后,可以試着在React項目中訪問api接口。
用VScode編輯器打開已經創建完成的React項目目錄
我們創建一個組件,內容如下:
import React from 'react'; class Page2 extends React.Component{ constructor(props){ //構造函數 super(props); this.state = { mytext : '', } } getData(){ //請求數據函數 fetch(`http://127.0.0.1:8081/`,{ method: 'GET' }).then(res => res.text()).then( data => { this.setState({mytext:data}) } ) } componentWillMount(){ this.getData(); } render(){ return(<div><div>{this.state.mytext}</div></div>); } } export default Page2;
下面來分析一下代碼,首先,在上方的“構造函數”constructor中,設置了State的初值,添加一個mytext屬性,初始值為空,其他內容是標准的構造語法,可以參照React官方資料。之后,我們創建一個getData() 函數,用於實現fetch方法獲取后台服務器的數據。
如上所示,fetch方法有兩個傳入的參數,一個是url,也就是后台api接口所在的地址,另一個是{method:'GET'},意思是采用GET方式與后台服務器進行通信。后面的 .then( ) 方法將上面傳回來的結果進行進一步的處理,將結果作為 res這個對象傳入,並使用 .text() 方法使其轉化為字符串類型,然后再下一個 .then( ) 方法中將上一步的返回值作為data 賦值給 state里的mytext。
(Fetch的詳細用法各位可以參照一下網上的資料,本文只是簡單使用,不做太多介紹)
現在我們有了獲取數據的函數,需要調用這個函數,這里要注意的是,我們不能直接在下方的render函數里調用getData( ),那樣會造成頁面死循環,由於React的特性,在render函數中,每當State被改變時就會重新渲染組件,getData( )函數中涉及到了對State的更改,所以React系統會重新去渲染頁面==>加載render函數==>重新調用getData( )==>重新渲染頁面==>一直死循環...
所以我們需要使用到React的生命周期函數,componentWillMount( ),將getData函數放置在其中,這個生命周期函數會在組件被渲染前調用,這個時候改變State就不會造成死循環。
(關於生命周期各位可以參照React官方文檔 https://doc.react-china.org/ )
然后,我們需要將State中的數據顯示出來,在render函數return的標簽中如上所示將 this.state.mytext 的內容顯示出來。
保存文件,用 npm start 啟動項目,輸入 localhost:3000 頁面將會呈現如下內容:
注意,這里會出現一個問題,無法實現跨域請求,也就是說,我們的React項目所在的 3000 端口與后台服務應用的 8081 端口不能進行通信,這是出於安全考慮,為了解決這一問題,可以在后台服務應用 myserver.js 中加入下面這段代碼:把rapp.get那替換掉就可以了 之后重啟一下 node myserver.js
app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By",' 3.2.1'); res.header("Content-Type", "application/json;charset=utf-8"); res.send("this is templace!!!") next(); });
這樣就可以讓React項目進行跨域請求,顯示數據。
現在,我們成功地從后台api中獲取並顯示字符串信息,那么其他類型的數據也可以這樣嗎?
下面我們來實現對json格式數據的獲取。
首先要對 node.js/express 服務應用進行改造,代碼如下:
var express = require('express'); var app = express(); app.all('/json', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By",' 3.2.1'); res.header("Content-Type", "application/json;charset=utf-8"); let myjson = { name : '盒裝牛奶', price : '3元', date : '2018年1月1日' } res.send(myjson); next(); }); var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("應用實例,訪問地址為 http://%s:%s", host, port) })
在代碼中,我們添加了一個get方法,地址為'/json',也就是 localhost:8081/json ,在方法中創建了一個json格式的數據對象 myjson,然后將其傳回。
ctrl+c 退出原來的服務,使用 node myserver.js 重新啟動服務后,我們用瀏覽器來訪問 localhost:8081/json ,內容如下:
我們成功地從后台服務器中獲取了json格式的數據,下面我們要在react項目中將其顯示出來,改造Page2組件,代碼如下:
import React from 'react'; class Page2 extends React.Component{ constructor(props){ //構造函數 super(props); this.state = { mytext : '', } } getData(){ //請求數據函數 fetch(`http://127.0.0.1:8081/json`,{ method: 'GET' }).then(res => res.json()).then( data => { this.setState({mytext:data}) } ) } componentWillMount(){ this.getData(); } render(){ return( <div> <div>{this.state.mytext.name}</div> <div>{this.state.mytext.price}</div> <div>{this.state.mytext.date}</div> </div> ); } }
export default Page2;
其中,fetch函數的url要改變為 localhost:8081/json ,在后面的.text( ) 方法要改為 .json( ),將數據轉換為json格式,在render函數的return里面創建3對<div>標簽,分別顯示mytext數據對象的name、price、date屬性,在頁面中我們可以看到:
上所示,我們儲存在后台服務器中的json數據被傳遞了過來,並由React應用渲染在了頁面上。
到此,本篇文章的內容就結束了,此次介紹了如何搭建 node.js/express 服務器,以及介紹了如何在React項目中使用Fetch獲取數據,存放在State中,並渲染出來。希望對各位有所幫助,也是對本人學習心得的記錄,感謝各位支持。后續還會有React相關文章更新。
記錄學習。看一遍不如自己實踐一次,勤動手,勤動腦,邁出第一步!
看后續文章的 可以點擊這個鏈接,https://blog.csdn.net/daxiazouyizou/article/details/80196815