阅读 391

【避坑指“难”】复选框☑️勾选,按钮可点击。常用于注册页、须知页,同意XXX协议(内含material-ui的坑)

PM:“用户需要同意XXX协议,才能点击按钮,否则就给它置灰!!!” 我:你说的对

在项目中经常会有这样需求,特别是在H5移动端,成了家常便饭,今天来详细讲讲代码实现过程。

技术栈:react + material-ui + typescript

实现效果如下 在这里插入图片描述 下面放上主要代码,主要逻辑在于复选框checkbox和按钮button,上面的文字布局就不赘述喽。

由于使用的是material-ui,所以部分组件名字和antd是有区别的,大家举一反三就好啦。

部分逻辑会写在注释里!!!

HTML

<Grid className={classes.checkboxItem}>
          <FormControlLabel
            control={
              <Checkbox
                classes={{
                  root: classes.radioRoot
                }}
                checked={checked}
                onChange={() => {
                  if(checked===false){
                    setChecked(true)
                  }else if (checked===true){
                    setChecked(false)
                  }
                }}
                size="small"
                color="primary"
              />
            }
            label="我已阅读并同意以上须知"
          />
        </Grid>
        <div className={classes.bottomContainer}>
          <Fab
            variant="extended"
            color="primary"
            aria-label="add"
            className={classes.bottomLink}
            disabled={btndisabled}
            onClick={getCountDown}
            style={{opacity:bottonOpa,backgroundColor:bottonBgColor,color:bottonColor}}
          >
            <Avatar
              variant="square"
              className={classes.bottomLinkIcon}
              src={img1}
            />
            立即申请
            {visible?
              <>{` (${time}s)`}</>
            :""}
          </Fab>
          </div>
      </Grid>
复制代码

CSS

	bottomLink: {
      position:'fixed',
      bottom:10,
      left:0,
      height: theme.typography.pxToRem(48),
      width: theme.typography.pxToRem(350),
      boxShadow: "0px 2px 8px 0px rgba(0, 127, 254, 0.3)",
      margin: `0 ${theme.typography.pxToRem(13)}`,
    },
    bottomLinkIcon: {
      width: 16,
      height: 19,
      marginRight: 8,
      marginTop: -2,
    },
    bottomContainer: {
      position: "fixed",
      bottom: 0,
      left: 0,
      right: 0,
      padding: "8px 12px",
    },
    checkboxItem:{
      position:'fixed',
      bottom:70,
      left:55,
    },
    radioRoot: {
      position: 'fixed',
      left: 10,
    },
复制代码

JS

1、引用相关组件库

import React, {useState, useEffect}from "react"; 
import { useHistory } from 'react-router-dom';
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import { Typography, Grid , Avatar, Fab} from "@material-ui/core";
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
复制代码

2、定义初始变量

let bottonOpa = 0.5; 
let bottonBgColor = '#007FFE';
let bottonColor = '#fff';

const img1 = require('@/assets/images/notice_button@2x.png')
复制代码

3、react hook在场景中的应用

  const history = useHistory();		//按钮点击后路由跳转
  const [checked, setChecked] = useState(false);	//复选框状态,默认未勾选
  const [btndisabled, setBtndisabled] = useState(true);		//按钮状态,默认为不可点击
  const [timerDisabled, setTimerDisabled] = useState(false); //监听时间
  const [time, setTime] = useState(15);		//倒计时15s
  const [visible, setVisible] = useState(true); //按钮的倒计时文案
复制代码

4、点击按钮触发的事件

  const getCountDown = () => {
    setTimerDisabled(true); 	//开始倒计时,并进行倒计时需要的一系列监听事件
    history.push('/nextPage')  	//路由跳转到下一页
  };
复制代码

5、监听时间+复选框

  useEffect(() => {
    const timeChange = setTimeout(() => {	//初始时间15s,开始倒计时,间隔为1s
      setTime((oldTime) => oldTime - 1); 
    }, 1000);
    if (timerDisabled) {	//判断如果没有进行时间监听,清除计时器
      clearInterval(timeChange);
    }
    if(time === 0){		//当倒计时为0
      clearInterval(timeChange);	//清除计时器		
      setVisible(false)		// 按钮的时间文案不用显示了
    }
    if (time === 0 && checked === true) { 	// 倒计时为0,且已勾选复选框☑️
      setBtndisabled(false)		//按钮可点击
      setVisible(false)			//按钮的时间文案不用显示了
      bottonOpa = 1			//按钮不用置灰
      clearInterval(timeChange);  //清除定时器
    }
    return ()=>{
      clearInterval(timeChange)
    }
  }, [time, timerDisabled]);


  useEffect(()=>{
    if(checked === true && !time){	//已勾选复选框☑️,时间为0
      setBtndisabled(false)		// 按钮可点击
      bottonOpa = 1		//按钮不用置灰
    }else {		//已勾选复选框勾选,但是时间还在走
      setBtndisabled(true) 	//按钮不可点击
      bottonOpa = 0.5		//按钮置灰
    }
  },[checked])
复制代码

整个操作流程就完成啦。

题外话:

1)为什么我写这么多变量来控制css样式(按钮半透明,不透明两个状态)?为什么我不直接给按钮添加disabled属性就好了?

谁不想呢!可是materi-ui他的设计师

在这里插入图片描述 是这样设计的,disabled灰的像天空刚哭过一样。。。

这根本满足不了我们高端洋气的产品的审美,所以只能通过变量的方式(虽然累了点),但是他要的我都能给!

2)为什么不去全局css文件里写disabled的样式??

我也希望material-ui能够普通平凡一点,直接可以.button_disabled{balabalabala},就覆盖它原本的样式,但是不行!!

他是这样的,我们只能改一写基本的属性值,比如root、input属性,所以。。。如果有小伙伴成功改变了disabled属性,请速速与我联系! 在这里插入图片描述

文章分类
前端
文章标签