1、初衷
在开发RN项目时,经常会新建页面,新建的页面内容如果是手敲的话,比较慢,如果是从其他文件中复制过来还要删除多余的代码;所以开发一个一健生成hooks的RN文件会提升效率
2、插件功能
在编辑目录中新增一个“新建hooks文件”的功能,该功能可自动生成设置好的内容
3、开始开发
3.1、安装官方脚手架
npm install -g yo generator-code
3.2、安装成功后使用脚手架
yo code
3.3、安装成功后的目录结构
其中,最核心的两个文件是package.json和extension.js,package.json是整个插件工程的配置文件,extension.js则是工程的入口文件。下面将对这两个文件进行详细的介绍。
4、运行调试
5、package.json详解
{
"name": "createhooks", // 插件名称
"displayName": "createHooks", // 显示在插件市场的名称
"description": "快速创建一个hooks的RN文件", // 插件描述
"publisher":"zhuangzi", //发布者
"version": "0.0.1", //版本号
"engines": { // 表示插件支持的最低vscode版本
"vscode": "^1.66.0"
},
"categories": [ // 插件应用市场分类,可选值: [Programming Languages, Snippets,Linters,Themes, Debuggers, Formatters, Keymaps, SCM Providers, Other, Extension Packs, Language Packs]
"Other"
],
"icon": "images/icon.png",// 插件图标,至少128x128像素 images文件需要在根目录下创建
"activationEvents": [ // 扩展的激活事件数组,可以被哪些事件激活扩展,后文有详细介绍
"*"
],
"main": "./out/extension.js", // 插件的入口文件
"contributes": { // 贡献点,整个插件最重要最多的配置项 后文有详细介绍
"commands": [ // 注册命令 其中‘createHooks.createFile’为标识命令字段
{
"command": "createHooks.createFile",
"title": "新建hooks文件"
}
],
"menus": {
"explorer/context": [ //右键菜单
{
"command": "createHooks.createFile",
"group": "1_modification",
"when": "explorerResourceIsFolder"
}
]
}
},
"scripts": {
"vscode:prepublish": "yarn run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "yarn run compile && yarn run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js"
},
"devDependencies": {
"@types/vscode": "^1.66.0",
"@types/glob": "^7.2.0",
"@types/mocha": "^9.1.0",
"@types/node": "14.x",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"eslint": "^8.11.0",
"glob": "^7.2.0",
"mocha": "^9.2.2",
"typescript": "^4.5.5",
"@vscode/test-electron": "^2.1.3"
}
}
5.1、activationEvents
配置项配置插件的激活数组,即在什么情况下插件会被激活,目前支持以下8种配置:
- onLanguage: 在打开对应语言文件时
- onCommand: 在执行对应命令时
- onDebug: 在 debug 会话开始前
- onDebugInitialConfigurations: 在初始化 debug 设置前
- onDebugResolve: 在 debug 设置处理完之前
- workspaceContains: 在打开一个文件夹后,如果文件夹内包含设置的文件名模式时
- onFileSystem: 打开的文件或文件夹,是来自于设置的类型或协议时
- onView: 侧边栏中设置的 id 项目展开时
- onUri: 在基于 vscode 或 vscode-insiders 协议的 url 打开时
- onWebviewPanel: 在打开设置的 webview 时
- *: 在打开 vscode 的时候,如果不是必须一般不建议这么设置
5.2、contributes
整个插件的贡献点,也就是说这个插件有哪些功能。contributes字段可以设置的key也基本显示了vscode插件可以做什么。
- configuration:通过这个配置项我们可以设置一个属性,这个属性可以在
vscode的settings.json中设置,然后在插件工程中可以读取用户设置的这个值,进行相应的逻辑。 - commands:命令,通过
cmd+shift+p进行输入来实现的。 - menus:通过这个选项我们可以设置右键的菜单
- keybindings:可以设置快捷键
- languages:设置语言特点,包括语言的后缀等
- grammars:可以在这个配置项里设置描述语言的语法文件的路径,vscode可以根据这个语法文件来自动实现语法高亮功能
- snippets:设置语法片段相关的路径 就是输入一个前缀,会得到一个或多个提示,然后回车带出很多代码。
查看更多配置 code.visualstudio.com/api/referen…
举例
"contributes": {
// 插件配置项
"configuration": {
"type": "object",
// 配置项标题,会显示在vscode的设置页
"title": "create-hooks-file",
"properties": {
// 这里我随便写了2个设置,配置你的昵称
"vscodePluginDemo.yourName": {
"type": "string",
"default": "guest",
"description": "zhuangzi" //你的名称
},
// 是否在启动时显示提示
"vscodePluginDemo.showTip": {
"type": "boolean",
"default": true,
"description": "是否在每次启动时显示欢迎提示!"
}
}
},
// 命令
"commands": [
{
"command": "createHooks.createFile",
"title": "新建hooks文件"
}
],
"menus": {
// 编辑器右键菜单
"editor/context": [{
"when": "editorFocus", // 表示只有编辑器具有焦点时才会在菜单中出现
"command": "extension.sayHello",
"group": "navigation@6" // navigation是一个永远置顶的分组,后面的@6是人工进行组内排序
// `navigation`:导航组在所有情况下都排在第一位
// `1_modification`:该组紧随其后,包含修改代码的命令
// `9_cutcopypaste`:带有基本编辑命令的倒数第二个默认组
// `z_commands`:带有打开命令面板的条目的最后一个默认组
},
{
"when": "editorFocus",
"command": "extension.demo.getCurrentFilePath",
"group": "navigation@5"
},
{
"when": "editorFocus && resourceLangId == javascript", // 只有编辑器具有焦点,并且打开的是JS文件才会出现
"command": "extension.demo.testMenuShow",
"group": "z_commands"
},
{
"command": "extension.demo.openWebview",
"group": "navigation"
}
],
// 编辑器右上角图标,不配置图片就显示文字
"editor/title": [{
"when": "editorFocus && resourceLangId == javascript",
"command": "extension.demo.testMenuShow",
"group": "navigation"
}],
// 编辑器标题右键菜单
"editor/title/context": [{
"when": "resourceLangId == javascript",
"command": "extension.demo.testMenuShow",
"group": "navigation"
}],
// 资源管理器右键菜单
"explorer/context": [{
"command": "extension.demo.getCurrentFilePath",
"group": "navigation"
},
{
"command": "extension.demo.openWebview",
"group": "navigation"
}
]
},
"keybindings": [ // 按键绑定
{
"command": "extension.helloWorld",
"key": "ctrl+f10",
"mac": "cmd+f10",
"when": "editorTextFocus"
}
],
// 代码片段
"snippets": [{
"language": "javascript",
"path": "./snippets/javascript.json"
},
{
"language": "html",
"path": "./snippets/html.json"
}
],
5.3、代码片段
想要在vscode插件中实现snippets的功能,首先要在package.json的contributes配置项中配置代码提示文件的文件路径:
"snippets": [
{
"language": "typescriptreact", // javascript typescript javascriptreact
"path": "./snippets.json"
}
]
这里language设置了snippets作用于何种语言,path设置了服务于snippets的文件的路径。
再看一下在snippets.json文件中:
{
"View组件": {
"prefix": "View",
"body": [
"<View>",
"${1}",
"</VIew>"
],
"description": "View组件"
}
}
"View组件":snippet的名称"prefix":前缀,即输入什么可以出现snippets的提示"body":按回车后出现的一大段代码,是一个数组,数组里面是字符串,每个字符串代表一行代码,${1}表示第一个光标的位置,同样,${2}表示第二个光标的位置"description":对于这个snippet的描述,当我们选中这个snipets提示时,描述会出现在后面。 现在,我们运行插件,并保证插件被激活,在规定的语言下,输入View:
6、extension
import * as vscode from 'vscode';
import genFile from './getFiles';
export function activate(context: vscode.ExtensionContext) {
// 当createHooks.createFile命令触发时 弹出输入文件的名的输入框并检查文件名是否已存在
let createdirindexCommand = vscode.commands.registerCommand('createHooks.createFile', async(uri: vscode.Uri) => {
const fileName = await vscode.window.showInputBox({prompt: '文件名称(不需要输入后缀名)', placeHolder: '输入文件名称'});
const dirPath = uri.fsPath;
genFile(dirPath, fileName);
});
context.subscriptions.push(createdirindexCommand);
}
export function deactivate() {}
genFile.ts
import { readdir, writeFile } from 'fs';
import * as vscode from 'vscode';
import { join } from 'path';
import { promisify } from 'util';
const indexFileExt = '.tsx';
const genFile = async(dir: string,fileName:string | undefined) =>{
if(!fileName || fileName===''){
vscode.window.showErrorMessage('文件名不能为空');
return;
}
// 得到目录下所有文件名集合
const result = await promisify(readdir)(dir);
if(result.indexOf(fileName+'.tsx') !== -1){
vscode.window.showErrorMessage('文件名已存在');
return;
}
const content=`
import React, { useState } from 'react';
import { View, StyleSheet, Image, TouchableOpacity } from 'react-native';
import { DeprecatedNavigator, TYText, Utils } from 'tuya-panel-kit';
import String from '@i18n';
import Res from '@res';
import { useIoTUIValue } from '@models';
const { convertX: cx } = Utils.RatioUtils;
interface MainProps {
navigator: DeprecatedNavigator;
}
const Pages: React.FC<MainProps> = () => {
const fontColor = useIoTUIValue('fontColor');
const background = useIoTUIValue('background');
return <View style={styles.main} />;
};
const styles = StyleSheet.create({
main: {
flex: 1,
alignItems: 'center',
},
});
export default Pages;
`;
// 写入文件夹下
await promisify(writeFile)(join(dir, fileName + indexFileExt), content);
};
export default genFile;
7、打包
安装vsce(Visual Studio Code Extension)
npm install -g vsce
打包(首次打包需要修改readme.md文件内容,否则打包不成功)
vsce package
打包后在项目目录下会生成一个vsix包,可通过添加扩展插件导入使用
8、发布
-
1.在网站
https://dev.azure.com/vscode获取一个access token,这个token用来创建一个publisher -
2.创建
publisher
vscr create-publisher (publisher name) -
3.登入一个
publisher
vscde login (publisher name) -
4.发布
vsce publish
9、开发过程中遇到的问题
1.首次打包的时候需要修改下README.md文件内容,否则打包会失败
2.设置了插件icon打包的时候路径报错了————需要将存放图片的文件夹放在项目的根目录下,然后用绝对路径引入
3.设置了snippets代码片段不生效————configuration中的配置导致的,建议去掉configuration中的配置,一般也不会用到这个