随笔

13 篇文章 0 订阅
5 篇文章 0 订阅

随笔

文章目录

一、求一个数组中的两个数和为某个值,返回这两数的索引(没有考虑数组重复的情况)

一个数组中的两个数和为一个值,返回对应的数,比如【1,2,3,4,5】,让和为5,则结果就是1,4,可以输出其对应索引为【0,3function sum(arr, result){
    let obj={};
    for(var index=0;index<arr.length;index++){
         let num = arr[index];
         if(num  in obj){return [obj[num], index]}else{obj[result -num]=index;}
    }
}

二、排序

 1. 冒泡排序

> 说明
时间复杂度指的是一个算法执行所耗费的时间
空间复杂度指运行完一个程序所需内存的大小
稳定指,如果a=b,a在b的前面,排序后a仍然在b的前面
不稳定指,如果a=b,a在b的前面,排序后可能会交换位置
JS冒泡排序 
原理
依次比较相邻的两个值,如果后面的比前面的小,则将小的元素排到前面。依照这个规则进行多次并且递减的迭代,直到顺序正确。
时间复杂度,空间复杂度,稳定性
平均时间复杂度O(n*n)
最好情况O(n)
最差情况O(n*n)
空间复杂度O(1)
稳定性:稳定
冒泡排序:
var examplearr=[8,94,15,88,55,76,21,39];
function sortarr(arr){
    for(i=0;i<arr.length-1;i++){
        for(j=0;j<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
                var temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
    return arr;
}
sortarr(examplearr);
console.log(examplearr);

 2. 快排

> 快排(递归的思路):
方式一:
var quickSort = function(arr) {
  if (arr.length <= 1) {
    return arr;
  }
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];
  var left = [];
  var right = [];
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return quickSort(left).concat([pivot], quickSort(right));
};
以上代码的实现方式是,选择一个中间的数字为基准点,用两个数组分别去保存比基准数小的值,
和比基准数大的值,最后递归左边的数组和右边的数组,用concat去做一个数组的合并。
对于这段代码的分析:
**缺点:**
获取基准点使用了一个splice操作,在js中splice会对数组进行一次拷贝的操作,而它最坏的情况下复杂度为O(n),而O(n)代表着针对数组规模的大小进行了一次循环操作。
首先我们每次执行都会使用到两个数组空间,产生空间复杂度。
concat操作会对数组进行一次拷贝,而它的复杂度也会是O(n)
对大量数据的排序来说相对会比较慢
**优点:**
代码简单明了,可读性强,易于理解
非常适合用于面试笔试题

 3. 选择排序:

```typescript
function selectSort(arr){
	for(var i=0; i<arr.length-1; i++){
		var minIndex = i;
		for(var j=i+1;j<arr.length;j++){
			if(arr[minIndex] > arr[j]){
				minIndex = j;
			}
		}
		var temp = arr[minIndex];
		arr[minIndex]=arr[i];
		arr[i]=temp;
	}
	return arr;
}
selectSort([3,2,5,1,6,9,-10,4,10]);

三、统计出现次数最多的三个节点(即标签)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const allTag = [...document.getElementsByTagName('*')];
        console.log('所有的标签', allTag);
        const allTagMap = allTag.map((item, index)=>{
            return (item.tagName)
        });
        var obj = {};
        allTagMap.map((item, index)=>{
            if(item in obj){
                obj[item]+=1;
            }else{
                obj[item]=1;
            }
        });
        function sortTag(obj){
            return Object.keys(obj).sort((a,b)=>obj[b]-obj[a]); // 按照其属性值进行排列
        }
        var resultSortTag = sortTag(obj);
        var theFirstsThree = {};
        for(var i = 0; i<3; i++){
            var qian = resultSortTag[i];
            theFirstsThree[qian] = obj[qian];
        }
        console.log('前三个标签是:', theFirstsThree);
    </script>
</body>
</html>

四、前端如何优雅的处理类数组对象

  • 常见的几种类数组对象:
  1. arguments对象

arguments 对象;
function fun() {
return arguments;
}
fun(1,2,3)
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
在这里插入图片描述

  1. NodeList(比如 document.getElementsByClassName(‘a’) 得到的结果;
    document.getElementsByTagName(‘img’)
    // HTMLCollection(3) [img, img, img]

NodeList(比如
document.getElementsByTagName(‘img’)
// HTMLCollection(3) [img, img, img]
在这里插入图片描述

  1. typedArray(比如 Int32Array);

这里是引用

  1. 使用 jQuery 获取的元素

$('img')// init(3) [img, img, img, prevObject: init(1), context: document, selector: "img"]

  • 类数组对象处理

Array.from()、Array.prototype.slice.call()、[…]、Array.protype.concat.apply()

const memberList = Array.prototype.slice.call($('#MemberList li'));
const memberList = [...document.getElementsByTagName("li")];
const memberList = Array.prototype.concat.apply([], $('#MemberList li'));
const memberList = Array.from($('#MemberList li'));  
Array.from语法如下:
Array.from(arrayLike[, mapFn[, thisArg]])
参数:
arrayLike 想要转换成数组的伪数组对象或可迭代对象。
mapFn 可选如果指定了该参数,新数组中的每个元素会执行该回调函数。
thisArg 可选可选参数,执行回调函数 mapFn 时 this 对象。

五、wrappedComponentRef获取子组件的实例

class A extends Component {
    cRef = React.createRef();
    。。。。
    // 调用B组件实例的方法showModal
	this.cRef.current.showModal();
	。。。。。
	// 使用wrappedComponentRef
	<B wrappedComponentRef={this.cRef}/> 
	// 也有下面的这种使用方式(就可以不使用上面的 React.createRef())
	<MediaForm wrappedComponentRef={node => this.formRef = node} .... />

六、遍历数组,将内外层结构一样的数组重新构建得到想要的数据结构的新数组

const transformData = (params, showData) = >{
  const arr = showData;
  params.map((item, index) = >{
    if (item.children.length) {
      const brr = [];
      arr.push({
        title: item.name,
        value: item.code,
        children: transformData(item.children, brr)
      })
    } else {
      arr.push({
        title: item.name,
        value: item.code
      });
    }
  }) return arr
};
const contentData = [{
  "children": [{
    "children": [],
    "code": 103003003,
    "name": "注册会计",
    "parentCode": 103003
  },
  {
    "children": [],
    "code": 103003002,
    "name": "CFA",
    "parentCode": 103003
  },
  {
    "children": [],
    "code": 103003001,
    "name": "律师",
    "parentCode": 103003
  },
  {
    "children": [{
      "children": [],
      "code": 103003004001,
      "name": "建造师高级",
      "parentCode": 103003004
    }],
    "code": 103003004,
    "name": "建造师",
    "parentCode": 103003
  }],
  "code": 103003,
  "name": "职业考试",
  "parentCode": 103
},
{
  "children": [],
  "code": 104001,
  "name": "建造师",
  "parentCode": 104
}];
const showData = [];
console.log(transformData(contentData, showData));

七、git相关(部分)

  1. 先拉取最新master分支,然后将master合并到本地分支:
    git checkout master
    git pull
    git checkout 本地分支
    git merge master
    git status(这个命令可以检查一下,然后没有push的话就会提示让push,所以最好push一下)
    将dev分支合并到test分支(假如现在就在dev分支):
    git checkout test
    git pull
    git merge dev
    git push
    git status
  2. 本地项目更改远程仓库地址说明:
    1.更改项目的的仓库地址为变更后的仓库地址:
    以aaa项目(变更后的仓库地址是git@gitlab…/bbb.git)为例:
    命令:git remote set-url origin git@gitlab…/bbb.git
    2.更改本地工作空间中的项目文件夹名为变更后git仓库名称, 例如:aaa 变为 bbb
    3.完成

八、倒计时

          <CountDown
            format="hh:mm"
            startDate={new Date()}
            endDate={text}
            /* cb={() => {
            console.log('倒计时结束');
          }} */
          />
**CountDown组件如下:**
import React, { useEffect } from 'react';
import { useImmer } from 'use-immer';

export type CdFormat = 'dd:hh:mm:ss' | 'hh:mm:ss' | 'hh:mm' | 'mm:ss';

interface IProps {
  startDate: string | Date;
  endDate: string | Date;
  format?: CdFormat;
  cb?(): void;
}

const stringToDate = (date: string | Date) => {
  if (typeof date === 'string') {
    // 日期字符串转换为日期对象,并兼容ios
    return new Date(Date.parse(date.replace(/-/g, '/')));
  }
  return date;
};

/**
 * 单个数字格式化为两位数, 9 => 09
 * @param num
 * @returns {string}
 */
const formatTwoDigit = (num: number): string => {
  if (num < 10) {
    return (Array(2).join('0') + num).slice(-2);
  }
  return num.toString();
};

const CountDown: React.FC<IProps> = props => {
  const [formatDate, setFormatDate] = useImmer<string>('');

  const { startDate, endDate, format = 'hh:mm:ss', cb = () => {} } = props;
  const [defaultValue, setDefaultValue] = useImmer<string>('');
  useEffect(() => {
    switch (format) {
      case 'dd:hh:mm:ss':
        setDefaultValue(() => '00:00:00:00');
        break;
      case 'hh:mm:ss':
        setDefaultValue(() => '00:00:00');
        break;
      default:
        setDefaultValue(() => '00:00');
    }
  }, [format]);
  useEffect(() => {
    let interval: any = null;
    clearInterval(interval);

    const sDate = stringToDate(startDate);
    const eDate = stringToDate(endDate);

    const startTime = sDate.getTime();
    const endTime = eDate.getTime();

    // 获取相差的毫秒数
    let diffTime = endTime - startTime;

    if (diffTime > 0) {
      interval = setInterval(() => {
        if (diffTime <= 0) {
          clearInterval(interval);
          cb();
          interval = null;
        }

        let m: string = formatTwoDigit(Math.floor((diffTime / 1000 / 60) % 60));
        const s: string = formatTwoDigit(Math.floor((diffTime / 1000) % 60));

        let result = '';

        // dd:hh:mm:ss
        if (/^(d{2}).+(h{2}).+(m{2}).+(s{2})$/.test(format)) {
          const d: string = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60 / 24));
          const h: string = formatTwoDigit(Math.floor((diffTime / 1000 / 60 / 60) % 24));
          result = format
            .replace(/dd/, d)
            .replace(/hh/, h)
            .replace(/mm/, m)
            .replace(/ss/, s);
          setFormatDate(() => result);
        }
        // hh:mm:ss
        else if (/^(h{2}).+(m{2}).+(s{2})$/.test(format)) {
          const h = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60));
          result = format
            .replace(/hh/, h)
            .replace(/mm/, m)
            .replace(/ss/, s);
          setFormatDate(() => result);
        }
        // hh:mm
        else if (/^(h{2}).+(m{2})$/.test(format)) {
          const h = formatTwoDigit(Math.floor(diffTime / 1000 / 60 / 60));
          result = format.replace(/hh/, h).replace(/mm/, m);
          setFormatDate(() => result);
        }
        // mm:ss
        else if (/^(m{2}).+(s{2})$/.test(format)) {
          m = formatTwoDigit(Math.floor(diffTime / 1000 / 60));
          result = format.replace(/mm/, m).replace(/ss/, s);
          setFormatDate(() => result);
        } else {
          clearInterval(interval);
          interval = null;
          throw new Error('format is error');
        }
        diffTime -= 1000;
      }, 1000);
    }

    return () => {
      clearInterval(interval);
    };
  }, [startDate, endDate]);
  return <div>{formatDate || defaultValue}</div>;
};

export default React.memo(CountDown);


九、在js(ts)中实现弹出一个弹窗

// 在ts中实现弹出一个弹窗
const { confirm } = Modal;
confirm({
        title: '提示',
        content: '是否确定对所选档案进行启用?',
        onOk() {
          startConfirm(selectedRowKeys);
        },
        onCancel() {
          console.log('Cancel');
        }
      });

十、时长(过去多长时间HH:mm:ss)

import dayjs from 'dayjs';
import React, { useEffect } from 'react';
import { useImmer } from 'use-immer';

export type CdFormat = 'HH:mm:ss' | 'HH:mm' | 'mm:ss';

interface IProps {
  startDate: string | Date;
  format?: CdFormat;
  cb?(): void;
}

const stringToDate = (date: string | Date) => {
  if (typeof date === 'string') {
    // 日期字符串转换为日期对象,并兼容ios
    return new Date(Date.parse(date.replace(/-/g, '/')));
  }
  return date;
};

const Duration: React.FC<IProps> = props => {
  const [formatDate, setFormatDate] = useImmer<string>('');
  const { startDate, format = 'HH:mm:ss', cb = () => {} } = props;
  useEffect(() => {
    let interval: any = null;
    clearInterval(interval);
    if (startDate) {
      const sDate = stringToDate(startDate);
      interval = setInterval(() => {
        setFormatDate(() =>
          dayjs(
            dayjs()
              .subtract(8, 'hour')
              .diff(dayjs(sDate))
          ).format(format)
        );
      }, 1000);
    }
    return () => {
      clearInterval(interval);
    };
  }, [startDate]);
  return <div>{formatDate || ''}</div>;
};

export default React.memo(Duration);


十一、密码校验(ant design)

密码不能小于六位,至少含字母、数字、特殊字符其中的2种!(不能包括中文及中文符号)登陆时的密码校验(两次输入得相同)

法一:

                      <Form.Item
                  name="initPassword"
                  label="初始密码"
                  rules={[
                    {
                      validator: (rule, value, callback) => {
                        const oNumber = new RegExp(/\d/);
                        const oLetter = new RegExp(/[a-zA-Z]/);
                        const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';

                        if (!value) {
                          callback('密码必填!');
                          return;
                        }

                        if (value.length < 6) {
                          callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!');
                          return;
                        }

                        try {
                          [...value].forEach(val => {
                            if (
                              !(
                                oNumber.test(val) ||
                                oLetter.test(val) ||
                                oSpecial.indexOf(val) >= 0
                              )
                            ) {
                              throw new Error();
                            }
                          });
                        } catch (e) {
                          callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!');
                        }

                        const contain: boolean[] = [];

                        [...value].forEach(val => {
                          if (oNumber.test(val)) {
                            contain[0] = true;
                          }
                          if (oLetter.test(val)) {
                            contain[1] = true;
                          }
                          if (oSpecial.indexOf(val) >= 0) {
                            contain[2] = true;
                          }
                        });

                        if (contain.filter(item => item === true).length < 2) {
                          callback('密码不能小于六位,至少含字母、数字、特殊字符其中的2种!');
                          return;
                        }
                        callback();
                      }
                    }
                  ]}
                >
                  <Input
                    onChange={() => {
                      setSaveFlag(() => false);
                    }}
                    disabled={disableFlag}
                    className="largeWidth"
                    placeholder="请输入初始密码"
                  />
                </Form.Item>
                

法二:

                <Form.Item
                  name="initPassword"
                  label="初始密码"
                  rules={[
                    {
                      validator: (rule, value) => {
                        const oNumber = '0123456789';
                        const oLetter = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                        const oSpecial = '`.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';
                        const oTher = oNumber + oLetter + oSpecial;
                        let total = 0;
                        const oSpeArr = value.split('');
                        const oNumberItem = oSpeArr.find(
                          (item: any) => oNumber.indexOf(item) !== -1
                        );
                        const oLetterItem = oSpeArr.find(
                          (item: any) => oLetter.indexOf(item) !== -1
                        );
                        const oSpeItem = oSpeArr.find((item: any) => oSpecial.indexOf(item) !== -1);
                        const oTherItem = oSpeArr.find((item: any) => oTher.indexOf(item) === -1);
                        if (!value) {
                          rule.message = '密码必填!';
                          return Promise.reject();
                        }
                        console.log(oNumberItem, oLetterItem, oSpeItem);
                        if (value.length < 6 || oTherItem !== undefined) {
                          rule.message = '密码不能小于六位,至少含字母、数字、特殊字符其中的2种!';
                          return Promise.reject();
                        }
                        if (oNumberItem !== undefined) {
                          total += 1;
                        }
                        if (oLetterItem !== undefined) {
                          total += 1;
                        }
                        if (oSpeItem !== undefined) {
                          total += 1;
                        }
                        if (total >= 2) {
                          return Promise.resolve();
                        }
                        rule.message = '密码不能小于六位,至少含字母、数字、特殊字符其中的2种!';
                        return Promise.reject();
                      }
                    }
                  ]}
                >
                  <Input
                    onChange={() => {
                      setSaveFlag(() => false);
                    }}
                    disabled={disableFlag}
                    className="largeWidth"
                    placeholder="请输入初始密码"
                  />
                </Form.Item>

十二、时间跨度超过XXX的日期置灰不可选择(ant design-RangePicker)

**状态**
  const [validDateFlag, setValidDateFlag] = useImmer<boolean>(false);
  const [dates, setDates]: any = useState([]);
  const [hackValue, setHackValue]: any = useState();
  const [dateValue, setDateValue]: any = useState();
**方法**
  // 不可选的日期范围(时间跨度不能超过3年,超过3年的日期置灰不可选择)
  const handleDisabledDate = (current: any) => {
    if (!dates || dates.length === 0) {
      return false;
    }
    const tooLate = dates[0] && current.diff(dates[0], 'days') > 1095; // 3年
    const tooEarly = dates[1] && dates[1].diff(current, 'days') > 1095;
    return tooEarly || tooLate;
  };
  const onDateOpenChange = (open: any) => {
    if (open) {
      setHackValue([]);
      setDates([]);
    } else {
      setHackValue(undefined);
    }
  };
 **组件**
           <Form.Item label="有效期">
            <RangePicker
              className={validDateFlag ? 'tip_rangepicker' : ''}
              showTime
              format={formatTime}
              value={hackValue || dateValue}
              disabledDate={handleDisabledDate}
              onCalendarChange={val => setDates(val)}
              onOpenChange={onDateOpenChange}
              onChange={val => {
                setDateValue(val);
                !val && setValidDateFlag(() => true);
                val && setValidDateFlag(() => false);
              }}
            />
          </Form.Item>
          {validDateFlag && <div className="tip_date">有效期不能为空</div>} 
 **样式**
   .ant-picker {
    &.tip_rangepicker {
      border-color: #ff4d4f !important;
      &.ant-picker-focused {
        box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.2);
      }
    }
  }
  .tip_date {
    margin: -24px 0 2px 0;
    color: #ff4d4f;
  }          

