<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)戰(zhàn)-從零開始實(shí)現(xiàn)VS Code基金插件(上班摸魚可用)

          共 14150字,需瀏覽 29分鐘

           ·

          2020-11-14 21:28

          寫在前面

          隨著7月一波牛市行情,越來越多的人投身A股行列,但是股市的風(fēng)險(xiǎn)巨大,有人一夜暴富,也有人血本無歸,所以對于普通人來說基金定投是個(gè)不錯(cuò)的選擇,本人也是基金定投的一枚小韭菜。

          基金定投

          上班的時(shí)候經(jīng)常心理癢癢,想看看今天的基金又賺(ge)了多少錢,拿出手機(jī)打開支付寶的步驟過于繁瑣,而且我也不太關(guān)心其他的指標(biāo),只是想知道今天的凈值與漲幅。VS Code 做為一個(gè)編碼工具,提供了強(qiáng)大的插件機(jī)制,我們可以好好利用這個(gè)能力,可以一邊編碼的時(shí)候一邊看看行情。

          示例

          實(shí)現(xiàn)插件

          初始化

          VSCode 官方提供了非常方便的插件模板,我們可以直接通過 Yeoman 來生成 VS Code 插件的模板。

          先全局安裝 yo 和 generator-code,運(yùn)行命令 yo code

          #?全局安裝?yo?模塊
          npm?install?-g?yo?generator-code

          這里我們使用 TypeScript 來編寫插件。

          yo code
          yo code

          生成后的目錄結(jié)構(gòu)如下:

          目錄結(jié)構(gòu)

          VS Code 插件可以簡單理解為一個(gè) Npm 包,也需要一個(gè) package.json 文件,屬性與 Npm 包的基本一致。

          {
          ??//?名稱
          ??"name":?"fund-watch",
          ??//?版本
          ??"version":?"1.0.0",
          ??//?描述
          ??"description":?"實(shí)時(shí)查看基金行情",
          ??//?發(fā)布者
          ??"publisher":?"shenfq",
          ??//?版本要求
          ??"engines":?{
          ????"vscode":?"^1.45.0"
          ??},
          ??//?入口文件
          ??"main":?"./out/extension.js",
          ??"scripts":?{
          ????"compile":?"tsc?-p?./",
          ????"watch":?"tsc?-watch?-p?./",
          ??},
          ??"devDependencies":?{
          ????"@types/node":?"^10.14.17",
          ????"@types/vscode":?"^1.41.0",
          ????"typescript":?"^3.9.7"
          ??},
          ??//?插件配置
          ??"contributes":?{},
          ??//?激活事件
          ??"activationEvents":?[],
          }

          簡單介紹下其中比較重要的配置。

          • contributes:插件相關(guān)配置。
          • activationEvents:激活事件。
          • main:插件的入口文件,與 Npm 包表現(xiàn)一致。
          • namepublisher:name 是插件名,publisher 是發(fā)布者。${publisher}.${name} 構(gòu)成插件 ID。

          比較值得關(guān)注的就是 contributesactivationEvents 這兩個(gè)配置。

          創(chuàng)建視圖

          我們首先在我們的應(yīng)用中創(chuàng)建一個(gè)視圖容器,視圖容器簡單來說一個(gè)單獨(dú)的側(cè)邊欄,在 package.jsoncontributes.viewsContainers 中進(jìn)行配置。

          {
          ??"contributes":?{
          ????"viewsContainers":?{
          ??????"activitybar":?[
          ????????{
          ??????????"id":?"fund-watch",
          ??????????"title":?"FUND?WATCH",
          ??????????"icon":?"images/fund.svg"
          ????????}
          ??????]
          ????}
          ??}
          }
          側(cè)邊欄

          然后我們還需要添加一個(gè)視圖,在 package.jsoncontributes.views 中進(jìn)行配置,該字段為一個(gè)對象,它的 Key 就是我們視圖容器的 id,值為一個(gè)數(shù)組,表示一個(gè)視圖容器內(nèi)可添加多個(gè)視圖。

          {
          ??"contributes":?{
          ????"viewsContainers":?{
          ??????"activitybar":?[
          ????????{
          ??????????"id":?"fund-watch",
          ??????????"title":?"FUND?WATCH",
          ??????????"icon":?"images/fund.svg"
          ????????}
          ??????]
          ????},
          ????"views":?{
          ??????"fund-watch":?[
          ????????{
          ??????????"name":?"自選基金",
          ??????????"id":?"fund-list"
          ????????}
          ??????]
          ????}
          ??}
          }

          如果你不希望在自定義的視圖容器中添加,可以選擇 VS Code 自帶的視圖容器。

          • explorer: 顯示在資源管理器側(cè)邊欄
          • debug: 顯示在調(diào)試側(cè)邊欄
          • scm: 顯示在源代碼側(cè)邊欄
          {
          ??"contributes":?{
          ????"views":?{
          ??????"explorer":?[
          ????????{
          ??????????"name":?"自選基金",
          ??????????"id":?"fund-list"
          ????????}
          ??????]
          ????}
          ??}
          }
          顯示到資源管理器中

          運(yùn)行插件

          使用 Yeoman 生成的模板自帶 VS Code 運(yùn)行能力。

          vscode配置

          切換到調(diào)試面板,直接點(diǎn)擊運(yùn)行,就能看到側(cè)邊欄多了個(gè)圖標(biāo)。

          調(diào)試面板
          運(yùn)行結(jié)果

          添加配置

          我們需要獲取基金的列表,當(dāng)然需要一些基金代碼,而這些代碼我們可以放到 VS Code 的配置中。

          {
          ??"contributes":?{
          ????//?配置
          ????"configuration":?{
          ??????//?配置類型,對象
          ??????"type":?"object",
          ??????//?配置名稱
          ??????"title":?"fund",
          ??????//?配置的各個(gè)屬性
          ??????"properties":?{
          ????????//?自選基金列表
          ????????"fund.favorites":?{
          ??????????//?屬性類型
          ??????????"type":?"array",
          ??????????//?默認(rèn)值
          ??????????"default":?[
          ????????????"163407",
          ????????????"161017"
          ??????????],
          ??????????//?描述
          ??????????"description":?"自選基金列表,值為基金代碼"
          ????????},
          ????????//?刷新時(shí)間的間隔
          ????????"fund.interval":?{
          ??????????"type":?"number",
          ??????????"default":?2,
          ??????????"description":?"刷新時(shí)間,單位為秒,默認(rèn)?2?秒"
          ????????}
          ??????}
          ????}
          ??}
          }

          視圖數(shù)據(jù)

          我們回看之前注冊的視圖,VS Code 中稱為樹視圖。

          "views":?{
          ??"fund-watch":?[
          ????{
          ??????"name":?"自選基金",
          ??????"id":?"fund-list"
          ????}
          ??]
          }

          我們需要通過 vscode 提供的 registerTreeDataProvider 為視圖提供數(shù)據(jù)。打開生成的 src/extension.ts 文件,修改代碼如下:

          //?vscode?模塊為?VS?Code?內(nèi)置,不需要通過?npm?安裝
          import?{?ExtensionContext,?commands,?window,?workspace?}?from?'vscode';
          import?Provider?from?'./Provider';

          //?激活插件
          export?function?activate(context:?ExtensionContext)?{
          ??//?基金類
          ??const?provider?=?new?Provider();

          ??//?數(shù)據(jù)注冊
          ??window.registerTreeDataProvider('fund-list',?provider);
          }

          export?function?deactivate()?{}

          這里我們通過 VS Code 提供的 window.registerTreeDataProvider 來注冊數(shù)據(jù),傳入的第一個(gè)參數(shù)表示視圖 ID,第二個(gè)參數(shù)是 TreeDataProvider 的實(shí)現(xiàn)。

          TreeDataProvider 有兩個(gè)必須實(shí)現(xiàn)的方法:

          • getChildren:該方法接受一個(gè) element,返回 element 的子元素,如果沒有element,則返回的是根節(jié)點(diǎn)的子元素,我們這里因?yàn)槭菃瘟斜恚圆粫?huì)接受 element 元素;
          • getTreeItem:該方法接受一個(gè) element,返回視圖單行的 UI 數(shù)據(jù),需要對 TreeItem 進(jìn)行實(shí)例化;

          我們通過 VS Code 的資源管理器來展示下這兩個(gè)方法:

          方法展示

          有了上面的知識,我們就可以輕松為樹視圖提供數(shù)據(jù)了。

          import?{?workspace,?TreeDataProvider,?TreeItem?}?from?'vscode';

          export?default?class?DataProvider?implements?TreeDataProvider<string>?{
          ??refresh()?{
          ????//?更新視圖
          ??}

          ??getTreeItem(element:?string):?TreeItem?{
          ????return?new?TreeItem(element);
          ??}

          ??getChildren():?string[]?{
          ????const?{?order?}?=?this;
          ????//?獲取配置的基金代碼
          ????const?favorites:?string[]?=?workspace
          ??????.getConfiguration()
          ??????.get('fund-watch.favorites',?[]);
          ????
          ????//?依據(jù)代碼排序
          ??return?favorites.sort((prev,?next)?=>?(prev?>=?next???1?:?-1)?*?order);
          ??}
          }


          現(xiàn)在運(yùn)行之后,可能會(huì)發(fā)現(xiàn)視圖上沒有數(shù)據(jù),這是因?yàn)闆]有配置激活事件。

          {
          ?"activationEvents":?[
          ????//?表示?fund-list?視圖展示時(shí),激活該插件
          ??"onView:fund-list"
          ?]
          }
          基金代碼列表

          請求數(shù)據(jù)

          我們已經(jīng)成功將基金代碼展示在視圖上,接下來就需要請求基金數(shù)據(jù)了。網(wǎng)上有很多基金相關(guān) api,這里我們使用天天基金網(wǎng)的數(shù)據(jù)。

          天天基金網(wǎng)

          通過請求可以看到,天天基金網(wǎng)通過 JSONP 的方式獲取基金相關(guān)數(shù)據(jù),我們只需要構(gòu)造一個(gè) url,并傳入當(dāng)前時(shí)間戳即可。

          const?url?=?`https://fundgz.1234567.com.cn/js/${code}.js?rt=${time}`

          VS Code 中請求數(shù)據(jù),需要使用內(nèi)部提供的 https 模塊,下面我們新建一個(gè) api.ts

          import?*?as?https?from?'https';

          //?發(fā)起?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('網(wǎng)絡(luò)請求錯(cuò)誤!'));
          ????????return;
          ??????}
          ??????res.on('data',?(chunk)?=>?chunks?+=?chunk.toString('utf8'));
          ??????res.on('end',?()?=>?resolve(chunks));
          ????});
          ??});
          };

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

          //?根據(jù)基金代碼請求基金數(shù)據(jù)
          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((results)?=>?{
          ????const?resultArr:?FundInfo[]?=?[];
          ????results.forEach((rsp:?string)?=>?{
          ??????const?match?=?rsp.match(/jsonpgz\((.+)\)/);
          ??????if?(!match?||?!match[1])?{
          ????????return;
          ??????}
          ??????const?str?=?match[1];
          ??????const?obj?=?JSON.parse(str);
          ??????const?info:?FundInfo?=?{
          ????????//?當(dāng)前凈值
          ????????now:?obj.gsz,
          ????????//?基金名稱
          ????????name:?obj.name,
          ????????//?基金代碼
          ????????code:?obj.fundcode,
          ????????//?昨日凈值
          ????????lastClose:?obj.dwjz,
          ????????//?漲跌幅
          ????????changeRate:?obj.gszzl,
          ????????//?漲跌額
          ????????changeAmount:?(obj.gsz?-?obj.dwjz).toFixed(4),
          ??????};
          ??????resultArr.push(info);
          ????});
          ????return?resultArr;
          ??});
          }

          接下來修改視圖數(shù)據(jù)。

          import?{?workspace,?TreeDataProvider,?TreeItem?}?from?'vscode';
          import?fundApi?from?'./api';

          export?default?class?DataProvider?implements?TreeDataProvider<FundInfo>?{
          ??//?省略了其他代碼
          ??getTreeItem(info:?FundInfo):?TreeItem?{
          ????//?展示名稱和漲跌幅
          ???const?{?name,?changeRate?}?=?info
          ????return?new?TreeItem(`${name}??${changeRate}`);
          ??}

          ??getChildren():?Promise?{
          ????const?{?order?}?=?this;
          ????//?獲取配置的基金代碼
          ????const?favorites:?string[]?=?workspace
          ??????.getConfiguration()
          ??????.get('fund-watch.favorites',?[]);
          ????
          ????//?獲取基金數(shù)據(jù)
          ??return?fundApi([...favorites]).then(
          ??????(results:?FundInfo[])?=>?results.sort(
          ???????(prev,?next)?=>?(prev.changeRate?>=?next.changeRate???1?:?-1)?*?order
          ?????)
          ????);
          ??}
          }

          視圖數(shù)據(jù)

          美化格式

          前面我們都是通過直接實(shí)例化 TreeItem 的方式來實(shí)現(xiàn) UI 的,現(xiàn)在我們需要重新構(gòu)造一個(gè) TreeItem

          import?{?workspace,?TreeDataProvider,?TreeItem?}?from?'vscode';
          import?FundItem?from?'./TreeItem';
          import?fundApi?from?'./api';

          export?default?class?DataProvider?implements?TreeDataProvider<FundInfo>?{
          ??//?省略了其他代碼
          ??getTreeItem(info:?FundInfo):?FundItem?{
          ????return?new?FundItem(info);
          ??}
          }
          //?TreeItem
          import?{?TreeItem?}?from?'vscode';

          export?default?class?FundItem?extends?TreeItem?{
          ??info:?FundInfo;

          ??constructor(info:?FundInfo)?{
          ????const?icon?=?Number(info.changeRate)?>=?0???'?'?:?'?';

          ????//?加上?icon,更加直觀的知道是漲還是跌
          ????super(`${icon}${info.name}???${info.changeRate}%`);

          ????let?sliceName?=?info.name;
          ????if?(sliceName.length?>?8)?{
          ??????sliceName?=?`${sliceName.slice(0,?8)}...`;
          ????}
          ????const?tips?=?[
          ??????`代碼:?${info.code}`,
          ??????`名稱:?${sliceName}`,
          ??????`--------------------------`,
          ??????`單位凈值:????${info.now}`,
          ??????`漲跌幅:?????${info.changeRate}%`,
          ??????`漲跌額:?????${info.changeAmount}`,
          ??????`昨收:??????${info.lastClose}`,
          ????];

          ????this.info?=?info;
          ????//?tooltip?鼠標(biāo)懸停時(shí),展示的內(nèi)容
          ????this.tooltip?=?tips.join('\r\n');
          ??}
          }
          美化后

          更新數(shù)據(jù)

          TreeDataProvider 需要提供一個(gè) onDidChangeTreeData 屬性,該屬性是 EventEmitter 的一個(gè)實(shí)例,然后通過觸發(fā) EventEmitter 實(shí)例進(jìn)行數(shù)據(jù)的更新,每次調(diào)用 refresh 方法相當(dāng)于重新調(diào)用了 getChildren 方法。

          import?{?workspace,?Event,?EventEmitter,?TreeDataProvider?}?from?'vscode';
          import?FundItem?from?'./TreeItem';
          import?fundApi?from?'./api';

          export?default?class?DataProvider?implements?TreeDataProvider<FundInfo>?{
          ??private?refreshEvent:?EventEmitternull>?=?new?EventEmitternull>();
          ??readonly?onDidChangeTreeData:?Eventnull>?=?this.refreshEvent.event;

          ??refresh()?{
          ????//?更新視圖
          ????setTimeout(()?=>?{
          ??????this.refreshEvent.fire(null);
          ????},?200);
          ??}
          }

          我們回到 extension.ts,添加一個(gè)定時(shí)器,讓數(shù)據(jù)定時(shí)更新。

          import?{?ExtensionContext,?commands,?window,?workspace?}?from?'vscode'
          import?Provider?from?'./data/Provider'

          //?激活插件
          export?function?activate(context:?ExtensionContext)?{
          ??//?獲取?interval?配置
          ??let?interval?=?workspace.getConfiguration().get('fund-watch.interval',?2)
          ??if?(interval?2)?{
          ????interval?=?2
          ??}

          ??//?基金類
          ??const?provider?=?new?Provider()

          ??//?數(shù)據(jù)注冊
          ??window.registerTreeDataProvider('fund-list',?provider)

          ??//?定時(shí)更新
          ??setInterval(()?=>?{
          ????provider.refresh()
          ??},?interval?*?1000)
          }

          export?function?deactivate()?{}

          除了定時(shí)更新,我們還需要提供手動(dòng)更新的能力。修改 package.json,注冊命令。

          {
          ??"contributes":?{
          ??"commands":?[
          ???{
          ????"command":?"fund.refresh",
          ????"title":?"刷新",
          ????"icon":?{
          ?????"light":?"images/light/refresh.svg",
          ?????"dark":?"images/dark/refresh.svg"
          ????}
          ???}
          ??],
          ??"menus":?{
          ???"view/title":?[
          ????{
          ?????"when":?"view?==?fund-list",
          ?????"group":?"navigation",
          ?????"command":?"fund.refresh"
          ????}
          ???]
          ??}
          ?}
          }
          • commands:用于注冊命令,指定命令的名稱、圖標(biāo),以及 command 用于 extension 中綁定相應(yīng)事件;
          • menus:用于標(biāo)記命令展示的位置;
            • when:定義展示的視圖,具體語法可以查閱官方文檔;
            • group:定義菜單的分組;
            • command:定義命令調(diào)用的事件;
          view-actions

          配置好命令后,回到 extension.ts 中。

          import?{?ExtensionContext,?commands,?window,?workspace?}?from?'vscode';
          import?Provider?from?'./Provider';

          //?激活插件
          export?function?activate(context:?ExtensionContext)?{
          ??let?interval?=?workspace.getConfiguration().get('fund-watch.interval',?2);
          ??if?(interval?2)?{
          ????interval?=?2;
          ??}

          ??//?基金類
          ??const?provider?=?new?Provider();

          ??//?數(shù)據(jù)注冊
          ??window.registerTreeDataProvider('fund-list',?provider);

          ??//?定時(shí)任務(wù)
          ??setInterval(()?=>?{
          ????provider.refresh();
          ??},?interval?*?1000);

          ??//?事件
          ??context.subscriptions.push(
          ????commands.registerCommand('fund.refresh',?()?=>?{
          ??????provider.refresh();
          ????}),
          ??);
          }

          export?function?deactivate()?{}

          現(xiàn)在我們就可以手動(dòng)刷新了。

          image-20200824113219392

          新增基金

          我們新增一個(gè)按鈕用了新增基金。

          {
          ??"contributes":?{
          ??"commands":?[
          ??????{
          ????????"command":?"fund.add",
          ????????"title":?"新增",
          ????????"icon":?{
          ??????????"light":?"images/light/add.svg",
          ??????????"dark":?"images/dark/add.svg"
          ????????}
          ??????},
          ???{
          ????"command":?"fund.refresh",
          ????"title":?"刷新",
          ????"icon":?{
          ?????"light":?"images/light/refresh.svg",
          ?????"dark":?"images/dark/refresh.svg"
          ????}
          ???}
          ??],
          ??"menus":?{
          ???"view/title":?[
          ????????{
          ??????????"command":?"fund.add",
          ??????????"when":?"view?==?fund-list",
          ??????????"group":?"navigation"
          ????????},
          ????{
          ?????"when":?"view?==?fund-list",
          ?????"group":?"navigation",
          ?????"command":?"fund.refresh"
          ????}
          ???]
          ??}
          ?}
          }

          extension.ts 中注冊事件。

          import?{?ExtensionContext,?commands,?window,?workspace?}?from?'vscode';
          import?Provider?from?'./Provider';

          //?激活插件
          export?function?activate(context:?ExtensionContext)?{
          ??//?省略部分代碼?...
          ??
          ??//?基金類
          ??const?provider?=?new?Provider();

          ??//?事件
          ??context.subscriptions.push(
          ????commands.registerCommand('fund.add',?()?=>?{
          ??????provider.addFund();
          ????}),
          ????commands.registerCommand('fund.refresh',?()?=>?{
          ??????provider.refresh();
          ????}),
          ??);
          }

          export?function?deactivate()?{}

          實(shí)現(xiàn)新增功能,修改 Provider.ts

          import?{?workspace,?Event,?EventEmitter,?TreeDataProvider?}?from?'vscode';
          import?FundItem?from?'./TreeItem';
          import?fundApi?from?'./api';

          export?default?class?DataProvider?implements?TreeDataProvider<FundInfo>?{
          ??//?省略部分代碼?...

          ??//?更新配置
          ??updateConfig(funds:?string[])?{
          ????const?config?=?workspace.getConfiguration();
          ????const?favorites?=?Array.from(
          ??????//?通過?Set?去重
          ??????new?Set([
          ????????...config.get('fund-watch.favorites',?[]),
          ????????...funds,
          ??????])
          ????);
          ????config.update('fund-watch.favorites',?favorites,?true);
          ??}

          ??async?addFund()?{
          ????//?彈出輸入框
          ????const?res?=?await?window.showInputBox({
          ??????value:?'',
          ??????valueSelection:?[5,?-1],
          ??????prompt:?'添加基金到自選',
          ??????placeHolder:?'Add?Fund?To?Favorite',
          ??????validateInput:?(inputCode:?string)?=>?{
          ????????const?codeArray?=?inputCode.split(/[\W]/);
          ????????const?hasError?=?codeArray.some((code)?=>?{
          ??????????return?code?!==?''?&&?!/^\d+$/.test(code);
          ????????});
          ????????return?hasError???'基金代碼輸入有誤'?:?null;
          ??????},
          ????});
          ????if?(!!res)?{
          ??????const?codeArray?=?res.split(/[\W]/)?||?[];
          ??????const?result?=?await?fundApi([...codeArray]);
          ??????if?(result?&&?result.length?>?0)?{
          ????????//?只更新能正常請求的代碼
          ????????const?codes?=?result.map(i?=>?i.code);
          ????????this.updateConfig(codes);
          ????????this.refresh();
          ??????}?else?{
          ????????window.showWarningMessage('stocks?not?found');
          ??????}
          ????}
          ??}
          }
          新增按鈕
          輸入框

          刪除基金

          最后新增一個(gè)按鈕,用來刪除基金。

          {
          ?"contributes":?{
          ??"commands":?[
          ???{
          ????"command":?"fund.item.remove",
          ????"title":?"刪除"
          ???}
          ??],
          ??"menus":?{
          ??????//?這個(gè)按鈕放到?context?中
          ??????"view/item/context":?[
          ????????{
          ??????????"command":?"fund.item.remove",
          ??????????"when":?"view?==?fund-list",
          ??????????"group":?"inline"
          ????????}
          ??????]
          ??}
          ??}
          }

          extension.ts 中注冊事件。

          import?{?ExtensionContext,?commands,?window,?workspace?}?from?'vscode';
          import?Provider?from?'./Provider';

          //?激活插件
          export?function?activate(context:?ExtensionContext)?{
          ??
          //?省略部分代碼?...
          ??

          ??
          //?基金類
          ??
          const?provider?=?new?Provider();

          ??
          //?事件
          ??context.subscriptions.push(

          ????commands.registerCommand(
          'fund.add',?()?=>?{
          ??????provider.addFund();

          ????}),

          ????commands.registerCommand(
          'fund.refresh',?()?=>?{
          ??????provider.refresh();

          ????}),

          ????commands.registerCommand(
          'fund.item.remove',?(fund)?=>?{
          ??????
          const?{ code }?=?fund;
          ??????provider.removeConfig(code);

          ??????provider.refresh();

          ????})

          ??);

          }


          export?function?deactivate()?{}

          實(shí)現(xiàn)新增功能,修改 Provider.ts

          import?{?window,?workspace,?Event,?EventEmitter,?TreeDataProvider?}?from?'vscode';
          import?FundItem?from?'./TreeItem';
          import?fundApi?from?'./api';

          export?default?class?DataProvider?implements?TreeDataProvider<FundInfo>?{
          ??//?省略部分代碼?...

          ??//?刪除配置
          ??removeConfig(code:?string)?{
          ????const?config?=?workspace.getConfiguration();
          ????const?favorites:?string[]?=?[...config.get('fund-watch.favorites',?[])];
          ????const?index?=?favorites.indexOf(code);
          ????if?(index?===?-1)?{
          ??????return;
          ????}
          ????favorites.splice(index,?1);
          ????config.update('fund-watch.favorites',?favorites,?true);
          ??}
          }
          刪除按鈕

          總結(jié)

          實(shí)現(xiàn)過程中也遇到了很多問題,遇到問題可以多翻閱 VSCode 插件中文文檔。該插件已經(jīng)發(fā)布的了 VS Code 插件市場,感興趣的可以直接下載該插件,或者在 github 上下載完整代碼。

          ??愛心三連擊

          1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的點(diǎn)贊在看是我創(chuàng)作的動(dòng)力。

          2.關(guān)注公眾號程序員成長指北,回復(fù)「1」加入Node進(jìn)階交流群!「在這里有好多 Node 開發(fā)者,會(huì)討論 Node 知識,互相學(xué)習(xí)」!

          3.也可添加微信【ikoala520】,一起成長。


          “在看轉(zhuǎn)發(fā)”是最大的支持

          瀏覽 74
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人网在线观看了 | 伊人大香蕉伊人在线 | 亲子乱一区二区三区电影 | 偷拍精品一区二区三区 | 特级一级a片 |