不忘初心,不负韶华,砥砺前行!
分页: 1/242 第一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]
Jan 7
npm install lottie-web
https://github.com/airbnb/lottie-web
Tags:
Jan 7
Monorepo 是管理项目代码的一个方式,是一种代码组织的概念,指在一个项目仓库 (repo) 中管理多个模块/包 (package),不同于常见的每个模块建一个 repo。

目前有不少大型开源项目采用了这种方式,如 Babel:

How is the repo structured?
The Babel repo is managed as a monorepo that is composed of many npm packages.
还有 create-react-app, react-router 等。可以看到这些项目的第一级目录的内容以脚手架为主,主要内容都在 packages 目录中、分多个 package 进行管理。

├── packages
|   ├── pkg1
|   |   ├── package.json
|   ├── pkg2
|   |   ├── package.json
├── package.json

monorepo 最主要的好处是统一的工作流和Code Sharing。比如我想看一个 pacakge 的代码、了解某段逻辑,不需要找它的 repo,直接就在当前 repo;当某个需求要修改多个 pacakge 时,不需要分别到各自的 repo 进行修改、测试、发版或者 npm link,直接在当前 repo 修改,统一测试、统一发版。只要搭建一套脚手架,就能管理(构建、测试、发布)多个 package。

不好的方面则主要是 repo 的体积较大。特别是,因为各个 package 理论上都是独立的,所以每个 package 都维护着自己的 dependencies,而很大的可能性,package 之间有不少相同的依赖,而这就可能使install时出现重复安装,使本来就很大的 node_modues 继续膨胀(我称这为「依赖爆炸」...)。

基于对以上的理解,我认为当项目到一定的复杂度,需要且可以划分模块、但模块间联系紧密的,比较适合用 monorepo 组织代码。

目前最常见的 monorepo 解决方案是
Lerna https://github.com/lerna/lerna
yarn 的 workspaces 特性https://classic.yarnpkg.com/en/docs/workspaces/
其中,lerna 是一个独立的包,其官网的介绍是:

a tool that optimizes the workflow around managing multi-package repositories with git and npm.
上面提到的 Babel, create-react-app 等都是用 lerna  进行管理的。在项目 repo 中以lerna.json声明 packages 后,lerna 为项目提供了统一的 repo 依赖安装 (lerna bootstrap),统一的执行 package scripts (lerna run),统一的 npm 发版 (lerna publish) 等特性。对于「依赖爆炸」的问题,lerna 在安装依赖时提供了--hoist选项,相同的依赖,会「提升」到 repo 根目录下安装,但……太鸡肋了,lerna 直接以字符串对比 dependency 的版本号,完全相同才提升,semver 约定在这并不起作用。

具体的使用方法移步 Lerna 官网:https://lerna.js.org

而使用 yarn 作为包管理器的同学,可以在 package.json 中以 workspaces 字段声明 packages,yarn 就会以 monorepo 的方式管理 packages。相比 lerna,yarn 突出的是对依赖的管理,包括 packages 的相互依赖、packages 对第三方的依赖,yarn 会以 semver 约定来分析 dependencies 的版本,安装依赖时更快、占用体积更小;但欠缺了「统一工作流」方面的实现。

yarn 官网对 workspace的详细说明:Workspaces | Yarn

lerna 和 yarn-workspace 并不是只能选其一,大多 monorepo 即会使用 lerna 又会在 package.json 声明 workspaces。这样的话,无论你的包管理器是 npm 还是 yarn,都能发挥 monorepo 的优势;要是包管理是 yarn ,lerna 就会把依赖安装交给 yarn 处理。
Tags: ,
Dec 20


通过 flush:post可以避免副作用,在DOM更新后运行副作用,确保模板引用与DOM保持同步,并引入正确的元素。

Tags: , ,
Dec 20


Dec 16
Dec 16

import type { App, Plugin } from 'vue';
export const withInstall = <T>(component: T, alias?: string) => {
  const comp = component as any;
  comp.install = (app: App) => {
    app.component(comp.name || comp.displayName, component);
    if (alias) {
      app.config.globalProperties[alias] = component;
    }
  };
  return component as T & Plugin;
};




import { withInstall } from '/@/utils';
import appLogo from './src/AppLogo.vue';
export const AppLogo = withInstall(appLogo);
Dec 16

props: {
      /**
       * Specified role is visible
       * When the permission mode is the role mode, the value value can pass the role value.
       * When the permission mode is background, the value value can pass the code permission value
       * @default ''
       */
      value: {
        type: [Number, Array, String] as PropType<RoleEnum | RoleEnum[] | string | string[]>,
        default: '',
      },
    },



export const buttonProps = {
  color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) },
  loading: { type: Boolean },
  disabled: { type: Boolean },
  /**
   * Text before icon.
   */
  preIcon: { type: String },
  /**
   * Text after icon.
   */
  postIcon: { type: String },
  /**
   * preIcon and postIcon icon size.
   * @default: 14
   */
  iconSize: { type: Number, default: 14 },
  onClick: { type: Function as PropType<(...args) => any>, default: null },
};

Dec 16

<script lang="tsx">
  import { defineComponent, ref, unref } from 'vue';
  import { Tooltip } from 'ant-design-vue';
  import { SearchOutlined } from '@ant-design/icons-vue';
  import AppSearchModal from './AppSearchModal.vue';
  import { useI18n } from '/@/hooks/web/useI18n';

  export default defineComponent({
    name: 'AppSearch',
    setup() {
      const showModal = ref(false);
      const { t } = useI18n();

      function changeModal(show: boolean) {
        showModal.value = show;
      }

      return () => {
        return (
          <div class="p-1" onClick={changeModal.bind(null, true)}>
            <Tooltip>
              {{
                title: () => t('common.searchText'),
                default: () => <SearchOutlined />,
              }}
            </Tooltip>
            <AppSearchModal onClose={changeModal.bind(null, false)} visible={unref(showModal)} />
          </div>
        );
      };
    },
  });
</script>
Dec 16
Tags: , , , , ,
Dec 14
就是xhr.abort(),不需要服务器确认。
axios/blob/master/lib/cancel/CancelToken.js#L22
axios/blob/master/lib/adapters/xhr.js#L153
the-abort()-method

在开发中,经常会遇到接口重复请求导致的各种问题。

对于重复的get请求,会导致页面更新多次,发生页面抖动的现象,影响用户体验。

对于重复的post请求,会导致在服务端生成两次记录(例如生成两条订单记录)。

如果当前页面请求还未响应完成,就切换到了下一个路由,那么这些请求直到响应返回才会中止。

无论从用户体验或者从业务严谨方面来说,取消无用的请求确实是需要避免的。

当然我们可以通过页面loading来避免用户进行下一次的操作,但本文只讨论单纯的如何取消这些无用的请求。

axios 的 cancelToken
axios是一个主流的http请求库,它提供了两种取消请求的方式。

通过axios.CancelToken.source生成取消令牌token和取消方法cancel

需要注意的是在catch中捕获异常时,应该使用axios.isCancel()判断当前请求是否是主动取消的,以此来区分普通的异常逻辑。
封装取消请求逻辑
上面有两种取消请求,用哪种都是可以的,这里使用第二种。

取消请求主要有两个场景:

当请求方式method,请求路径url,请求参数(get为params,post为data)都相同时,可以视为同一个请求发送了多次,需要取消之前的请求
当路由切换时,需要取消上个路由中未完成的请求
我们封装几个方法:

Map是ES6中一种新型的数据结构,本身提供了诸多方法,方便操作,适合当前场景。如果不熟悉的可以查看ECMAScript 6 入门。

在给config.cancelToken赋值的时候,需要判断当前请求是否已经在业务代码中使用了cancelToken

qs是一个专门用来转换对象和字符串参数的库,最初是由 TJ 创建并维护的,也是axios推荐使用的参数序列化库。这里我们的目的只是单纯的将参数对象转换为字符串方便拼接。

Map结构默认部署了Symbol.iterator属性,可以使用for...of循环直接获取键名和键值,当然你也可以使用for...in循环。

在 axios 拦截器中使用
主要的方法已经写好了,只需要添加到axios拦截器中就可以了。
分页: 1/242 第一页 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 下页 最后页 [ 显示模式: 摘要 | 列表 ]