前言
在上一篇『手撕Vue-CLI』添加自定义指令中,已经实现了自定义指令的添加,但是指令还是比较简单的,只是简单的打印一句话,那么在实际运用场景中,可能会有更多的需求,比如可能需要在指令中传递参数,或者需要在指令中进行一些复杂的操作,那么这个时候我们就需要对指令进行处理了。
创建指令处理文件
在上一篇『手撕Vue-CLI』添加自定义指令中,添加了一个 create 指令与 add 指令, 先来处理一下 create 指令,为了更好的处理指令,我单独为每一个指令创建了一个文件,这样更加清晰。
在 bin
目录下创建一个 create.js
文件,用于处理 create 指令,create.js 文件内容如下:
module.exports = () => {console.log('create');
}
在 bin
目录下创建一个 add.js
文件,用于处理 add 指令,add.js 文件内容如下:
module.exports = () => {console.log('add');
}
修改指令处理文件
接下来需要修改 bin/index.js
文件,之前是在 action 回调中根据 key 来判断指令,然后处理指令,之前只是简简单单的打印出来指令所对应的 description,现在需要根据指令来引入对应的处理文件,然后执行对应的处理函数。
这里会遇到几个问题,首先是如何引入对应的处理文件,其次是如何执行对应的处理函数。
首先来解决如何引入对应的处理文件,这里可以使用 require
函数来引入对应的处理文件,然后使用 module.exports
来导出处理函数这一步已经在处理函数文件中已经编写好了,这样就可以在 index.js
中引入对应的处理文件,然后执行对应的处理函数。
上面我提到了使用 require
来引入对应的处理文件这里有存在一个问题路径问题,这里可以用 __dirname
获取当前文件所在的目录:
然后配合 path
模块来拼接路径,这样就可以解决路径问题了,在 path 中有一个 resolve
这个函数可以接受多个参数,每个参数都会被视为路径的一部分,并且会从右到左依次进行解析。最终返回的是这些路径片段拼接后的绝对路径。
随后我们的代码就可以改写成如下:
require(path.resolve(__dirname, key))();
首先利用 _dirname
获取当前文件所在的目录,然后使用 path.resolve
将 __dirname
与 key 拼接成一个绝对路径,key 就是指令名称,然后使用 require
引入对应的处理文件,最后执行对应的处理函数。
我们的处理文件是通过 module.exports
导出的,所以可以直接调用引入的文件,然后执行对应的处理函数。
其它的代码没动,还有就是我这里使用到了 path 模块,所以需要在 index.js
文件中引入 path 模块:
const path = require('path');
__dirname
在我之前的 Node.js 系列文章中有提到过,这里就不再赘述了,如果不了解的可以去看一下之前的文章。
看到这,我们是不是已经有能力去处理不同的指令了,但是还有问题需要解决,那就是如何传递参数。
传递参数
在实际这些指令的时候,指令后面可能会跟一些参数,比如 create
指令后面可能会跟一个项目名称,add
指令后面可能会跟一个组件名称,那么这个时候我们就需要传递参数了。
在 Node.js 中,可以通过 process.argv
来获取命令行参数,process.argv
是一个包含命令行参数的数组,第一个元素是 Node.js 的可执行文件路径,第二个元素是当前执行的 JavaScript 文件路径,从第三个元素开始,依次是命令行传入的参数。
所以从这就可以得出,可以通过 process.argv
来获取到指令后面的参数,然后传递给对应的处理函数,在上面说了从第三个元素开始,依次是命令行传入的参数,所以我们可以通过 process.argv.slice(3)
来获取到指令后面的参数。
先来打印一下看看:
很 ok,结果正是我想要的,那么接下来就可以将这些参数传递给对应的处理函数了。
改写一下 index.js
文件:
require(path.resolve(__dirname, key))(...process.argv.slice(3));
就改一行代码,将 require(path.resolve(__dirname, key))()
改成 require(path.resolve(__dirname, key))(...process.argv.slice(3));
,利用 ...
来展开数组,将数组中的元素传递给函数。
接下来要改的就是在处理函数中接收参数了,比如在 create.js
中接收参数,create 只需要一个参数就是项目名称,所以只需要一个参数,那么可以这样改写:
module.exports = (projectName) => {console.log('create', projectName);
}
在 add.js
中接收参数,add 需要两个参数:
module.exports = (a, b) => {console.log('add', a, b);
}
这样就可以在处理函数中接收参数了,然后在处理函数中就可以根据参数来进行一些操作了。
最后来测试一下: