?? Umi官方文檔地址
本篇文章主要介紹的一個 React小白
龟虎,從 0 使用umi
搭建React
項目的過程璃谨,記錄了相關(guān)umi
的使用以及react
的相關(guān)知識點~
目錄:
??持續(xù)更新中...??
1.在 config 文件內(nèi)配置 title 無效問題;
2.favicon頁面頭部小圖標(biāo)配置無效;
3.className 樣式選中高亮,或者多個 className 存在;
4.路由跳轉(zhuǎn)和參數(shù)接受;
5.useState 和 useEffect;
6.如何用 dva 定義一個 Model鲤妥,并修改佳吞;
7.權(quán)限路由(根據(jù)用戶登錄狀態(tài),跳轉(zhuǎn)登錄頁)棉安;
8.組件通信底扳;
9.函數(shù)式組件調(diào)用(forwardRef, useImperativeHandlede);
10.在React中顯示html模塊內(nèi)容
11.修改List列表中的某一個數(shù)值
12.request請求配置
13.受控組件空值警告解決
14.useState()異步問題處理
15.打包后修改輸出文件目錄 outputPath
16.如何使用sass
17.createElement 和 cloneElement的區(qū)別
18.路由按需加載贡耽,Loading
19.部署后頁面不顯示問題
?? 1.在 config 文件內(nèi)配置 title 無效問題
解決:如果你采用的是config方式衷模,那就把默認的 .umirc.ts 文件刪掉即可
?? 2.favicon頁面頭部小圖標(biāo)配置無效
解決:采用links引入,favicon適合引入對應(yīng)鏈接的圖標(biāo)
?? 3.className 樣式選中高亮菇爪,或者多個 className 存在
解決:
參考地址
className={`nav ${index === '1' ? 'active' : ''}`}
?? 4.路由跳轉(zhuǎn)和參數(shù)接受
?? 5.useState 和 useEffect
Hook概覽算芯,建議仔細閱讀文檔
這里會牽扯到 useEffect 后面有無 [] 的解釋
: 相當(dāng)于 componentDidMount和componentDidUpdate,有點類似計算屬性凳宙;
[] : 相當(dāng)于 componentDidMount 執(zhí)行一次熙揍,用來請求數(shù)據(jù);
[值]: 相當(dāng)于把方法與這個值綁定氏涩,值發(fā)生改變時届囚,就會調(diào)用該方法;
export default function IndexPage(props) {
const [bannerList, setBannerList] = useState([])
const [count, setCount] = useState(0)
useEffect(() => {
getBannerList().then(res=>{
//儲存輪播圖數(shù)據(jù)
setBannerList(res.data)
})
}, [])
useEffect(()=>{
//這里每次點擊add按鍵就會返回
console.log(count);
})
return (
<>
<div className='top'>
<Banner list={bannerList} />
<h1 className='title'>寄內(nèi)地</h1>
<button onClick={() => setCount(count + 1)}>add</button>
</div>
</>
);
}
?? 6.如何用 dva 定義一個 Model是尖,并修改
總而言之意系,這家伙有點類似于
vuex
,相當(dāng)于用來處理全局?jǐn)?shù)據(jù)的一個東西,希望下面的幾個文章可以幫到你
例子:
這是我簡單寫的一個切換用戶名的Model案例
需要留意的地方我已經(jīng)用 紅色 標(biāo)記出來了饺汹,尤其是 { } ,如果沒有的話蛔添,默認會接受一個 props ,在路由頁面?zhèn)鲄⒅杏刑岬?/code>
?? 7.權(quán)限路由(根據(jù)用戶登錄狀態(tài)兜辞,跳轉(zhuǎn)登錄頁)
約定式路由,如果按照官方推薦的目錄結(jié)構(gòu)迎瞧,是可以不用配置路由表的,它會自動生成
這里有兩種寫法逸吵,一種是放在route
路由表里凶硅,另一種是直接在指定頁面寫,看個人需求扫皱。
寫法1:wrappers
寫法2:權(quán)限路由 ??
?? 8.組件通信
?? React 中組件間通信的幾種方式
子用父:將數(shù)據(jù)綁定到子組件上足绅,子組件通過props接收捷绑;
//父組件
<Fu value={值} />
...
//子組件調(diào)用
this.props.value
父用子:通過useRef()
定義,并在子組件上綁定ref,.current
獲取DOM氢妈;
//父組件
const ziRef = useRef(null)
<Zi ref={ziRef} />
ziRef.current.state.{值}
子改父:通過在子組件上綁定一個關(guān)聯(lián)父組件的方法數(shù)據(jù)
//父組件
<Fu onChange={(值)=>{改值方法}} />
...
//子組件調(diào)用
this.props.onChange(值)
父改子:通過useRef()
定義粹污,并在子組件上綁定ref,.current
調(diào)用子組件定義修改值的方法;
//父組件
const ziRef = useRef(null)
<Zi ref={ziRef} />
ziRef.current.onChange(值)
...
//子組件
onChange = (值)=>{
改值方法
}
?? 9.函數(shù)式組件調(diào)用(forwardRef, useImperativeHandlede)
報錯信息:
**Warning:**devScripts.js:6523 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
如果你在封裝的組件上使用ref首量,那你就會發(fā)現(xiàn)這個錯誤厕怜,這就屬于函數(shù)式調(diào)用,需要 useRef forwardRef
的使用,同時還能配合 useImperativeHandlede
來暴露子組件的數(shù)值或者方法給父組件使用蕾总。
?? React函數(shù)式組件值之useRef()和useImperativeHandle()
?? React Hooks系列之useImperativeHandle
?? 10.在React中顯示html模塊內(nèi)容
<div dangerouslySetInnerHTML={{ __html: '版權(quán) ©' }} />
??11.修改List列表中的某一個數(shù)值
const [list,handleList] = useState([])
...
{
list.map((val, index) =><span onClick={() => {
let arr = [...list]
arr[index] = '修改'
handleList(arr)
}}>點擊修改list{index}的數(shù)值</span>
)}
??12.request請求配置
umi-request配置說明
本地端口號修改
如何獲取后端的相應(yīng)數(shù)據(jù) data
src/utils/request.js
/** Request 網(wǎng)絡(luò)請求工具 更詳細的 api 文檔: https://github.com/umijs/umi-request */
import { extend } from 'umi-request';
import { Toast } from 'antd-mobile';
const codeMessage = {
200: '服務(wù)器成功返回請求的數(shù)據(jù)粥航。',
201: '新建或修改數(shù)據(jù)成功。',
202: '一個請求已經(jīng)進入后臺排隊(異步任務(wù))生百。',
};
/** 異常處理程序 */
const errorHandler = (error) => {
const { response } = error;
console.log(response);
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
const { status, url } = response;
Toast.info({
message: `請求錯誤 ${status}: ${url}`,
description: errorText,
});
} else if (!response) {
Toast.info({
description: '您的網(wǎng)絡(luò)發(fā)生異常递雀,無法連接服務(wù)器',
message: '網(wǎng)絡(luò)異常',
});
}
return response;
};
/** 配置request請求時的默認參數(shù) */
const request = extend({
// prefix: 'http://192.168.0.115', //配置域名
timeout: 3000, //請求超時時間
headers: {},
// errorHandler,
// 默認錯誤處理
credentials: 'include', // 默認請求是否帶上cookie
});
// 請求攔截
request.interceptors.request.use((url, options) => {
options.headers['Authorization'] = 'Bearer'
return {
url,
options: { ...options, interceptors: true },
};
});
// 響應(yīng)攔截
request.interceptors.response.use(async (response) => {
const data = await response.clone().json();
if (data.code !== 200) {
Toast.info(data.message)
}
return response;
});
export default request;
使用
import request from '@/utils/request';
export function loginIn(data) {
return request('/api/login/account', {
method: 'POST',
data,
});
}
?? 13.受控組件空值警告解決
解決方法
//defaultValue 替換 `input` 上的 value
<input name='mobile' placeholder='電話' defaultValue={msg.mobile} onChange={handleInput} type="text" />
//or
<input name='mobile' placeholder='電話' value={msg.mobile || ''} onChange={handleInput} type="text" />
?? 14.useState()異步問題處理
下面的預(yù)期在某些時候并不是你想要的
const [num,handleNum] = useState(0)
...
useEffect(() => {
handleNum(1)
console.log(num) //0
handleNum(2)
console.log(num) //0
}, []);
例如:在移動端滑動加載更多 list,根據(jù)搜索條件去更新 list蚀浆,每次條件的變化就需要重新讓 list = [],然后再去獲取新的 list缀程,此時就會遇到這種 list 不能及時更新清空的問題
const [search,handleSearch] = useState('')
const [list,setList] = useState([])
獲取list數(shù)據(jù)
const fetchList = ()=> {
getList().then(res=>{
setList(...list,...res.data)
})
}
//根據(jù)篩選條件加載數(shù)據(jù)
useEffect(() => {
setList([]) //設(shè)想每次變化時就清空 list
fetchList() //但是在處理數(shù)據(jù)并沒有及時清空 list
}, [search]);
解決:
...
//每次條件變化就會清空 list
useEffect(() => {
setList([])
}, [search]);
//list發(fā)生變化就去調(diào)用接口數(shù)據(jù)
useEffect(() => {
//判斷當(dāng)list為[]時,調(diào)用接口
if(!list.length){
fetchList()
}
}, [list]);
?? 15.打包后修改輸出文件目錄 outputPath
outputPath 配置
outputPath:dist/shunfeng
,打包后會生成 dist
文件下shunfeng
文件下的其他文件
?? 16.如何使用sass
umi中使用sass只需安裝 @umijs/plugin-sass
yarn add @umijs/plugin-sass --D
安裝完后無需配置市俊,umi會自己識別杨凑。默認使用dart sass , 如果需要使用node-sass,才需要想官網(wǎng)那樣 配置
?? 17.createElement 和 cloneElement的區(qū)別
區(qū)別:傳入的第一個參數(shù)不同
React.createElement()
它接受三個參數(shù),第一個參數(shù)可以是一個標(biāo)簽名摆昧。如 div撩满、span,或者 React 組件绅你。第二個參數(shù)為傳入的屬性伺帘。第三個以及之后的參數(shù),皆作為組件的子組件忌锯。
React.createElement(type, [props], [...children]);
React.cloneElement()
React.cloneElement()
與 React.createElement()
相似伪嫁,不同的是它傳入的第一個參數(shù)是一個 React 元素,而不是標(biāo)簽名或組件偶垮。新添加的屬性會并入原有的屬性张咳,傳入到返回的新元素中,而舊的子元素將被替換似舵。將保留原始元素的鍵和引用脚猾。
React.cloneElement(element, [props], [...children]);
?? 18.路由按需加載,Loading
export default {
dynamicImport: {
loading: '@/Loading', //Loading組件
},
};
?? 19.部署后頁面不顯示問題
// 生產(chǎn) 測試配置
base: process.env.NODE_ENV === 'production' ? '/foo/' : '/',
publicPath: process.env.NODE_ENV === 'production' ? '/foo/' : '/',