样式部分:就是类似必须项的样式;
自定义这部分样式的原因:是因为如果在form.Item中添加name后,在其里面时,当值不能按照理想的方向改变时,遇到这种情况需要自己定义想要的样式,这次的这个设置不可选择日期等属性后发现没有按照想要的方向显示相应日期,就去掉name然后自己定义必填样式了。
在这里插入图片描述

有一个问题(待解决)是:上述
const [dates, setDates]: any = useState([]);
const [hackValue, setHackValue]: any = useState();
const [dateValue, setDateValue]: any = useState();
使用useImmer替换useState,方法中改变状态的方式也变为useImmer下改变状态的方式,但是在选择日期后没有日期显示是空的,所以就没有改变使用useImmer
在这里插入图片描述

十三、直接触发表单验证中的某一个(ant design——form)

如何直接触发表单验证中的某一个
比如:设置为undefined后先让其直接就出来提示,可以设置form.validateFields(['名字']);
      form.setFieldsValue({
        briefUrls: undefined // 为了让其有提示
      });
      form.validateFields(['briefUrls']);

十四、history跳转页面后,获取参数

跳转页面通过
history.push({
      pathname: '/intent/handle/ProcessIntentOrder',
      query: { id: record.id, checkFlag: false } 
});
// 到跳转页面后
const { query = {} } = props.location;
console.log(query.checkFlag, '查看还是处理'); // 获取到的会是一个字符串false,所以通过props.location获取的话最好记得是将checkFlag:'false'或者用下边的这种

