Skip to content

10.24-15 日知识总结

知识点整理

知识点1 umi runtime报错

使用场景

INFO

项目多人开发的时候,别人可能更新的依赖,但是umi的runtime是一个临时文件,git pull 并不会更新,所以我们在项目启动的时候便会出现报错: D:/xxxx/xxx/xxx/node_modules/@umijs/runtime

操作

  1. src/.umi这个临时文件删掉
  2. 再次npm install

参考链接

node_modules/@umijs/runtime does not exist in container_[@umijs/runtime] load component failed error: modu-CSDN博客

知识点2 select里面的冒泡问题

使用场景

INFO

当我们需要在Select里面使用mode="multiple"并使用了自定义的dropDownRender的时候,当删除dropdownRender里的内容会导致,选中的options也删除

思路

因为当你选中_**dropdownRender**_里面的_**input**_,应该是里面的事件发生了冒泡,导致将_**multiple**_里面的_**options**_也被删除了。

这时候就应该使用_**e.stopPropagation()**_,但是又不是在_**onChange**_里面添加,因为,你想要去除的冒泡是,你按了_**Delete**_以后的冒泡,所以应该是在_**onKeyDown**_里面添加

代码

jsx
<Select
  placeholder="参数"
  mode="multiple"
  options={paramList[key]}
  dropdownRender={(menu) => (
    <div>
      {menu} // 展示选中内容
      <Divider style={{ margin: '4px 0' }} />
      <div style={{ display: 'flex', flexWrap: 'nowrap', padding: 8 }}>
        <Input.Search
          onKeyDown={(e) => {
            //  阻止多选的冒泡
            e.stopPropagation()
          }}
          style={{ flex: 'auto' }}
          onSearch={(value) => {
            addFieldCode(value, key)
          }}
          enterButton="添加"
          />
      </div>
    </div>
  )}
  >

参考链接:Select的组件 mode=“multiple” & 自定义dropdownRender时,删除dropdownRender里的内容会把选中的option删除 · Issue #28692 · ant-design/ant-design

知识点3 useState获取最新数据不及时

使用场景

INFO

useState获取数据是异步的,当你在同一个代码块里面,先set然后使用state拿到的状态其实是上一次的状态

思路

  1. 网上有一种说法就是将setState写为一个函数,这个函数是异步的,但是我发现比较难用
  2. 我直接将这个状态改为使用**useRef**来解决

如果你刻意地想要从某些异步回调中读取最新的 state,你可以用 一个 ref 来保存它,修改它,并从中读取。 ---官网

  1. 当然还有其他方法,比如使用useEffect,但是都没有Ref来的方便

参考链接:

使用useRef解决useState异步更新数据导致更新不及时问题_德墨忒尔的博客-CSDN博客

react useState 异步 数据获取不到 - 掘金

知识点4 vue遍历图片显示异常

使用场景

INFO

现在有一很多本地图片需要显示在页面上,但是在遍历的时候,路径是正确的,但是却获取不到图片

思路

  1. 将图片路径使用**require()**进行包裹,但是不知道为什么不可以,可能是导入的有问题
  2. 采用**vite**官网推荐的方法new URL(url, import.meta.url),url必须是静态的才可以使用
  3. 但是官网也强调了,这个方法不可以在SSR中使用,在**build.target**不支持**import.meta.url**

参考资料

  1. Vue3 + Vite 使用本地图片报错:require is not defined - 掘金
  2. Vite 静态资源处理为URL
  3. 为什么new URL(url, import.meta.url)本地开发可以打包后就不行?

知识点5 typescript类型

语法1

INFO

使用的是extends,继承的对象用分隔

typescript
interface a{}
interface b{}

interface c extends a,b{}

参考链接

TypeScript继承&多继承笔记

语法2

INFO

keyOf typeOf的使用

参考链接

详解 TypeScript 中的 typeof 和 keyof - 掘金

项目整理

场景1 国际化处理

描述

INFO

umi项目需要接入国际化,那么我们可以直接使用umi的插件

思路

  1. 首先在src中创建locales文件夹,里面放的是国际化的东西
bash
src
 - en-US.ts
  - zh-CN.ts
  1. 但是现在我们都是区分组件的,所以国际化最好也是区分组件来写,不要一股脑放在一个文件里面,然后再**en-US.ts/zh-CN.ts**文件里面直接调用即可
bash
src
 en-us
   - xxx.ts
    - xxx.ts
  zh-CN
    - xxx.ts
    - xxx.ts
 - en-US.ts
  - zh-CN.ts
typescript
import menu from "./en-US/menu";
import athena60 from "./en-US/athena60";
export default {
  "navBar.lang": "语言",
  "layout.user.link.help": "帮助",
  "layout.user.link.privacy": "隐私",
  "layout.user.link.terms": "条款",
  ...menu, // 直接导入即可
  ...athena60,
};
  1. 在组件里面使用,umi.formatMessage({id:xxx})来进行替换
typescript
import { Alert } from 'antd';
import { useIntl } from 'umi';

export default function Page() {
  const intl = useIntl();
  const msg = intl.formatMessage({
    id: 'welcome',
  });

  return <Alert message={msg} type="success" />;
};
  1. 这时候其实页面上基本都已经可以做到国际化了,但是你会发现memutab上面会存在问题

这边其实需要注意的是

所以我们在设置menu的时候,不能简单地直接修改menu中的name,而是直接修改router

typescript
// 根据当前语言环境(intl)配置路由对应语言的name值
// routes中routes和children字段都必须保留,并且props.routes的索引不能改变
function setRoutesOfIntl(arr: any) {
  arr.forEach((item: any) => {
    if (item.children) setRoutesOfIntl(item.children);
    if (item.name && item.key) {
      item.name = intl.formatMessage({ id: item.key });
    }
  });
  return arr;
}
// 省略一些代码
const newProps = {
  mAppProps,
  ...props,
  proLayoutConfig,
  scLayoutConfig,
  routes: setRoutesOfIntl(props.routes),
};

错误配置情况:

这样只是简单的修改了name,但是,umi去国际化匹配的时候,找的是routername,但是你的name并没有修改,依然是中文。

typescript
menu: {
  // 如何对menu进行国际化
  locale: true,
    async request(_: any, routes: MenuDataItem[]) {
    const userInfo = JSON.parse(localStorage.getItem("userInfo") || "0");
    // 没有登录
    // some useless codes
    // 有登录时
    const showMenuList: MenuDataItem[] = [];
    routes.forEach((item) => {
      if (
        item.key &&
        powerList.includes(item.key) &&
        item.children?.length
      ) {
        const temp = lodash.cloneDeep(item);
        // 直接修改menu的name
        if (temp.key) {
          temp.name = intl.formatMessage({
            id: temp.key,
          });
        }
        temp.children = item.children.filter(
          (val) => val.key && powerList.includes(val.key)
        );
        // 修改children的name
        temp.children.forEach((item) => {
          if (item.key) {
            item.name = intl.formatMessage({
              id: item.key,
            });
          }
        });
        showMenuList.push(temp);
      }
    });
    return new Promise((r) => {
      r(showMenuList);
    });
  },
},

代码

参考链接

如何为你的项目添加国际化配置(umi@3的国际化实践)_umi3 多语言-CSDN博客

布局与菜单

国际化

场景2

描述

INFO

思路

代码