首页 > 编程语言 >源码共读 | tdesign-vue 初始化组件

源码共读 | tdesign-vue 初始化组件

时间:2023-04-07 18:33:12浏览次数:59  
标签:tdesign vue const 函数 文件 component toBeCreatedFiles 源码 组件

前言

Tdesign-vue 是一由腾讯开源的 Vue.js 组件库。我们知道,这些大型的组件库业务覆盖面很广,基本都包含了很多组件,很多组件包含了一些通用性代码,如果每开发一个组件,都去把这些通用性代码复制出来,无疑是非常繁琐的,那么作者在开发这些组件时是如何做的呢?

学习目标:

  • 新增组件: npm run init [组件名]
  • 删除组件:npm run init [组件名] del

资源:

源码

找到用于初始化组件的源码,如图:

<img src="https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6fb2ece2680442f4bfe46c7ec0ebe771~tplv-k3u1fbpfcp-watermark.image?" alt="" width="30%" />

脚本的入口

function init() {
  const [component, isDeleted] = process.argv.slice(2);
  if (!component) {
    console.error('[组件名]必填 - Please enter new component name');
    process.exit(1);
  }
  const indexPath = path.resolve(cwdPath, 'src/index.ts');
  const toBeCreatedFiles = config.getToBeCreatedFiles(component);
  if (isDeleted === 'del') {
    deleteComponent(toBeCreatedFiles, component);
    deleteComponentFromIndex(component, indexPath);
  } else {
    addComponent(toBeCreatedFiles, component);
    insertComponentToIndex(component, indexPath);
  }
}

函数接受两个参数: Component 和 isDelete。

  • component 参数是要创建或删除的组件的名称
  • isDelete 参数是一个标志,指示是否应该创建或删除该组件。

函数首先检查是否提供了组件参数。如果未提供,则向控制台输出一条错误消息,函数退出。否则,函数将继续执行。

之后,该函数获取需要创建或删除的文件列表,以便添加或删除组件。然后检查 isDelete 参数的值,以确定是否应该创建或删除组件。如果 isDelete 等于 del,则函数调用 deleteComponent 函数来删除组件,然后调用 deleteComponentFromIndex 函数来从项目的索引文件中删除组件。如果 isDelete 不等于 del,则函数调用 addComponent 函数创建组件,然后调用 insertComponentToIndex 函数将组件添加到项目的索引文件中。

创建目录

function addComponent(toBeCreatedFiles, component) {
  // At first, we need to create directories for components.
  Object.keys(toBeCreatedFiles).forEach((dir) => {
    const _d = path.resolve(cwdPath, dir);
    fs.mkdir(_d, { recursive: true }, (err) => {
      if (err) {
        utils.log(err, 'error');
        return;
      }
      console.log(`${_d} directory has been created successfully!`);
      // Then, we create files for components.
      const contents = toBeCreatedFiles[dir];
      contents.files.forEach((item) => {
        if (typeof item === 'object') {
          if (item.template) {
            outputFileWithTemplate(item, component, contents.desc, _d);
          }
        } else {
          const _f = path.resolve(_d, item);
          createFile(_f, '', contents.desc);
        }
      });
    });
  });
}

该函数接受两个参数: toBeCreatedFilescomponent

  • toBeCreatedFiles 参数是一个对象,它包含为了添加组件而需要创建的目录和文件的列表
  • component 参数是要创建的组件的名称。

函数首先迭代 toBeCreatedFiles 对象的键,这些键表示需要创建的目录。对于每个目录,该函数使用 fs.mkdir 函数创建目录。如果目录已经存在,则函数将错误消息记录到控制台。

创建目录后,函数将遍历需要为组件创建的文件列表。如果文件是包含模板属性的对象,则函数调用 outputFileWithTemplate 函数以使用模板创建文件。如果文件不是具有模板属性的对象,则函数调用 createFile 函数创建空文件。

内容写入

