自学内容网 自学内容网

vue cli源码学习之cli-plugin-vuex

vue cli源码学习之cli-plugin-vuex

jscodeshift库简介

jscodeshift 是一个用于代码转换的工具,特别适用于 JavaScript 和 TypeScript 代码。它基于 Recast 和 AST(抽象语法树)来解析、遍历和修改代码。jscodeshift 提供了一种编程方式来批量修改代码,常用于代码重构、升级库版本、自动化代码修复等场景。

jscodeshift 的主要功能

  1. 解析代码:将源代码解析为 AST,便于程序化地分析和修改代码结构。
  2. 遍历和查找:提供强大的 API 来遍历 AST,并查找特定的节点(如函数调用、变量声明等)。
  3. 修改代码:允许对 AST 进行修改,添加、删除或替换节点。
  4. 生成代码:将修改后的 AST 转换回代码字符串。

使用 jscodeshift

首先,你需要全局安装 jscodeshift:

npm install -g jscodeshift

创建转换脚本
编写一个 JavaScript 文件作为转换脚本。例如,以下是一个简单的转换脚本示例:

module.exports = (fileInfo, api) => {
  const j = api.jscodeshift;
  const root = j(fileInfo.source);

  // 查找所有的函数声明
  root.find(j.FunctionDeclaration)
    .forEach(path => {
      // 在这里对每个函数声明进行操作
      console.log(path.node.id.name);
    });

  return root.toSource();
};

运行转换
使用 jscodeshift 命令行工具运行转换脚本:

jscodeshift -t path/to/transform.js path/to/your/code

-t 指定转换脚本的路径。 path/to/your/code 是你想要转换的代码文件或目录。

常用 API

  • find:查找特定类型的节点。
  • replaceWith:替换找到的节点。
  • forEach:遍历找到的节点。
  • toSource:将 AST 转换回代码字符串。

generator\injectUseStore.js

使用 jscodeshift 库对 JavaScript 文件进行代码转换。具体来说,它查找并修改所有的 createApp 调用,向其添加 use(store) 方法调用。以下是代码的详细解释:
1. 导入和初始化:
j 是 jscodeshift 的一个实例,用于解析和转换代码。
root 是代码的根节点,表示整个代码文件的抽象语法树(AST)。

2. 查找 createApp 调用:
使用 root.find(j.CallExpression, …) 查找所有的函数调用表达式。
检查这些调用是否是 createApp 函数或 Vue.createApp 方法。

3. 替换 createApp 调用:
使用 appRoots.replaceWith 方法,将找到的 createApp 调用替换为调用 use(store)。
具体实现是将 createApp 调用节点转换为一个新的调用表达式,添加 use 方法和 store 参数。

4. 返回修改后的代码:
使用 root.toSource() 将修改后的 AST 转换回代码字符串并返回。
这段代码的主要目的是在 Vue 项目中自动为 createApp 调用添加 use(store),以便在应用中使用 Vuex 状态管理。

module.exports = (file, api) => {
  const j = api.jscodeshift
  const root = j(file.source)

  // 查找所有的 createApp 调用
  const appRoots = root.find(j.CallExpression, (node) => {
    // 检查是否是 createApp 函数调用
    if (j.Identifier.check(node.callee) && node.callee.name === 'createApp') {
      return true
    }

    // 检查是否是 Vue.createApp 方法调用
    if (
      j.MemberExpression.check(node.callee) &&
      j.Identifier.check(node.callee.object) &&
      node.callee.object.name === 'Vue' &&
      j.Identifier.check(node.callee.property) &&
      node.callee.property.name === 'createApp'
    ) {
      return true
    }
  })

  // 替换 createApp 调用,添加 use(store)
  appRoots.replaceWith(({ node: createAppCall }) => {
    return j.callExpression(
      j.memberExpression(createAppCall, j.identifier('use')),
      [j.identifier('store')]
    )
  })

  // 返回修改后的代码
  return root.toSource()
}

在 jscodeshift 中,j.identifier 是一个用于创建或匹配标识符(Identifier)节点的函数。标识符是编程语言中用于命名变量、函数、类等的名称。在 JavaScript 中,标识符可以是任何有效的变量名或函数名。

j.identifier 的作用

  • 创建标识符节点:当你需要在 AST 中插入一个新的标识符时,可以使用 j.identifier 来创建这个节点。例如,如果你想创建一个名为
    myVariable 的标识符节点,可以这样做:
  const myIdentifier = j.identifier('myVariable');

