React學習(四)----- 基於React腳手架的React應用
阿新 • • 發佈:2021-09-07
1、React腳手架
- 什麼是腳手架???
用來幫助程式設計師快速建立一個基於React庫的模板專案
1) 包含了所有需要的配置(語法檢查、jsx編譯、devServer…)
2) 下載好了所有相關的依賴
3) 可以直接執行一個簡單效果
4)專案的整體技術架構為: react + webpack + es6 + eslint
5)使用腳手架開發專案的特點: 模組化, 元件化, 工程化
- 腳手架的安裝
cnpm install create-react-app -g
- 建立專案
1、建立專案 create-react-app hello-react
- React腳手架專案結構
- public ----- 靜態資原始檔夾
- favicon.ico ----- 網站頁籤圖示
- index.html ----- 主頁面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <!-- %PUBLIC_URL%代表public資料夾的路徑 相當於./favicon.ico --> <
- robots.txt ----- 爬蟲協議檔案
- src ----- 原始碼資料夾
- App.css ----- App元件的樣式
- App.js ----- App元件
- App.test.js ----- 用於給App做測試
- index.css ----- 樣式
- index.js ----- 入口檔案:React.StrictMode用於檢查App和App的子元件的寫法是否合理
- logo.svg ----- logo圖
- reportWebVitals.js ----- 頁面效能分析檔案(需要web-vitals庫的支援)
- setupTests.js ----- 元件單元測試的檔案(主要jest-dom庫的支援)
- public ----- 靜態資原始檔夾
2、一個簡單的Hello元件
- vscode中react外掛的安裝
ES7 React/Redux/GraphQL/React-Native snippets
- 樣式的模組化
- 元件的檔案目錄
-
- 將元件的css檔案命名為:index.module.css,在元件jsx中的引入方式為用一個變數接收,並且定義的時候使用差值表示式的方式定義,這樣不會造成樣式汙染;
import { Component } from "react"; import hello from './index.module.css' export default class Hello extends Component { render() { return <h1 className={hello.title}>Hello,React!!!!</h1>; } }
不然結果就是:同名的class標籤只會使用後引入的css檔案
- 將元件的css檔案命名為:index.module.css,在元件jsx中的引入方式為用一個變數接收,並且定義的時候使用差值表示式的方式定義,這樣不會造成樣式汙染;
- 功能介面的元件化編碼流程
1. 拆分元件: 拆分介面,抽取元件 2. 實現靜態元件: 使用元件實現靜態頁面效果 3. 實現動態元件 3.1 動態顯示初始化資料 3.1.1 資料型別 3.1.2 資料名稱 3.1.3 儲存在哪個元件? 3.2 互動(從繫結事件監聽開始)
3、元件的組合使用(TodoList)
- 效果圖
- 知識點
- 步驟
-
- 生成唯一的id值得庫
cnpm i uuid/nanoid -D//uuid庫比較大,建議選擇nanoid
- 非父子元件之間的傳值
1、子傳父、父傳子 即Header傳給App,App傳給List (1)子傳父 子元件在父元件當做標籤使用 1) 子元件this.props.sendData(event.target.value) 2) 父元件中的子元件繫結資料 <Header sendData={this.receiveData} /> 3) 父元件中的方法 receiveData = (data) => { console.log(data); }; (2)父傳子 子元件在父元件當做標籤使用 1) 父元件中的子元件繫結資料 <Header {...this.state}} /> 2) 在子元件的render方法中使用this.props進行接收
- checkbox的相關問題
1、checked屬性必須與onChange事件一起使用; 2、defaultChecked屬性只有第一次會生效,後效修改將無效;
- 生成唯一的id值得庫
4、React Ajax
- 為什麼要引入Ajax???
1.React本身只關注於介面, 並不包含傳送ajax請求的程式碼 2.前端應用需要通過ajax請求與後臺進行互動(json資料) 3.react應用中需要整合第三方ajax庫(或自己封裝)
- 常用的Ajax請求庫
1.jQuery: 比較重, 直接操作DOM,會有回撥函式地域的問題,如果需要另外引入不建議使用 2.axios: 輕量級, 建議使用 1)封裝XmlHttpRequest物件的ajax 2)promise風格 3)可以用在瀏覽器端和node伺服器端
- 腳手架配置代理(客戶端解決,伺服器的話使用cors)
- 跨域原因
http://localhost:3000 -----> http://localhost:5000/students 原因:由於Ajax引擎的限制,請求可以從3000傳送到5000埠,但是響應的時候被引擎攔截,這個時候我們可以配置代理 (設定一箇中間人伺服器,也在3000埠執行,而中間伺服器沒有ajax引擎的影響,且伺服器之間無同源策略的影響,可以正常接收響應,接收到響應資料後,由於埠都是
3000,客戶端直接收到資料)
本地3000埠執行這一個腳手架,一個伺服器,name腳手架和伺服器由於協議、域名、埠號完全一致,所以不會產生跨域,而本地代理的伺服器與訪問伺服器之間不受同源策略的影響
因此也可以正常的接收到資料,代理伺服器收到資料後再返回給客戶端,因此解決跨域問題!!! - 第一種方式:代理一個伺服器的情況下,多個不允許這麼配置
- 步驟
1、修改package.json "proxy": "http://localhost:5000" 2、重啟 npm start 3、修改請求介面 http://localhost:5000/students -----> http://localhost:3000/students
- 說明
1. 優點:配置簡單,前端請求資源時可以不加任何字首。 2. 缺點:不能配置多個代理。 3. 工作方式:上述方式配置代理,當請求了3000不存在的資源時,那麼該請求會轉發給5000 (優先匹配前端資源)
- 步驟
- 第二種方式:代理多個伺服器
- 步驟
1. 第一步:建立代理配置檔案 在src下建立配置檔案:src/setupProxy.js 2. 編寫setupProxy.js配置具體代理規則: // 使用commonjs的語法,引入一個內建外掛 無需安裝 const proxy = require('http-proxy-middleware') module.exports = function(app) { app.use( proxy('/api1', { //api1是需要轉發的請求(所有帶有/api1字首的請求都會轉發給5000) target: 'http://localhost:5000', //配置轉發目標地址(能返回資料的伺服器地址) changeOrigin: true, //控制伺服器接收到的請求頭中host欄位的值 /* changeOrigin設定為true時,伺服器收到的請求頭中的host為:localhost:5000 changeOrigin設定為false時,伺服器收到的請求頭中的host為:localhost:3000 changeOrigin預設值為false,但我們一般將changeOrigin值設為true */ pathRewrite: {'^/api1': ''} //去除請求字首,保證交給後臺伺服器的是正常請求地址(必須配置) 重寫請求路徑 }), proxy('/api2', { target: 'http://localhost:5001', changeOrigin: true, pathRewrite: {'^/api2': ''} }) ) }
- 說明
1. 優點:可以配置多個代理,可以靈活的控制請求是否走代理。 2. 缺點:配置繁瑣,前端請求資源時必須加字首。
- 步驟
- 跨域原因
- github搜尋案例
- 效果圖
-
- 知識點
- 連續解構賦值
const obj = {a:{b:{c:1}}} console.log(obj.a.b.c) //1 const { a: { b: { c } } } = obj console.log(c) //1
- 連續解構賦值
- 知識點
5、釋出-訂閱機制(適用於任意元件的通訊)
- 安裝
cnpm i pubsub-js -S
- 使用:Search元件傳遞給-----List元件(兄弟元件之間的傳值)
- List元件訂閱訊息
import PubSub from 'pubsub-js' componentDidMount(){ // 訂閱訊息 this.token = PubSub.subscribe("updateAppState",(msg,data)=>{ console.log("list") console.log(msg,data)//msg是updateAppState,即事件的名稱,data是釋出的訊息 this.setState(data) }) } //取消訂閱 componentWillUnmount(){ PubSub.unsubscribe(this.token) }
- Search元件釋出訊息
import PubSub from 'pubsub-js' PubSub.publish('updateAppState',{ isFirst: false,isLoading:true })
- List元件訂閱訊息
6、前後端互動的方式
- jquery/axios
- 特點
axios是一個基於Promise,用於瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特徵: 1)從瀏覽器中建立 XMLHttpRequest 2)從 node.js 發出 http 請求 3)支援 Promise API 4)攔截請求和響應 5)轉換請求和響應資料 6)自動轉換JSON資料, 7)客戶端支援防止CSRF/XSRF
- 示例
import axios from 'axios' axios.get(`http://localhost:3000/api/search/users?q=${inputValue}`).then((res) => { // 請求成功後通知App更新狀態 updateAppState({isLoading:false,users:res.data.items}) }).catch(err => { updateAppState({isLoading:false,err:err.message}) })
- 特點
- fetch ----- 無需安裝,瀏覽器內建
- 特點
fetch:返回的是一個未處理的方法集合,我們可以通過這些方法得到我們想要的資料型別。如果我們想要json格式,就執行res.json(),如果我們想要字串就res.text() 1)關注分離,沒有將輸入、輸出和用事件來跟蹤的狀態混雜在一個物件裡 2)更加底層,提供的API豐富(request, response) 3)脫離了XHR,是ES規範裡新的實現方式 4)fetch只對網路請求報錯,對400,500都當做成功的請求,需要封裝去處理 5)fetch預設不會帶cookie,需要新增配置項 6)fetch不支援abort,不支援超時控制,使用setTimeout及Promise.reject的實現的超時控制並不能阻止請求過程繼續在後臺執行,造成了量的浪費 7)fetch沒有辦法原生監測請求的進度,而XHR可以
- 示例
fetch(`http://localhost:3000/api/search/users?q=${inputValue}`) .then( (res) => { console.log('聯絡伺服器成功了', res)//是一個綜合各種方法的物件,並不是請求的資料 return res.json() }, (error) => { console.log('聯絡伺服器失敗了', error) return new Promise(()=>{})//為了防止斷網走了上一行後,接著走下一個then中的第一個回撥,加上只走上面一行 }) .then( (res) => { console.log("獲取資料成功了",res) }, (error) => { console.log('獲取資料失敗了',error) })
- 簡化程式碼後
fetch(`http://localhost:3000/api/search/users?q=${inputValue}`) .then( (res) => { console.log('聯絡伺服器成功了', res)//是一個綜合各種方法的物件,並不是請求的資料 return res.json() } ) .then( (res) => { console.log("獲取資料成功了",res) } ).catch( (error) => { console.log('請求出錯',error) } )
- 使用async和await
try { let response = await fetch(`http://localhost:3000/api/search/users?q=${inputValue}`) let result = await response.json(); console.log(result) } catch (e) { console.log(e) }
- 特點
7、其他問題
暫無
北梔女孩兒