function insertComponentToIndex(component, indexPath) {
  const upper = getFirstLetterUpper(component);
  // last import line pattern
  const importPattern = /import.*?;(?=\n\n)/;
  // components pattern
  const cmpPattern = /(?<=const components = {\n)[.|\s|\S]*?(?=};\n)/g;
  const importPath = getImportStr(upper, component);
  const desc = '> insert component into index.ts';
  let data = fs.readFileSync(indexPath).toString();
  if (data.match(new RegExp(importPath))) {
    utils.log(`there is already ${component} in /src/index.ts`, 'notice');
    return;
  }
  // insert component at last import and component lines.
  data = data.replace(importPattern, (a) => `${a}\n${importPath}`).replace(cmpPattern, (a) => `${a}  ${upper},\n`);
  fs.writeFile(indexPath, data, (err) => {
    if (err) {
      utils.log(err, 'error');
    } else {
      utils.log(`${desc}\n${component} has been inserted into /src/index.ts`, 'success');
    }
  });
}

这个函数接受两个参数: componentindexPath

  • component 参数是要插入的组件的名称
  • indexPath 参数是项目索引文件的路径。

该函数首先定义两个正则表达式: importPatterncmpPattern

  • importPattern 正则表达式用于匹配索引文件中的最后一个 import 语句
  • cmpPattern 正则表达式用于匹配索引文件中的组件列表。

接下来,函数使用 getImportStr 函数,使用变量(组件名称的大写版本)为新组件生成导入语句。

然后,该函数使用 fs.readFileSync 函数读取索引文件的内容,并在文件中搜索 importPatterncmpPattern 正则表达式。如果文件中已经存在新组件的 import 语句,则函数将消息记录到控制台并返回。否则,该函数将最后一个 import 语句替换为新 import 语句,并将组件列表替换为包含新组件的新组件列表。最后,函数使用 fs.writeFile 函数将修改后的索引文件内容写回文件。

删除目录

function deleteComponent(toBeCreatedFiles, component) {
  const snapShotFiles = getSnapshotFiles(component);
  const files = Object.assign(toBeCreatedFiles, snapShotFiles);
  Object.keys(files).forEach((dir) => {
    const item = files[dir];
    if (item.deleteFiles && item.deleteFiles.length) {
      item.deleteFiles.forEach((f) => {
        fs.existsSync(f) && fs.unlinkSync(f);
      });
    } else {
      utils.deleteFolderRecursive(dir);
    }
  });
  utils.log('All radio files have been removed.', 'success');
}

该函数接受两个参数: toBeCreatedFiles 和 Component。

  • toBeCreatedFiles 参数是一个包含与组件关联的目录和文件列表的对象
  • component参数是要删除的组件的名称。

该函数首先调用 getSnapshoFiles 函数以获取与组件关联的快照文件列表。然后,它使用 Object.sign 函数将该列表与 toBeCreatedFiles 对象合并。

接下来,函数迭代合并对象的键,这些键表示需要删除的目录和文件。对于每个键,该函数检查是否设置了关联值的 deleteFiles 属性。如果是,函数将遍历文件列表并使用 fs.unlinkSync 函数删除它们。如果未设置 deleteFiles 属性,该函数将调用 deleteFolderRecursive 函数以删除整个目录及其所有内容。

删除导入语句

function deleteComponentFromIndex(component, indexPath) {
  const upper = getFirstLetterUpper(component);
  const importStr = `${getImportStr(upper, component)}\n`;
  let data = fs.readFileSync(indexPath).toString();
  data = data.replace(new RegExp(importStr), () => '').replace(new RegExp(`  ${upper},\n`), '');
  fs.writeFile(indexPath, data, (err) => {
    if (err) {
      utils.log(err, 'error');
    } else {
      utils.log(`${component} has been removed from /src/index.ts`, 'success');
    }
  });
}

该函数接受两个参数: component 和 indexPath。

  • component参数是要删除的组件的名称
  • indexPath 参数是项目索引文件的路径。

该函数首先使用 getImportStr 函数,使用变量(组件名称的大写版本)为组件生成 import 语句。然后,它使用 fs.readFileSync 函数读取索引文件的内容,并在文件中搜索 import 语句和组件名。

如果找到 import 语句或组件名称,函数将使用 String.place 函数将其替换为空字符串。最后,函数使用 fs.writeFile 函数将修改后的索引文件内容写回文件。如果在此过程中发生错误,该函数将一条错误消息记录到控制台。否则,它将记录一条成功消息,指示组件已从索引文件中删除。

总结

通过本次章节的学习,学习到了动态修改文件内容以及根据模板生成组件文件的方式。

标签:tdesign,vue,const,函数,文件,component,toBeCreatedFiles,源码,组件
From: https://blog.51cto.com/codeniu/6176472

相关文章

  • Mac Apple 芯片运行 Vue 项目中 node-sass 转为 sass 遇到的问题记录,node-sass 替换成
    背景:前段时间因为某些原因将window笔记本换成MacM1pro,然后运行项目的时候发现高于node12版本的项目中不支持node-sass。记录下解决相关问题之后的记录......
  • Jenkins Vue Windows(FreeSSHd)整合
      创建项目第一次创建执行一次如下的代码。#进入Jenkins工作空间下hxkj项目目录cd/root/.jenkins/workspace/pc_back#下面的命令只需要执行一次,后续可以删除####npm切换为淘宝源npmconfigsetregistryhttp://registry.npm.taobao.org/#安装yarnnpmiyarn......
  • vue3学习第二课:组件和父组件的传递数据给子组件方式props
    1,在conponents目录中新建header.vue<template><div><h1>这是头部组件</h1></div></template>2,在App.vue中添加<template><div><Header></Header><Main></Main><Foote......
  • 记录-VueJs中如何使用Teleport组件
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助在DOM结构相对比较复杂,层级嵌套比较深的组件内,需要根据相对应的模块业务处理一些逻辑,该逻辑属于当前组件但是从整个页面应用的视图上看,它在DOM中应该被渲染在整个vue应用外部的其他地方,不能影响组件的结构比......
  • 学习使用VUE3+Django+GraphQL实现简单的Blog网站
    这周每天花点时间学习使用VUE3+Django+GraphQL的使用,按照RealPython的网站的教程走了一遍,踩了一遍坑.Realpython上的教程使用的是Vue2的Vue-CLI模块,Vue本身已经进化到VUE3,并且推荐使用Vite代替Vue-CLI.我按照教程上的步骤将代码转化为VUE3+Vite+CompositionAPI模式.在这里......
  • VUE解决跨域的proxyTable
    找到问题:因为java服务运行在localhost:9001端口,vue运行在localhost:8080端口,不同端口存在跨域问题。所以我使用了反向代理处理。在vue.config.js里:proxyTable:{'/api':{target:'localhost:9001',//secure:true,changeOrigin:true,......
  • vue全家桶进阶之路29:Element Plus
    ElementPlus是一个用于Vue.js的UI组件库,为开发人员提供了一组可重用和可定制化的组件,用于构建现代Web应用程序。它是流行的ElementUI库的扩展,重点是提高性能和可访问性。ElementPlus包括广泛的组件,如按钮、表单、表格、对话框等。除了常规的UI组件外,ElementPlus还提供了一些......
  • Go-context源码解析
    首先我们简单的来看一个例子,如下:(学好这个例子,我们就可以说完全掌握住context了,并且能重构一个contextfuncmain(){ ctx,cancel:=context.WithCancel(context.Background()) ctxV:=context.WithValue(ctx,1,"HelloWorld") gofunc(ctxcontext.Context){ val:=......
  • vue生产环境跨域不生效
    vue生产环境跨域不生效开发环境跨域项目集成了百度地图的api,在接入ip查询地址等功能时返回跨域报错,所以使用vite配置文件配置服务代理来解决。传送门生成环境失效测试跟我说内网功能失效了,在验证了程序确实build到最新版本之后,使用f12发现了api访问的地址并没有代理到百度地图......
  • Python源码笔记——Python中的列表对象
    1.列表结构体#definePyObject_VAR_HEADPyVarObjectob_base;typedefstruct{PyObjectob_base;Py_ssize_tob_size;/*Numberofitemsinvariablepart*/}PyVarObject;typedefstruct{PyObject_VAR_HEAD/*Vectorofpointerstolistel......