共计 5296 个字符,预计需要花费 14 分钟才能阅读完成。
本文指标:手摸手教你打造一个反对内嵌网页的 VS Code 插件,实现 Vue 我的项目前端表单代码的主动生成,早日实现摸鱼自在。
成果展现
废话不多说,先看看最终的工作成绩:
看完动图是不是提神了那么一丢丢,让咱们开干吧~~
第一步 /Step 1
首先,咱们须要一款 开源
、 拖拽式设计
的可视化设计器,GitHub、码云一通搜寻,曾经有很多成品了,各种 form-create、form-design、vue-form、form-generator 等等;<br/>
其次,从上述设计器中筛选反对代码生成的,当然如果没有代码生成也能够本人实现,毕竟都开源了不是?
我这里抉择的是开源的 VForm 设计器:VForm GitHub
为啥咧?哈哈。。。看着眼生呗,性能上多那么一丢丢~~
第二步 /Step 2
装置 VS Code 插件开发套件:
npm install -g yo generator-code
装置胜利后,运行 yo code
生成新的插件我的项目:
起个简略又好听的名字——quick-coder(撸码达人),加个简略的阐明,其余选项按需抉择即可。
来来来,看一下生成的插件我的项目:
这里只须要重点关注两个文件:extension.js
、package.json
extension.js,插件扩大点形容文件
package.json,我的项目属性、依赖包及插件配置文件
第二步工作告一段落,接下来开始第三步插件的编码实现工作。
第三步 /Step 3
批改 package.json,以减少插件的启动命令,能够从命令面板和左侧资源管理器启动。
"contributes": {
"commands": [{
"command": "extension.openVFormMaker",
"title": "关上 VForm 设计器"
}],
"menus": {
"explorer/context": [{
"command": "extension.openVFormMaker",
"group": "navigation"
}]
}
},
批改 extension.js 的插件启用办法,仅一行:
function activate(context) {require('./src/vform-loader')(context)
}
截止到此时,咱们尚未解释整个代码生成器插件是如何工作的,但当初到了不得不说的时候了。
咱们心愿,当插件启动的时候关上一个 WebView 面板,WebView 面板通过 URL 配置参数加载 VForm 网页,当 VForm 生成代码时与 VS Code 通过 postMessage 通信,VS Code 负责将生成代码保留为本地文件。
实现上述需要的要害代码都在 vform-loader.js 文件中。
这里还有两个小问题须要解答:
- WebView 能间接加载近程网页吗?
答案是 不能,只能加载本地 HTML 文件。- 那么问题来了?WebView 怎么加载远端网页的 HTML 呢?
答案也很 简略,就是在本地 HTML 文件内嵌入 iframe,iframe 万能——YYDS!
解决了上述几个小 case,咱们来看看整个插件的灵魂代码。
src\view\index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=0,maximum-scale=0,user-scalable=yes,shrink-to-fit=no"
/>
<title>Quick Coder</title>
</head>
<body>
<iframe id="frame" width="100%" height="100%" frameborder="0"></iframe>
<script>
window.onload = function () {const vscode = acquireVsCodeApi();
const cmds = {setSrc: function (message) {var frame = document.getElementById("frame");
frame.src = message.data.src;
},
writeFile: function (message) {vscode.postMessage(message);
},
openUrl: function (message) {vscode.postMessage(message);
},
setStorageItem: function (message) {vscode.postMessage(message);
},
};
window.addEventListener("message", (event) => {
const message = event.data;
if (message && message.cmd) cmds[message.cmd](message);
});
};
</script>
</body>
</html>
src\vform-loader.js
const vscode = require('vscode')
const fs = require('fs')
const path = require('path')
const open = require('open')
const DB_PATH = path.join(__dirname,'./data/db.json')
function getExtensionFileAbsolutePath(context, relativePath) {return path.join(context.extensionPath, relativePath)
}
/**
* 从某个 HTML 文件读取能被 Webview 加载的 HTML 内容
* @param {*} context 上下文
* @param {*} templatePath 绝对于插件根目录的 html 文件相对路径
*/
function getWebViewContent(context, templatePath) {const resourcePath = getExtensionFileAbsolutePath(context, templatePath)
const dirPath = path.dirname(resourcePath)
let html = fs.readFileSync(resourcePath, 'utf-8')
// vscode 不反对间接加载本地资源,须要替换成其专有门路格局,这里只是简略的将款式和 JS 的门路替换
html = html.replace(/(<link.+?href="|<script.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {return $1 + vscode.Uri.file(path.resolve(dirPath, $2)).with({scheme: 'vscode-resource'}).toString() + '"'})
return html
}
const methods = {writeFile: function (message, vscode, dirPath) {let { fileName, code} = message.data
let filePath = path.join(dirPath, fileName)
fs.writeFileSync(filePath, code)
vscode.window.showInformationMessage(` 文件 ${fileName}创立胜利 `)
},
openUrl: function (message, vscode, dirPath) {open(message.data.url)
},
setStorageItem: function(message, vscode, dirPath) {const { key, val} = message.data
const str = fs.readFileSync(DB_PATH).toString()
let json = {}
if (str) {json = JSON.parse(str)
}
json[key] = val
fs.writeFileSync(DB_PATH, JSON.stringify(json))
},
}
module.exports = function (context) {context.subscriptions.push(vscode.commands.registerCommand('extension.openVFormMaker', (uri) => {if (uri) {
let dirPath = uri.fsPath,
stat = fs.lstatSync(dirPath)
if (stat.isFile()) dirPath = path.dirname(dirPath)
let pclintBar = vscode.window.createStatusBarItem()
pclintBar.text = ` 指标文件夹:${dirPath}`
pclintBar.show()
const panel = vscode.window.createWebviewPanel(
'vFormMaker',
"VForm 表单设计器",
vscode.ViewColumn.One,
{
enableScripts: true, // 启用 JS,默认禁用
retainContextWhenHidden: true, // webview 被暗藏时放弃状态,防止被重置
}
)
panel.onDidChangeViewState(e => {if (panel.visible) {pclintBar.show()
} else {pclintBar.hide()
}
})
panel.webview.html = getWebViewContent(context, 'src/view/index.html')
panel.webview.postMessage({
cmd: 'setSrc',
data: {src: vscode.workspace.getConfiguration().get('VFormMaker.url') + '&t=' + new Date(),
db: JSON.parse(fs.readFileSync(DB_PATH).toString() || '{}')
}
})
panel.webview.onDidReceiveMessage(message => {if (message.cmd && message.data) {let method = methods[message.cmd]
if (method) method(message, vscode, dirPath)
} else {vscode.window.showInformationMessage(` 没有与音讯对应的办法 `)
}
}, undefined, context.subscriptions)
panel.onDidDispose(e => {pclintBar.dispose()
})
} else {vscode.window.showInformationMessage(` 无奈获取文件夹门路 `)
}
}))
}
OK~ 灰常好,给看到这里的大佬们鼓掌👏👏👏,行将看到插件运行成果!!
最初批改 package.json 文件的 contributes
属性,减少一个 URL 参数配置,竣工!!
"contributes": {
"configuration": {
"type": "object",
"title": "VForm 设计器配置",
"properties": {
"VFormMaker.url": {
"type": "string",
"default": "http://120.92.142.115/?vscode=1",
"description": "VForm 设计器近程 URL"
}
}
},
连忙在 VS Code 中按下 F5 键调试插件,观赏下本人的工作成绩😤😤~~~
第四步 / 打包公布
装置打包工具 vsce
npm install -g vsce
在插件我的项目运行 vsce package
命令,即可生成.vsix 文件(会提醒批改 README.md 文件,减少插件的简介及应用阐明)
vsce package
注册 VS marketplace 账号,上传.vsix 文件,凋谢给所有 VS Code 用户应用:
VS marketplace
后话 /Finally
简略回顾一下,咱们通过 WebView 嵌入 VForm 的远端网页,实现了常见的 Vue 表单前端代码生成(反对 Vue2 也反对 Vue3 哦)的预期需要,因为 VForm 自身是一个开源我的项目,且有良好的扩展性,有心的大佬们能够自在扩大 VForm 的性能,进一步实现 el-table 等更多组件的前端代码主动生成,早日实现摸鱼自在🍺🍺🍺
最初的最初
感觉本人写插件有点小累的大佬们,能够间接在 VS Code 扩大中搜寻 vform-maker
或vformAdmin
最初,再附上寰球最大同性交友网的 VForm 链接:GitHub
国内同步码云:Gitee