211130随笔


不想用return
// 一般我们render视图喜欢写无状态组件,一般需要return视图

// 如果不想用return了,可以 () => () 简介写法

    const renderEmpty = () => (
        <div style={{textAlign: 'center', cursor: 'pointer'}}>
            <div className="image-style">
                <Image
                    src={EmptyPng}
                    preview={false}
                    alt="当前还没有任务,请新建任务"
                    // fallback="http://..."
                />
            </div>
            <p className="image-alt">当前还没有任务,请新建任务</p>
        </div>
    );
antd typescript报错
 
  // 通过这种解构的方式给Table赋值,会报 属性“pagination”的类型不兼容。

  // 不能将类型“boolean”分配给类型“false | TablePaginationConfig | undefined”。
  const tableConfig = {
        columns: columns,
        dataSource: data,
        pagination: false, // 改为 pagination: false as false 即可
    };
如果不确定一个值的类型,用map、length怕报错的话
// 就用

data?.length 
好用的前端枫叶,不用给定初次调用的默认值
// 前端分页
// effect 里就写 getPageData(1)
// change里写 getPageData(page)

const getPageData = (cur: number) => {
    const copyData = JSON.parse(JSON.stringify(data));
    const showData = copyData.slice((cur - 1) * pagesize, cur * pagesize);
    setData(data);
};
泛型数组

export interface ColoumnType<T> { // 配置类型     定义
    title: string | ReactElement,
    dataIndex: T,
    render?: (value: string) => ReactElement
}

const columns : ColoumnType<string>[] = [...]  // 使用

// 凡是使用到了ColoumnType接口的地方,都要为泛型指定类型。
                                         
useRef的妙用
/**
 * useState 在某种程度上来说是异步的,也就是说我们在改变状态后并不能拿到他最新的值(比如在同一个函数
 * 中使用setState更新值,然后再打印这个值,打印的就会是上一次的值,而并非改变后的值。),
 * 而有的时候我们又必须使用他改变后最新的值,以此最新的值为基本进行组件接下来的计算,
 * 如果这个值不能是最新的,那么计算就是错误的!***这时,我们需要useRef。
 * 
 * useRef 生成的对象在组件整个生命周期内保持不变
 * 用useRef来存储值,改变值,拿到的永远都是最新的值。
*/

// function
{
    sortRef.current = !sortRef.current;
  // creatCompare要求第二个参数的值必须是改变后最新的值
  let sortData = copyAllTranslate.sort(
      creatCompare('timer', sortRef.current) // item 的 timer
  );
}

// 另一个useState异步的案例

const [current, setCurrent] = useState<number>(1);
const getPageDatas = (cur: number) => { // cur onchange函数传给 getPageDatas改变后的页码
    const copyDatas = JSON.parse(JSON.stringify(data));
    if(cur === 1){
      const showData = copyDatas.slice((cur - 1) * pagesize, cur * pagesize);
      setData(data);
    }
    // 这里拿到的值一直是current = 1, 所以一直只会截取前10条
    const showData = copyDatas.slice((current - 1) * pagesize, current * pagesize);
    setData(data);
};

// 解决方案 :去除不必要的代码,不再依赖于useState保存的状态来计算;页码改变的数据的计算,
// ***全部依赖于onChange 传入的最新值!,
// 见以上前端枫叶。

// 在某些时候,state用来更新视图就好,至于精确的运算的依赖值,我们就使用useRef

// useRef还可以配合forwrodRef获取函数组件实例

// useRef和useState的区别,实现原理。
ReactElement
ReactElement 是JSX.Element的父级,可以相互赋值(类型)
sort排序封装

let sortData = copyAllTranslate.sort(
    creatCompare('timer', sortRef.current) // item 的 timer
);

const creatCompare = (propertyName: string, type: boolean) => {
    return function (obj1: GetDataType, obj2: GetDataType): number {
        let value1 = obj1[propertyName];
        let value2 = obj2[propertyName];
        return type ? value1 - value2 : value2 - value1; // type 是true 就是升序,反之倒序
    };
};

// 排序依赖值,见上一项useRef
antd组件的渲染父级别

/* 使用 as HTMLElement 为 triggerNode.parentNode 指定类型使其不报错
 * 不写as 会报 : 不能将类型“ParentNode | null”分配给类型“HTMLElement”
 * antd ts  getPopupContainer的返回类型就是 HTMLElement,
 * 以后若出现此类错误可借鉴次方法
 * getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
 */

getPopupContainer={triggerNode => triggerNode.parentNode as HTMLElement}
自定义tab
/**
 * antd tab 调样式非常麻烦,自己写
 * 首先准备一个数组,数组里每一个对象都有key 和title,
 * 然后在组件中渲染,在渲染的div上加一个onClick, 
 * 在事件函数里setChooseIndex ,这个 state的初始值取数组第一个对象的key
 * 在一个render里,写不同的if为key的情况下return 不同的无状态组件。
 * 这样一个tab就写好了。
*/
其他

antd tabel 的colmuns只要最后传给tabel就好了,写在哪本身不重要。写在父组件传给子都没问题。

表格th若是有特殊样式,一些图标对应一些操作、下拉框什么的,

可以在colmuns的title写一个函数 as ReactElement防止报错

title: getTitleIcon('任务创建时间') as ReactElement,
  
需要下拉框的,给一个 Dropdown,节点会挂在th(ant-table-cell) 上,menu的父级会与 Dropdown包裹的div同级,

而不是挂在body上,挂在body上像datav这样的框架是会出问题的。
判断数组类型
// 数组方法前面加判断最好用 Array.isArray()

// 今天因为父组件传过来的是{},导致使用slice方法报错了,几经排查,才排查到这里。

// 问题: 太相信typescripe传过来的类型了

// ***也要注音非空判断之外的数据类型,哪怕用了ts
let obj = {}
undefined
obj.slice(1)
VM635410:1 Uncaught TypeError: obj.slice is not a function
at <anonymous>:1:5

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录