总共分为以下几个步骤:

  1. 初始化插件模板,生成一个插件项目
  2. 创建插件的视图容器和展示插件内容的视图
  3. 把插件运行起来,开始可视化的开发调试
  4. 为视图提供数据
  5. 发布插件

一、初始化插件模板

  1. 全局安装yo 和 generator-code
npm install -g yo generator-code



2.运行如下命令



yo code



3.各种配置项选择完毕之后,会生成一个项目




vscode使用mysql插件 编写vscode插件_vscode 插件


二、创建插件的视图容器和展示插件内容的视图

  1. 创建一个视图容器,通过修改package.json文件来创建
"contributes": {
 // 自定义插件的icon,展示在VSCode侧边栏上
 "viewsContainers": {
 "activitybar": [
            {
 "id": "custom-plugin",
 "title": "自定义插件",
 "icon": "images/custom.svg"
            }
        ]
    },
}


效果如下图,我在https://www.iconfont.cn/上找了一个自行车的icon


vscode使用mysql插件 编写vscode插件_vscode使用mysql插件_02


2.在视图容器中添加一个视图,继续配置package.json文件


"contributes": { 
 // 自定义插件的icon,展示在VSCode侧边栏上
 "viewsContainers": {
 "activitybar": [
            {
 "id": "custom-plugin",
 "title": "自定义插件",
 "icon": "images/custom.svg"
            }
        ]
    },
 "views": {
 // 和viewsContainers的id相对应
 "custom-plugin": [
            {
 "name": "我的插件",
 "id": "plugin-list"
            }
        ]
    },
}


三、把插件运行起来,开始可视化的开发调试


vscode使用mysql插件 编写vscode插件_ico_03


四、往视图中添加内容

假如我们要做一个查看基金涨跌数据的插件,大概需要3个步骤

  1. 修改项目中的extension.ts文件,为视图提供数据
import { ExtensionContext, commands, window, workspace } from 'vscode';
import Provider from './Provider';


// 激活插件时调用
export function activate(context: ExtensionContext) {
 // 基金类
 const provider = new Provider();
 // 数据注册,第一个参数是在package.json文件中配置的视图id
 window.registerTreeDataProvider('custom-plugin', provider);
}


// 停用插件时调用
export function deactivate() {}


其中registerTreeDataProvider是VSCode提供的一个API,用于给视图注入数据。

要想active方法起作用,还需要配置什么时候激活触发这个函数的执行,继续配置package.json文件,


"activationEvents": [
 "onView:plugin-list" // 配置在插件视图打开的时候激活插件
 ]


  1. provider文件如何写?
import { workspace, TreeDataProvider, TreeItem, Event, EventEmitter } from 'vscode';
import fundApi from './api';
import FundItem from './TreeItem';


export default class DataProvider implements TreeDataProvider<FundInfo> {
  private refreshEvent: EventEmitter<FundInfo | null> = new EventEmitter<FundInfo | null>();
  readonly onDidChangeTreeData: Event<FundInfo | null> = this.refreshEvent.event;
  private order: number;


 constructor() {
 this.order = -1;
  }


  refresh() {
 // 更新视图
 this.refreshEvent.fire(null);
  }


  getTreeItem(info: FundInfo): TreeItem {
 return new FundItem(info);
  }


  getChildren(): Promise<FundInfo[]> {
 const { order } = this;
 // 获取配置的基金代码
 const favorites: string[] = workspace
    .getConfiguration()
    .get('fund.favorites', []);


 // 获取基金数据
 return fundApi([...favorites]).then((results: FundInfo[]) => 
      results.sort((a, b) => (a.changeRate >= b.changeRate ? 1 : -1) * order)
    );
  }
}


2. TreeItem文件如何写?


import { TreeItem } from 'vscode';


export default class FundItem extends TreeItem {
  info: FundInfo;


 constructor (info: FundInfo) {
 const rate = Number(info.changeRate);
 const icon = rate >= 0 ? ' ' : ' ';
 super(`${icon}${info.name} ${info.changeRate}%`);
 this.info = info;
  }
}


3.fundApi很简单,去基金网站上扒获取基金的接口出来用就行了,把参考代码贴出来


import * as https from 'https';


// 发送get请求
const request = async (url: string): Promise<string> => {
 return new Promise((resolve, reject) => {
    https.get(url, (res) => {
      let chunks = '';
 if (!res || res.statusCode !== 200) {
        reject(new Error('网络请求失败'));
 return;
      }
 // 绑定事件
      res.on('data', chunk => chunks += chunk);
      res.on('end', () => resolve(chunks));
    });
  });
};


interface FundInfo {
  now: string
  name: string
  code: string
  lastClose: string
  changeRate: string
  changeAmount: string
}


export default function fundApi(codes: string[]): Promise<FundInfo[]> {
  const time = Date.now();
  const promises: Promise<string>[] = codes.map(code => {
    const url = `https://fundgz.1234567.com.cn/js/${code}.js?rt=${time}`;
 return request(url);
  });


 return Promise.all(promises).then((resArr) => {
    let fundInfo: FundInfo[] = [];
    resArr.forEach((res: string) => {
      const result = res.match(/jsonpgz((.+))/);
 if (!result || !result[1]) {
 return;
      }
      const resObj = JSON.parse(result[1]);
      const obj: FundInfo= {
 // 当前净值
        now: resObj.gsz,
 // 基金名称
        name: resObj.name,
 // 基金代码
        code: resObj.fundcode,
 // 昨天净值
        lastClose: resObj.dwjz,
 // 涨跌幅
        changeRate: resObj.gszzl,
 // 涨跌额
        changeAmount: (resObj.gsz - resObj.dwjz).toFixed(4)
      };


      fundInfo.push(obj);
    });


 return fundInfo;
  });
}


五、发布插件