Antd Pro2中使用Antd部分技巧总结(一)

Antd样式覆盖

项目中肯定需要部分页面对原有的antd样式做修改,刚开始弄的时候遇到不少坑,后来查了方法和本项目中的写法,主要修改的思路是:

  1. 用chrome的开发者工具定位到要修改的div,查看class名
  2. 在对应的less样式下,增加 :global 字段,再写入对应的class名,做样式修改
  3. :global 需要包在自己页面的 module 类内,以防污染其他页面的全局样式
// 这里采用了less作为css预处理器
: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;
  }
}

单页面多表单取值

当负责的页面涉及到需要很多表单的时候,例如绑定邮箱、手机的步骤验证或修改密码等,会出现单页面多表单这种情况。一般会分为两种:

  1. 一种是两个以上表单同时独立存在
  2. 一种是一个表单出现会销毁上一个表单
    情况1的处理
    以手机/邮箱注册为例
    Tabs+Form

    因为在Antd中,Tabs组件是带缓存的,所以在包含Tabs的页面中,“手机注册”和“邮箱注册”的表单是同时存在的,这时候要对提交按钮的方法做一下处理,防止出现提交当前页面的值去校验另一个页面的表单的情况。
    可以利用Form的getFieldsValue方法的第一个参数,自定义获取几组控件的值。
    例如:
  handleSubmitStepOne = e => {
    e.preventDefault();
    const { form, dispatch } = this.props;
    if (isSelectedEmail) {
      form.validateFields(['email', 'captchaEmail'], (errors, values) => {
        if (!errors) {
          // 你的业务逻辑
        }
      });
    } else {
      form.validateFields(['phone', 'country', 'captchaPhone'], (errors, values) => {
        if (!errors) {
          // 你的业务逻辑
        }
      });
    }
  };

同时需要搭配tabs获取当前页面key的做法,来判断当前页面是哪个。

  情况2的处理
以按照步骤条注册的表单为例

带步骤条的表单

针对这种场景有两种思路:

  1. 用变量控制FormItem
  2. 采用组件化的实现,抽离表单组件
    这里以带验证码按钮的抽离表单组件为例
    子组件需要提供如下方法:
方法/参数 说明 类型
type 可以让表单对应不同的校验规则或发送提示等,增加表单复用的可能性 “email”/“phone”
getCaptcha 父组件需要传入的验证码发送接口,需要返回true或false表示发送成功或失败 Function
getItemsValue 向父组件返回表单的值,父组件调用此方法 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});
    // 获取到父组件传过来的验证码发送接口
    this.props.getCaptcha()
      .then(res => {
        if (res === true) {
          // 开始倒计时
          message.success(type === 'email' ? '邮箱验证码已发送' : '手机号验证码已发送');
          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;

“获取验证码”按钮的倒计时和恢复,以及表单校验的逻辑都可以在表单组件中完成。只把需要的验证码发送接口和获取表单值的方法暴露给父组件。

父组件写法

<div>
    <VerifiedForm
      // antd提供的方法获取到表单组件的ref
      wrappedComponentRef={form => {
        this.form = form;
      }}
      // sendEmailCaptcha方法中包含验证码发送接口
      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方法调用表单组件的values值

handleClick = () => {
    // 此处获取表单值
    const values = this.form.getItemsValue();
    // 业务逻辑
}

响应式布局

这里用到了媒体查询,它有两种方式。

  1. 直接写在link中,根据设备尺寸的不同引入不同的CSS文件
// 意思是当屏幕的宽度 大于等于400px的时候,应用styleA.css
<link rel="stylesheet" type="text/css" href="styleA.css" media="screen and (min-width: 400px)">
  1. 写在<style>样式里
@media screen and (max-width: 600px) { /*当屏幕尺寸小于600px时,应用下面的CSS样式*/
      .class {
          background: #ccc;
       }          
  }

项目中用的是方式二,值得注意的是@media screen要放在对应的样式尾部,有层级关系!
关键字

类型 解释
and 并关系,用于连接逻辑
not 排除某种设备
all 所有设备
aural 听觉设备
braille 点字触觉设备
handled 便携设备,如手机、平板电脑
print 打印预览图等
projection 投影设备
screen 显示器、笔记本、移动端等设备
tty 如打字机或终端等设备
tv 电视机等设备类型
embossed 盲文打印机

出现滚动条的高度计算

首先明确

  • window.innerHeight: 获取浏览器窗口的高度
  • document.body.clientHeight: 获取body的高度
    出现这两种,一部分是为了解决不同浏览器的兼容性问题,还有移动web宽高的问题。在一般情况下两个值是相等的,但是在页面出现滚动条的情况下,innerHeight的计算会加入滚动条的height。
    所以在动态计算页面最小高度时,需要两者相减。参考如下代码:
minHeight: `calc(100vh - 198px - ${window.innerHeight - document.body.clientHeight}px)`,

多条件筛选

按钮筛选案例

针对react中使用多组按钮来控制筛选,可采用如下方法进行扩展。

  1. 全部按钮的value值为空字符
  2. 其余各个筛选按钮的value值对应后端传过来的值
    以“全部”、“iOS开发专家”、“Android开发专家”......这几个按钮为例。
    <RadioGroup
      value={identityStatus}
      onChange={e => this.handleChangeDataStatus(e)}
    >
      <RadioButton value="">全部</RadioButton>
      <RadioButton value="iOS开发专家">iOS开发专家</RadioButton>
      <RadioButton value="Android开发专家">Android开发专家</RadioButton>
      <RadioButton value="H5开发专家">H5开发专家</RadioButton>
      <RadioButton value="部署专家">部署专家</RadioButton>
      <RadioButton value="后端开发专家">后端开发专家</RadioButton>
    </RadioGroup>

筛选方法

// 两组按钮各自的选择状态
const { reviewStatus, identityStatus } = this.state;
// 过滤方法
tempDataSource = tempDataSource.filter(item => {
  // 设定初始flag状态
  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 });
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 目录 1 form 表单中 FormItem 的布局 2 form 表单,FormItem 的 rules 中新增...
    林ze宏阅读 21,742评论 2 19
  • 正如Ant Design 官方介绍: "在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多...
    sunnyghx阅读 4,202评论 1 2
  • HTML标签解释大全 一、HTML标记 标签:!DOCTYPE 说明:指定了 HTML 文档遵循的文档类型定义(D...
    米塔塔阅读 3,229评论 1 41
  • “现在村庄里是什么情况?全是丧尸为什么会打起来?”我好奇地问道。 “有……一只……丧……尸猫……侵入……他……们的...
    栩风暖暖阅读 268评论 2 2
  • 日常开发时我们经常使用log来打印数据用来调试程序或者查看数据,有些时候我们需要打印的数据很长比如List数组里数...
    EraJieZhang阅读 3,106评论 0 2