匹配标识符节点:在查找或遍历 AST 时,你可以使用 j.Identifier.check(node) 来检查某个节点是否是标识符节点。

generator\template-vue3\src\store\index.js

import { createStore } from 'vuex'

export default createStore({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

这个代码是一个使用 Vuex 创建的 Vue 3 状态管理存储(store)的基本模板。Vuex 是 Vue.js 的一个状态管理模式和库,通常用于管理应用程序的全局状态。
以下是代码的主要部分及其作用:

  • import { createStore } from ‘vuex’: 从 Vuex 库中导入 createStore函数,用于创建一个新的 Vuex 存储实例。
  • export default createStore({ … }): 创建并导出一个Vuex 存储实例。

这个实例包含以下几个部分:

  • state: 用于存储应用程序的状态数据
  • getters:用于从状态中派生出一些状态数据
  • mutations: 用于定义更改状态的同步方法
  • actions:用于定义可以包含异步操作的函数,这些函数最终会提交 mutation 来改变状态。
  • modules: 用于将存储分割成更小的模块

这个模板是一个起始点,开发者可以根据应用的需求来填充和扩展这些部分。

generator\index.js

module.exports = (api, options = {}, rootOptions = {}) => {
  // 向入口文件中注入 store 的导入语句
  api.injectImports(api.entryFile, `import store from './store'`)

  if (rootOptions.vueVersion === '3') {
    // 如果 Vue 版本是 3,转换脚本并扩展包依赖
    api.transformScript(api.entryFile, require('./injectUseStore'))
    api.extendPackage({
      dependencies: {
        vuex: '^4.0.0' // 使用 Vuex 4.0.0 版本
      }
    })
    // 渲染 Vue 3 的模板
    api.render('./template-vue3', {})
  } else {
    // 向根选项中注入 store
    api.injectRootOptions(api.entryFile, `store`)

    api.extendPackage({
      dependencies: {
        vuex: '^3.6.2' // 使用 Vuex 3.6.2 版本
      }
    })

    // 渲染 Vue 2 的模板
    api.render('./template', {})
  }

  if (api.invoking && api.hasPlugin('typescript')) {
    // 如果正在调用并且有 TypeScript 插件,转换文件
    /* eslint-disable-next-line node/no-extraneous-require */
    const convertFiles = require('@vue/cli-plugin-typescript/generator/convert')
    convertFiles(api)
  }
}

这段代码是一个用于 Vue CLI 插件的生成器模块,专门用于配置 Vuex(Vue 的状态管理库)。它根据项目的 Vue 版本和是否使用 TypeScript 插件来调整项目的配置。以下是代码的主要功能:

  1. 注入导入语句:
    向项目的入口文件中注入 import store from ‘./store’,以便在项目中使用 Vuex 的 store。

  2. 根据 Vue 版本进行配置:
    如果 rootOptions.vueVersion 是 ‘3’,则:
    转换入口文件的脚本以适应 Vue 3 的使用方式。
    扩展项目的 package.json,添加 Vuex 4.0.0 版本的依赖。
    渲染适用于 Vue 3 的模板。
    否则(即 Vue 版本为 2),则:
    向根选项中注入 store。
    扩展项目的 package.json,添加 Vuex 3.6.2 版本的依赖。
    渲染适用于 Vue 2 的模板。

3.TypeScript 支持:
如果正在调用生成器并且项目中有 TypeScript 插件,则调用 TypeScript 转换文件的功能,以确保 TypeScript 文件的正确配置。
这段代码的目的是在使用 Vue CLI 创建项目时,自动配置 Vuex 和相关的依赖项,以便开发者可以更方便地使用 Vuex 进行状态管理。

api.extendPackage 方法是 Vue CLI 插件 API 提供的一个功能,用于扩展或修改项目的 package.json 文件。通过这个方法,你可以在插件生成器中动态地添加、修改或删除项目的依赖、脚本、配置等。

添加依赖:可以向项目中添加新的依赖项或开发依赖项。
修改脚本:可以添加或修改 npm 脚本。
配置字段:可以添加或修改 package.json 中的其他字段,如 browserslist、eslintConfig 等。
使用示例

api.extendPackage({
  dependencies: {
    vuex: '^4.0.0'
  },
  devDependencies: {
    'eslint-plugin-vue': '^7.0.0'
  },
  scripts: {
    serve: 'vue-cli-service serve',
    build: 'vue-cli-service build'
  }
})

原文地址:https://blog.csdn.net/qq_42952637/article/details/143589740

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!