今天 utools 更新了第三方插件, 并且提供了初步的开发文档
我花了一点时间尝试了一下, 鉴于官网上也没有给出demo, 那我就简单地用代码展示一下插件的开发.
我实现了一个简单的命令行调用插件, 作为这次尝试的demo




总的来说, 插件开发还是非常简单的, 插件工程目录里最少只需要2个文件即可构成一个插件, 分别是index.html
和plugin.json
, 其中plugin.json
是插件的说明信息, index.html
是插件的本体.

刨去plugin.json
和preload.js
这两个 utools 插件特有的文件, 剩下的文件放在一起很显然就是一个传统的 web 工程, 也就是说插件就是一个 web 页面.
在plugin.json
定义的是一些插件的信息, 就像身份证一样, 作者, 描述, 版本, 插件的入口等等, 文档里描述得比较清楚, 就不赘述了.
{
"pluginName": "命令行调用",
"version": "0.0.1",
"description": "调用命令行执行命令",
"author": "lanyuanxiaoyao",
"homepage": "http://lanyuanxiaoyao.com",
"main": "index.html",
"preload": "preload.js",
"logo": "logo.png",
"pluginSetting": {
"single": true
},
"features": [
{
"code": "命令行",
"explain": "命令行",
"cmds": [
">", "cmd", "command"
]
}
]
}
接下来是插件的本体, 在这里我习惯性地用了 vue 来写, 但是也不影响主要逻辑, 因为比较简单, 大意就是获取输入框输入的命令, 然后调用相关的函数在 shell 里执行一下, 如果有返回值的话, 就展示在插件页面上, 如果没有的话, 就什么也不发生. (除了 vue 之外, 还顺便引入了 element-ui, 但是这不影响主要逻辑, 忽略即可.)
<!DOCTYPE html>
<html lang="zh">
<head>
<link rel="stylesheet" href="./element.css" />
</head>
<body>
<div id="app">
<el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="content" autosize resize="none" readonly />
</div>
</body>
</html>
<script src="./extra.js"></script>
<script src="./vue.js"></script>
<script src="./element.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
content: '',
command: ''
},
mounted: function () {
var self = this
// 进入插件执行的事件
utools.onPluginEnter(({ code, type, payload }) => {
// 将插件主界面的高度设为0, 即隐藏插件界面, 因为这个时候我们的这个插件只需要一个输入框而已
utools.setExpendHeight(0)
// 等待二次输入的回调方法
// 将输入的内容更新到 command 变量里, 交给其他函数使用
utools.setSubInput(({ text }) => {
self.command = text
}, '输入要执行的命令')
})
// API 里并没有回车键按下的事件, 所以监听事件要自己写
// 监控回车键按下的事件
document.onkeydown = function (e) {
var keyCode = window.event ? e.keyCode : e.which
if (keyCode == 13) {
if (self.command === '') {
return
}
window.exec(self.command, (content) => {
self.content = content
// 如果命令行调用有返回结果的话, 就把插件页面展示出来
if (content !== '') {
utools.setExpendHeight(500)
}
})
}
}
}
})
</script>
除了基础的两个文件外, 如果需要用到node.js
或者electron
提供的一些功能, 就要再加入一个preload.js
的文件, 这个文件可以理解为一个中间层, 用来把插件的页面和底层的框架连接起来, 在连接的同时也做了隔离, 方式底层 API 被滥用.
在这个文件里的事情也比较简单了, 就是做了一个名为exec
的扩展函数, 让页面上的代码可以调用child_process
模块.
console.log('preLoad')
const { exec } = require('child_process')
window.exec = function (command, callback) {
exec(command, (err, stdout, stderr) => {
if (err) {
callback(stderr);
return;
}
callback(stdout)
})
}
到这里, 一个插件的开发就已经完成了, 只要复制一下plugin.json
文件, 然后眼疾手快地打开 utools, 就可以导入模块到 utools 里了, 当然, 对于以上展示的这个模块来说, 可以完善的东西还有很多, 这里仅仅是做一个示范.
希望大家能玩得愉快.
当然, 在开发的过程中还是遇到了一些不愉快的事情
1. 插件如果没有退出的情况下重新加载 plugin.json
, utools 会卡死, 只能选择重启.
2. utools.setSubInput
的用法感觉有点古怪, 我一开始以为只要在最外层写了就会开启二级输入, 但是并没有, 只有写在utools.onPluginEnter
里才起作用, 希望在文档里能说明这一点.