使用这种方式的history就可以传递的是boolean类型的,获取到的也会是boolean类型的

import { history } from 'umi';
history.push({
      pathname: '/sysmange/message/manage/messageset',
      state: { id: record.id, checkFlag: false } // 或者用query:参数会显示在url上
    });
// 到跳转页面后
const { state = {} } = history.location;

十五、一些插件

  1. 水印
 npm install --save watermark-component-for-react

十六、

一些常用样式的设置

文章目录


一、一行或者多行文本显示省略号

// 一行或者多行文本显示省略号
.omitCommon {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
}
.doubleOmit {
  .omitCommon;
  -webkit-line-clamp: 2;
}

二、ant design-form表单去掉必填项前面的星号*及后面的冒号

/* 表单去掉必填项前面的星号*及后面的冒号 */
.special_form {
  .ant-form-item-label > label::after {
    content: '';
    position: relative;
    top: -0.5px;
    margin: 0 10px 0 0;
  }
  .ant-form-item-label
    > label.ant-form-item-required:not(.ant-form-item-required-mark-optional)::before {
    display: none;
  }
}

三、flex

/* ==========================================================
   flex:定义布局为盒模型
   flex-v:盒模型垂直布局
   flex-1:子元素占据剩余的空间
   flex-align-center:子元素垂直居中
   flex-pack-center:子元素水平居中
   flex-pack-justify:子元素两端对齐
   兼容性:ios 4+、android 2.3+、winphone8+
   ============================================================ */
.flex {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
.flex-v {
  -webkit-box-orient: vertical;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
}
.flex-1 {
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
.flex-2 {
  -webkit-box-flex: 2;
  -webkit-flex: 2;
  -ms-flex: 2;
  flex: 2;
}
.flex-align-center {
  -webkit-box-align: center;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}
.flex-pack-center {
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  -ms-flex-pack: center;
  justify-content: center;
}
.flex-pack-justify {
  -webkit-box-pack: justify;
  -webkit-justify-content: space-between;
  -ms-flex-pack: justify;
  justify-content: space-between;
}

四、底部固定的Footer

/* ==========================================================
    底部固定的Footer
  ============================================================ */
.Footer {
  position: fixed;
  bottom: 0;
  left: 207px;
  display: flex;
  background: #fff;
  justify-content: center;
  align-items: center;
  box-shadow: 0px -4px 10px 0px rgba(187, 189, 202, 0.19);
  height: 64px;
  line-height: 64px;
  z-index: 100;
  &.unfold {
    // 左侧侧边栏未折叠时
    left: 80px;
    width: calc(100% - 80px);
  }
  &.fold {
    // 左侧侧边栏折叠时
    left: 207px;
    width: calc(100% - 207px);
  }
  button {
    width: 80px;
    height: 32px;
    font-size: 12px;
    &:nth-last-of-type(2) {
      margin-right: 30px;
    }
  }
}

五、文本内换行(需要单独设置合适的宽度)

/* ==========================================================
    文本内换行(需要单独设置合适的宽度)
  ============================================================ */
.special_wrap {
  white-space: pre-line;
  display: inline-flex;
  word-break: break-all;
}

六、重置样式

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
  display: block;
}
body {
  line-height: 1;
  overflow: hidden;
}
ol,
ul {
  list-style: none;
}
blockquote,
q {
  quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}
table {
  border-collapse: collapse;
  border-spacing: 0;
}

html,
body {
  height: 100%;
  width: 100%;
  background-color: #f5f5f5;
  overflow: hidden;
}

#root {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

十七、ant design中column上width属性设置无效问题

列参数:
export interface Column {
  title: string;
  width?: number;
  dataIndex?: string;
  fixed?: string;
  ellipsis?: boolean;
  defaultSortOrder?: string;
  sorter?: any;
  align?: string;
  sortOrder?: string | boolean;
  render?(text?: number | string, record?: any, index?: number): void;
}
  const columns: Column[] = [
    {
      title: '操作',
      width: 50,
      ellipsis: true,
      align: 'center',
      fixed: 'left' as any,
      render: (text: any, record: any) => {
        return (
          ........
        );
      }
    },
table表格设置:
<Table
            loading={loadingPageFlag}
            columns={columns}
            scroll={{ x: 600 }} /*滚动距离太大的话就不能按照设置列宽度的那样,会有出入,这个值按照情况设置*/
            dataSource={pageDatas}
            rowKey="id"
            rowSelection={rowSelection()}
            onChange={handleTableChange}
            pagination={{ pageSize: PageSize }}
          />
          

发现如果设置的scroll太大的话,比如我的之前设置为1600,发现如下图所示:这一列设置的是50,但是实际宽度超出50,
在这里插入图片描述
后来将scroll改为600后可以了
在这里插入图片描述

十八、文本域(计数方式:已输入/可再输入)

样式:
.text-area_box {
      position: relative;
      .ant-input {
        height: 121px;
        background: #ffffff;
        border: 1px solid #d9d9d9;
        border-radius: 3px;
      }
      .word_number {
        position: absolute;
        bottom: -22px;
        right: 0;
        color: #bbbbbb;
        font-size: 14px;
      }
    }
文本域(计数方式:已输入/可再输入,ant design默认是已输入/总数,
使用ant design默认的那种需要在textarea加上showCount,也不需要再额外配置样式了)
<Form.Item name="remark" label="备注">
                <TextArea
                  ref={refTextArea1}
                  maxLength={maxLength1}
                  className="textArea"
                  onChange={handleChangeArea1}
                  value={descript}
                />
              </Form.Item>
              <span className="word_number">
                {count1} / {maxLength1 - count1 >= 0 ? maxLength1 - count1 : 0}
              </span>

十九、table组件中的columns数据渲染失败,提示错误,加上dataIndex(ant design)

1、对于组件的使用:
table组件中的columns数据渲染失败,一直提示错误,后来加上了dataIndex列就可以了,
不知道为什么,在ant design中定义dataIndex: 列数据在数据项中对应的路径,支持通过数组查询嵌套路径
这个是和数据来源中提供的属性名会对应,所以我想着如果没有该属性就不写了,结果就不对了。
之前的一些表格是可以的,这个不知道为什么
data:
[
    { id: '1', price: '¥1,200', flag: 'price1' },
    { id: '2', price: '¥600', flag: 'price2' },
    { id: '3', price: '¥600', flag: 'price3' }
  ]
报出错误:
Uncaught Error: Objects are not valid as a React child (found: object with keys {id, price, flag}). 
If you meant to render a collection of children, use an array instead.

二十、带有loading的select

带有loading的select
import React, { useEffect } from 'react';
import { Select, Spin } from 'antd';
import { useRequest, request } from 'umi';
import { useImmer } from 'use-immer';

export interface Employee {
  id: number;
  employeeName: string;
  employeeCode: string;
}

const { Option } = Select;

interface IProps {
  mode?: string;
  onChange?(value?: any, options?: any, record?: any): void;
  dataLoadFinish?(data: Employee[]): void;
  valueKey?: 'id' | 'code';
  list?: Employee[];
  params?: {
    isSystemOperator?: number; // 是否是系统操作员1.是2.不是
    employeeStatus?: number; // 1.入职2.离职
  };
  value?: string | string[] | number | number[];
}

const EmployeeSelect: React.FC<IProps> = props => {
  const { mode, onChange = () => {}, value, valueKey = 'id', list, params } = props;
  const [employeeList, setEmployeeList] = useImmer<Employee[]>([]);
  const [fetching, setFetching] = useImmer<boolean>(false);

  useEffect(() => {
    if (list && list.length > 0) {
      setEmployeeList(() => list);
    }
  }, [list && list.length]);

  const getReq = (employeeCodeOrName?: string) => {
    return request('xxx/xxx/xxxxx/xxxxxx', {
      method: 'post',
      data: {
        ...params,
        employeeCodeOrName
      }
    });
  };

  const { run } = useRequest(getReq, {
    debounceInterval: 800,
    manual: true,
    onSuccess: data => {
      setEmployeeList(() => data);
      setFetching(() => false);
    }
  });

  const onSearch = (val: string) => {
    setEmployeeList(() => []);
    setFetching(() => true);
    run(val);
  };

  const onFocus = () => {
    if (employeeList.length <= 0) {
      setFetching(() => true);
      run();
    }
  };

  return (
    <Select
      showSearch
      allowClear
      mode={mode as any}
      value={value}
      onSearch={onSearch}
      onChange={(val, options) => {
        const employee = employeeList.find(
          item => item[valueKey === 'code' ? 'employeeCode' : 'id'] === val
        );
        onChange(val, options, employee);
      }}
      filterOption={false}
      optionLabelProp="label"
      placeholder="请输入员工名称或编码"
      notFoundContent={fetching ? <Spin size="small" /> : null}
      onFocus={onFocus}
    >
      {employeeList?.map(item => (
        <Option
          value={item[valueKey]!}
          label={`${item.employeeCode}\\${item.employeeName}`}
          key={item.employeeCode}
        >
          <div>
            <span style={{ marginRight: '20px' }}>{item.employeeCode}</span>
            <span>{item.employeeName}</span>
          </div>
        </Option>
      ))}
    </Select>
  );
};

export default React.memo(EmployeeSelect);

二十一、刷屏

  1. 先复制一个内容,然后执行ctrl+v,然后双击下面的vbs文件然后鼠标点击对应的人员聊天框即可
    on error resume next
    dim wsh,ye,path
    set wsh=createobject("wscript.shell")
    for i=1 to 10
    wscript.sleep 200
    wsh.appactivate("老弟") // 这个是备注名
    wsh.sendkeys "^v"
    wsh.sendkeys i
    wsh.sendkeys "%s"
    next

二十二、ant design相关

1、form相关

1.1 form.list的使用、 Form.Item 下的子组件可以获取Form.Item传的默认参数(value, id, onChange)

组件AA
import React from 'react';
import { Container } from './style';

interface IProps {
  value?: any;
}

const AA: React.FC<IProps> = props => {
  console.log(props, '参数');
  const { value } = props;
  return (
    <Container>
      <div>{value}</div>
    </Container>
  );
};

export default React.memo(AA);

  useEffect(() => {
    form.setFieldsValue({
      users: [
        { nickName: 'name1', age: 20 },
        { nickName: 'name2', age: 24 }
      ]
    });
  }, []);
  
			  <Form.Item name="aa" label="呼哈">
                <AA />
              </Form.Item>
              <Form.List name={['users']}>
                {fields =>
                  fields.map(field => (
                    <React.Fragment key={field.key}>
                      <Form.Item name={[field.name, 'nickName']} label="名字">
                        <input />
                      </Form.Item>
                      <Form.Item name={[field.name, 'age']} label="年龄">
                        <AA />
                      </Form.Item>
                    </React.Fragment>
                  ))
                }
              </Form.List>


在这里插入图片描述
根据打印结果可知:
1、name 字段名称,会作为字段 id 前缀使用,如上图的id: ‘users_0_age’
2、Form.Item中调用组件AA显示内容,传给AA的参数中发现默认的有value: 24, id: “users_1_age”, onChange: ƒ

1.2 可以用于form.item校验的自定义规则

import { message } from 'antd';
import { isNull } from './utils';

const Pattern = {
  email: {
    reg: /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+(com|cn|net|hotmail)$/,
    message: '邮箱格式不正确'
  },
  mobile: { reg: /^1[3456789]\d{9}$/, message: '手机号格式不正确' },
  letterOrNum: { reg: /^[0-9a-zA-Z]{1,}$/ },
  idCard: { reg: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证格式不正确' }
};

/**
 * 验证
 */
const validator = {
  required: (value: any, msg?: string) => {
    if (isNull(value)) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },

  min: (value: number, min: number, msg?: string) => {
    if (value < min) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },

  max: (value: number, max: number, msg?: string) => {
    if (value > max) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },
  /**
   * 大于等于0的整数
   */
  integer: (value: any, msg?: string) => {
    const reg: any = /^([1-9]\d{0,}|0)$/;
    if (!reg.test(value)) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },
  /**
   *最多保留8位小数
   */
  decimal8: (value: any, msg?: string) => {
    const reg = /(^(-)?[1-9]([0-9]+)?(\.[0-9]{1,8})?$)|(^(0){1}$)|(^(-)?[0-9]\.[0-9]([0-9])?$)/;
    if (!reg.test(value)) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },
  /**
   * 数字或者字母
   * @param value
   * @param msg
   */
  letterOrNum: (value: any, msg?: string) => {
    const reg = /^[0-9a-zA-Z]{1,}$/;
    if (!reg.test(value)) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },
  email: (value: any, msg?: string) => {
    const { reg } = Pattern.email;
    if (!reg.test(value)) {
      msg && message.error(msg);
      return false;
    }
    return true;
  },
  isNumOrLetterOrSpecial: (
    rule: any,
    value: any,
    callback: any,
    title: string,
    min?: number,
    max?: number
  ) => {
    // 只能是字母、数字 、特殊字符
    const oNumber = new RegExp(/\d/);
    const oLetter = new RegExp(/[a-zA-Z]/);
    const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';
    if (min !== undefined && value.length < min) {
      callback(`${title}不能小于${min}位!`);
      return;
    }
    if (max !== undefined && value.length > max) {
      callback(`${title}不能大于${max}位!`);
      return;
    }

    try {
      [...value].forEach(val => {
        if (!(oNumber.test(val) || oLetter.test(val) || oSpecial.indexOf(val) >= 0)) {
          throw new Error();
        }
      });
    } catch (e) {
      callback(`${title}只能是字母、数字、特殊字符!`);
    }
    callback();
  }
};

export { validator, Pattern };

1.3 form.item中字段校验

                  <Form.Item
                    name="advertiserName"
                    label="广告主名称"
                    rules={[
                      {
                        validator: (rule, value, callback) => {
                          if (!value) {
                            callback('广告主名称必填!');
                            return;
                          }
                          if (value.length > 50) {
                            callback('广告主名称不能超过50位');
                            return;
                          }
                          callback();
                        }
                      }
                    ]}
                  >
                    <Input
                      onChange={() => {
                        setAdNameOnlyFlag(() => false);
                      }}
                    />
                  </Form.Item>
                  
				// 只能是字母、数字、特殊字符
                  <Form.Item
                    name="loginPassword"
                    label="A端密码"
                    rules={[
                      {
                        validator: (rule, value, callback) => {
                          const oNumber = new RegExp(/\d/);
                          const oLetter = new RegExp(/[a-zA-Z]/);
                          const oSpecial = '.~!@#$%^&*()_+=-{}|:<>?,./[]-;\\"';

                          if (!value) {
                            callback('A端密码必填!');
                            return;
                          }

                          if (value.length < 8) {
                            callback('A端密码不能小于8位!');
                            return;
                          }
                          if (value.length > 31) {
                            callback('A端密码不能大于31位!');
                            return;
                          }

                          try {
                            [...value].forEach(val => {
                              if (
                                !(
                                  oNumber.test(val) ||
                                  oLetter.test(val) ||
                                  oSpecial.indexOf(val) >= 0
                                )
                              ) {
                                throw new Error();
                              }
                            });
                          } catch (e) {
                            callback('A端密码只能是字母、数字、特殊字符!');
                          }
                          callback();
                        }
                      }
                    ]}
                  >
                    <Input.Password />
                  </Form.Item>

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.4 update+dependencies

当选择支持抓取入库的时候,抓取方式需要必选
<Form.Item shouldUpdate noStyle>
            {() => (
              <Form.Item
                name="grabMethod"
                label="抓取方式:"
                dependencies={['isGrab']}
                rules={[
                  {
                    required: form?.getFieldValue('isGrab') === 1,
                    message: ' '
                  },
                  ({ getFieldValue }) => ({
                    validator(_, value) {
                      if (getFieldValue('isGrab') !== 1 || (value && value.length)) {
                        return Promise.resolve();
                      }
                      return Promise.reject(new Error('请选择抓取方式!'));
                    }
                  })
                ]}
              >
                <Checkbox.Group
                  options={checkboxItems}
                  onChange={handleSelectValue}
                  className="grab"
                />
              </Form.Item>
            )}
          </Form.Item>

<Form.Item
            name="isGrab"
            label="是否支持抓取入库:"
            initialValue={1}
            rules={[{ required: true, message: '请选择是否支持抓取入库' }]}
          >
            <Radio.Group>
              <Radio value={1}></Radio>
              <Radio value={2}></Radio>
            </Radio.Group>
          </Form.Item>

2、InputNumber

带有两位小数的
<InputNumber
                      min={0.01}
                      step={0.01}
                      formatter={(value: any) =>
                        `${value}`
                          .replace(/\B(?=(\d{3})+(?!\d))/g, ',')
                          .replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
                      }
                      parser={(value = '') =>
                        value.replace(/\$\s?|(,*)/g, '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
                      }
                      precision={2}
                      style={{ width: '100%' }}
                      /* onBlur={onBlur} */
                    />
格式化输入带有%
 <InputNumber
                      className="clear_input_disable"
                      disabled={type === 3}
                      placeholder="请输入"
                      min={0}
                      max={100}
                      parser={(val: string | undefined) => {
                        const numberValue = Number.parseInt(val?.replace('%', '') ?? '', 10);
                        return numberValue ? Number(numberValue) : '';
                      }}
                      formatter={val => `${val}%`}
                    />

# 二十三、格式化数字金额用逗号隔开保留n位小数

```typescript
/**
 * 格式化数字金额用逗号隔开保留n位小数
 * @param s 数字金额
 * @param n 几位小数
 */
export const fmoney = (s: number | string, n: number) => {
  if (!s) {
    return `¥0.${new Array(n).fill(0).join('')}`;
  }
  n = n > 0 && n <= 20 ? n : 2;
  s = `${parseFloat(`${s}`.replace(/[^\d\\.-]/g, '')).toFixed(n)}`;
  const l = s
    .split('.')[0]
    .split('')
    .reverse();
  const r = s.split('.')[1];
  let t = '';
  // eslint-disable-next-line no-plusplus
  for (let i = 0; i < l.length; i++) {
    t += l[i] + ((i + 1) % 3 === 0 && i + 1 !== l.length ? ',' : '');
  }
  // eslint-disable-next-line consistent-return
  return `¥${t
    .split('')
    .reverse()
    .join('')}.${r}`;
};

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值