Antd樣式覆蓋
項目中肯定需要部分頁面對原有的antd樣式做修改凰浮,剛開始弄的時候遇到不少坑励烦,后來查了方法和本項目中的寫法,主要修改的思路是:
- 用chrome的開發(fā)者工具定位到要修改的div城菊,查看class名
- 在對應(yīng)的less樣式下秘蛇,增加 :global 字段其做,再寫入對應(yīng)的class名,做樣式修改
- :global 需要包在自己頁面的 module 類內(nèi)赁还,以防污染其他頁面的全局樣式
// 這里采用了less作為css預(yù)處理器
:global {
// Tab 樣式修改
.ant-tabs-nav .ant-tabs-tab {
line-height: 20px;
padding: 13px 0 17px;
margin: 0 47px 0 0;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #4a4a4a;
text-align: center;
}
}
單頁面多表單取值
當(dāng)負(fù)責(zé)的頁面涉及到需要很多表單的時候妖泄,例如綁定郵箱、手機的步驟驗證或修改密碼等艘策,會出現(xiàn)單頁面多表單
這種情況蹈胡。一般會分為兩種:
- 一種是兩個以上表單同時獨立存在
- 一種是一個表單出現(xiàn)會銷毀上一個表單
情況1的處理
以手機/郵箱注冊為例
Tabs+Form
因為在Antd中,Tabs組件是帶緩存的朋蔫,所以在包含Tabs的頁面中罚渐,“手機注冊”和“郵箱注冊”的表單是同時存在的,這時候要對提交按鈕的方法做一下處理驯妄,防止出現(xiàn)提交當(dāng)前頁面的值去校驗另一個頁面的表單
的情況搅轿。
可以利用Form的getFieldsValue
方法的第一個參數(shù),自定義獲取幾組控件的值富玷。
例如:
handleSubmitStepOne = e => {
e.preventDefault();
const { form, dispatch } = this.props;
if (isSelectedEmail) {
form.validateFields(['email', 'captchaEmail'], (errors, values) => {
if (!errors) {
// 你的業(yè)務(wù)邏輯
}
});
} else {
form.validateFields(['phone', 'country', 'captchaPhone'], (errors, values) => {
if (!errors) {
// 你的業(yè)務(wù)邏輯
}
});
}
};
同時需要搭配tabs獲取當(dāng)前頁面key的做法璧坟,來判斷當(dāng)前頁面是哪個既穆。
??情況2的處理
以按照步驟條注冊的表單為例
帶步驟條的表單
針對這種場景有兩種思路:
- 用變量控制FormItem
- 采用組件化的實現(xiàn),抽離表單組件
這里以帶驗證碼按鈕的抽離表單組件為例
子組件需要提供如下方法:
方法/參數(shù) | 說明 | 類型 |
---|---|---|
type | 可以讓表單對應(yīng)不同的校驗規(guī)則或發(fā)送提示等雀鹃,增加表單復(fù)用的可能性 | “email”/“phone” |
getCaptcha | 父組件需要傳入的驗證碼發(fā)送接口幻工,需要返回true或false表示發(fā)送成功或失敗
|
Function |
getItemsValue | 向父組件返回表單的值,父組件調(diào)用此方法 | Function |
子組件寫法
import React, {Component} from 'react';
import {Button, Col, Form, Input, message, Row} from "antd";
import style from "./index.less";
const FormItem = Form.Item;
@Form.create()
class VerifiedForm extends Component {
state = {
count: 0,
captchaLoading: false,
};
componentWillUnmount() {
clearInterval(this.interval);
}
// 向父組件傳form表單的值
getItemsValue = () => {
let value = '';
this.props.form.validateFields((err, values) => {
if (!err) {
value = values;
}
});
return value;
};
// 獲取驗證碼按鈕點擊
onGetCaptcha = (type) => {
this.setState({captchaLoading: true});
// 獲取到父組件傳過來的驗證碼發(fā)送接口
this.props.getCaptcha()
.then(res => {
if (res === true) {
// 開始倒計時
message.success(type === 'email' ? '郵箱驗證碼已發(fā)送' : '手機號驗證碼已發(fā)送');
let count = 59;
this.setState({count, captchaLoading: false});
this.interval = setInterval(() => {
count -= 1;
this.setState({count});
if (count === 0) {
clearInterval(this.interval);
}
}, 1000);
} else {
this.setState({captchaLoading: false});
}
})
};
render() {
const {form: {getFieldDecorator}, type} = this.props;
const {count, captchaLoading} = this.state;
return (
<Form onSubmit={this.handleSubmit}>
<FormItem>
<Row gutter={16}>
<Col span={16}>
{getFieldDecorator('captcha', {
rules: [
{
required: true,
message: '驗證碼不能為空',
},
],
})(<Input size="large" placeholder="請輸入驗證碼" />)}
</Col>
<Col span={8}>
<Button
size="large"
style={{width: '100%'}}
disabled={count}
className={style.getCaptcha}
onClick={(e) => this.onGetCaptcha(type, e)}
loading={captchaLoading}
>
{count ? `${count} s` : '獲取驗證碼'}
</Button>
</Col>
</Row>
</FormItem>
</Form>
)
}
}
export default VerifiedForm;
“獲取驗證碼”按鈕的倒計時和恢復(fù)黎茎,以及表單校驗的邏輯都可以在表單組件中完成囊颅。只把需要的驗證碼發(fā)送接口和獲取表單值的方法暴露給父組件。
父組件寫法
<div>
<VerifiedForm
// antd提供的方法獲取到表單組件的ref
wrappedComponentRef={form => {
this.form = form;
}}
// sendEmailCaptcha方法中包含驗證碼發(fā)送接口
getCaptcha={this.sendEmailCaptcha}
type="email"
/>
<Button
size="large"
type="primary"
loading={loadingCheckBindEmailCaptcha}
style={{ width: '100%', marginTop: 8 }}
onClick={this.handleClick}
disabled={!hasSendCaptcha}
>
下一步
</Button>
</div>
提交表單的按鈕需放在父組件傅瞻,通過按鈕handleClick
方法調(diào)用表單組件的values值
handleClick = () => {
// 此處獲取表單值
const values = this.form.getItemsValue();
// 業(yè)務(wù)邏輯
}
響應(yīng)式布局
這里用到了媒體查詢
踢代,它有兩種方式。
- 直接寫在link中嗅骄,根據(jù)設(shè)備尺寸的不同引入不同的CSS文件
// 意思是當(dāng)屏幕的寬度 大于等于400px的時候胳挎,應(yīng)用styleA.css
<link rel="stylesheet" type="text/css" href="styleA.css" media="screen and (min-width: 400px)">
- 寫在<style>樣式里
@media screen and (max-width: 600px) { /*當(dāng)屏幕尺寸小于600px時,應(yīng)用下面的CSS樣式*/
.class {
background: #ccc;
}
}
項目中用的是方式二溺森,值得注意的是@media screen
要放在對應(yīng)的樣式尾部慕爬,有層級關(guān)系!
關(guān)鍵字
類型 | 解釋 |
---|---|
and | 并關(guān)系屏积,用于連接邏輯 |
not | 排除某種設(shè)備 |
all | 所有設(shè)備 |
aural | 聽覺設(shè)備 |
braille | 點字觸覺設(shè)備 |
handled | 便攜設(shè)備医窿,如手機、平板電腦 |
打印預(yù)覽圖等 | |
projection | 投影設(shè)備 |
screen |
顯示器炊林、筆記本姥卢、移動端等設(shè)備 |
tty | 如打字機或終端等設(shè)備 |
tv | 電視機等設(shè)備類型 |
embossed | 盲文打印機 |
出現(xiàn)滾動條的高度計算
首先明確
- window.innerHeight: 獲取瀏覽器窗口的高度
-
document.body.clientHeight: 獲取body的高度
出現(xiàn)這兩種,一部分是為了解決不同瀏覽器的兼容性問題渣聚,還有移動web寬高的問題独榴。在一般情況下兩個值是相等的,但是在頁面出現(xiàn)滾動條的情況下饵逐,innerHeight的計算會加入滾動條的height。
所以在動態(tài)計算頁面最小高度時彪标,需要兩者相減倍权。參考如下代碼:
minHeight: `calc(100vh - 198px - ${window.innerHeight - document.body.clientHeight}px)`,
多條件篩選
按鈕篩選案例
針對react中使用多組按鈕來控制篩選,可采用如下方法進行擴展捞烟。
-
全部
按鈕的value值為空字符 - 其余各個篩選按鈕的value值對應(yīng)后端傳過來的值
以“全部”薄声、“iOS開發(fā)專家”、“Android開發(fā)專家”......這幾個按鈕為例题画。
<RadioGroup
value={identityStatus}
onChange={e => this.handleChangeDataStatus(e)}
>
<RadioButton value="">全部</RadioButton>
<RadioButton value="iOS開發(fā)專家">iOS開發(fā)專家</RadioButton>
<RadioButton value="Android開發(fā)專家">Android開發(fā)專家</RadioButton>
<RadioButton value="H5開發(fā)專家">H5開發(fā)專家</RadioButton>
<RadioButton value="部署專家">部署專家</RadioButton>
<RadioButton value="后端開發(fā)專家">后端開發(fā)專家</RadioButton>
</RadioGroup>
篩選方法
// 兩組按鈕各自的選擇狀態(tài)
const { reviewStatus, identityStatus } = this.state;
// 過濾方法
tempDataSource = tempDataSource.filter(item => {
// 設(shè)定初始flag狀態(tài)
let flagReview = !reviewStatus;
let flagIdentity = !identityStatus;
// 第一組按鈕過濾
if (reviewStatus && item.reviewStatus) {
flagReview = true;
}
// 第二組按鈕過濾
if (identityStatus && identityStatus === item.type) {
flagIdentity = true;
}
return flagReview && flagIdentity;
});
this.setState({ dataSource: tempDataSource });