日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

blazor wasm开发chrome插件

發(fā)布時(shí)間:2023/12/4 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 blazor wasm开发chrome插件 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

用blazor(Wasm)開(kāi)發(fā)了一個(gè)chrome插件感覺(jué)效率挺高的,分享給大家

先簡(jiǎn)單介紹下WebAssembly的原理:

“WebAssembly是一種用于基于堆棧的虛擬機(jī)的二進(jìn)制指令格式”

image

如上圖,瀏覽器在執(zhí)行js時(shí)是會(huì)經(jīng)歷 Parser轉(zhuǎn)成語(yǔ)法樹(shù)->Compiler轉(zhuǎn)成字節(jié)碼->JIT即時(shí)字節(jié)碼解釋執(zhí)行

因?yàn)閃ebAssembly 模塊已經(jīng)被編譯成一種 JavaScript 字節(jié)碼形式,現(xiàn)代支持 WebAssembly 的 JavaScript 引擎可以在其 JIT 組件中可以直接解釋執(zhí)行!

mono團(tuán)隊(duì)把開(kāi)源跨平臺(tái).NET運(yùn)行時(shí)Mono(也是unity3d的運(yùn)行時(shí))編譯成了WebAssembly ,那么開(kāi)發(fā)的.net程序就可以通過(guò)這個(gè)運(yùn)行時(shí)在瀏覽器中加載net程序執(zhí)行。

近日vs2022發(fā)布了,blazor的功能得到進(jìn)一步提升,

  • 支持AOT將.NET代碼直接編譯為WebAssembly字節(jié)碼

  • 支持NativeFileReference添加c語(yǔ)言和rust等原生依賴(手動(dòng)狗頭)

進(jìn)入正題

開(kāi)發(fā)瀏覽器插件,常見(jiàn)的就是按照插件的這幾塊api來(lái)進(jìn)行擴(kuò)展

  • 右鍵菜單擴(kuò)展

  • Backgroud(可以理解為每個(gè)插件都有一個(gè)后臺(tái)一直運(yùn)行的模塊)

  • popup(瀏覽器右上角點(diǎn)擊插件彈出的窗口模塊)

  • contentScript(嵌入到你想要嵌入的網(wǎng)站內(nèi)執(zhí)行)

  • devtools(開(kāi)發(fā)面板擴(kuò)展模塊)

首先基于這個(gè)大佬的模板搭建工程

https://github.com/mingyaulee/Blazor.BrowserExtension

基于模板的話會(huì)幫你引入哪些包

image

我也躺了很多坑,看看我給大佬提的issue,和大佬一起成長(zhǎng)

這里我總結(jié)一套非常高效的方案給大家:

  • Backgroud用csharp寫(xiě)

  • popup,option等的html不要用balzor寫(xiě),balzor加載html沒(méi)有任何優(yōu)勢(shì)

  • contentScript用js寫(xiě),內(nèi)嵌到網(wǎng)站的,如果是balzor的話會(huì)初始化的時(shí)候卡1~2s左右,這個(gè)會(huì)嚴(yán)重影響體驗(yàn)

  • js和csharp交互

    這里把BackGround(csharp開(kāi)發(fā))作為插件后端 html和js作為插件的前端的方式

    右鍵菜單擴(kuò)展

    在BackGround里面寫(xiě),包括響應(yīng)事件

    //選中跳轉(zhuǎn)菜單 await?WebExtensions.ContextMenus.Create(new?WebExtensions.Net.Menus.CreateProperties {Title?=?"測(cè)試菜單",Contexts?=?new?List<ContextType>{ContextType.Selection},//data是選中的內(nèi)容包裝對(duì)象Onclick?=?async?(data,?tab)?=>?{?await?test(data).ConfigureAwait(false);?} },?EmptyAction);//非選中跳轉(zhuǎn)菜單await?WebExtensions.ContextMenus.Create(new?WebExtensions.Net.Menus.CreateProperties {Title?=?"跳轉(zhuǎn)百度",Onclick?=?async?(d,?tab)?=>?{?await?OpenUrl("https://www.baidu.com").ConfigureAwait(false);?} },?EmptyAction);

    contentScript/popup等

    用js寫(xiě),有2種方式來(lái)和Backgroud通訊

    1. 事件一來(lái)一回的方式

    contentScript中發(fā)送消息給BackGround

    chrome.runtime.sendMessage("消息體",?function?()?{?});chrome.runtime.onMessage.addListener(function?(request,?sender,?sendResponse)?{//處理backgroup發(fā)來(lái)的消息});

    BackGround注冊(cè)事件用來(lái)接收js發(fā)過(guò)來(lái)的消息

    //注冊(cè)事件接收js過(guò)來(lái)的消息 await?WebExtensions.Runtime.OnMessage.AddListener(OnReceivedCommand);//處理事件 private?bool?OnReceivedCommand(object?obj,?MessageSender?sender,?Action?action){Console.WriteLine("OnCommand:"?+?key?+?$",from?TabId:{sender.Tab.Id}");//處理完成后發(fā)送事件給js那邊await?WebExtensions.Tabs.SendMessage(sender.Tab.Id.Value,?"處理完成了",?new?SendMessageOptions()); }

    2. 長(zhǎng)連接方式

    js端

    var?port?=?chrome.extension.connect({name:?"test" });port.onMessage.addListener(function?(msg)?{console.log(msg); });$('#test').click(e?=>?{port.postMessage('發(fā)消息'); });

    csharp端

    await?WebExtensions.Runtime.OnConnect.AddListener(port?=> {Console.WriteLine(port.Name?+?"---》connection");port.OnMessage.AddListener(new?DelegateMethod(async?(msg)?=>{//處理消息}));});

    目前這種方式有一個(gè)需要優(yōu)化,就是無(wú)法在csharp端主動(dòng)推送消息給js端 給大佬提了issue了,相信很快可以fix https://github.com/mingyaulee/WebExtensions.Net/issues/14

    配置/存儲(chǔ)相關(guān)

    有兩種方法:

    1. chrome.storage.local

    這里我封裝了一個(gè)類專門(mén)操作

    public?class?ChromLocalStorage {private?readonly?IWebExtensionsApi?_webExtensionsApi;private?readonly?IJSRuntime?_jsRuntime;public?ChromLocalStorage(IWebExtensionsApi?webExtensionsApi,?IJSRuntime?JsRuntime){_webExtensionsApi?=?webExtensionsApi;_jsRuntime?=?JsRuntime;}///?<summary>///?調(diào)用chrom.storage.local?set?把?key?和?value設(shè)置進(jìn)去///?key返回///?</summary>///?<param?name="value"></param>///?<param?name="existKey"></param>///?<returns></returns>public?async?Task<string>?localSet(string?value,string?existKey??=?null){var?key?=?existKey????"key_"?+?DateTime.Now.ToString("yyyyMMddHHmmss");byte[]?bytes?=?Encoding.UTF8.GetBytes(value);var?encode?=?Convert.ToBase64String(bytes);var?jss?=?"var?"?+?key?+?"?=?{'"?+?key?+?"':'"?+?encode?+?"'}";await?_jsRuntime.InvokeVoidAsync("eval",?jss);object?data2?=?await?_jsRuntime.InvokeAsync<object>("eval",?key);await?_jsRuntime.InvokeVoidAsync("chrome.storage.local.set",?data2);Console.WriteLine($"call?chrome.storage.local.set,key:{key},value:{value},base64Value:{encode}");return?key;}public?async?Task<string>?localSet<T>(T?value){if?(value?is?string?s){return?await?localSet(s,null);}//轉(zhuǎn)成jsonstringvar?serialize?=?JsonSerializer.Serialize(value);return?await?localSet(serialize,null);}public?async?Task<T>?localGet<T>(string?key){var?data?=?await?localGet(key);T?deserialize?=?JsonSerializer.Deserialize<T>(data);return?deserialize;}public?async?Task<string>?localGet(string?key,bool?remove=true){try{var?local?=?await?_webExtensionsApi.Storage.GetLocal();var?getData?=?await?local.Get(new?StorageAreaGetKeys(key));var?data?=?getData.ToString();if?(string.IsNullOrEmpty(data)){return?string.Empty;}var?value?=?data.Split(new?string[]?{?":\""?},?StringSplitOptions.None)[1].Split(new?string[]?{?"\""?},?StringSplitOptions.None)[0];var?str?=?Convert.FromBase64String(value);var?bastStr?=?Encoding.UTF8.GetString(str);//Console.WriteLine($"call?chrome.storage.local.get,key:{key},value:{bastStr},base64Value:{value}");if?(remove)?await?local.Remove(new?StorageAreaRemoveKeys(key));return?bastStr;}catch?(Exception?e){return?"";}}public?async?Task?localRemove(string?key){var?local?=?await?_webExtensionsApi.Storage.GetLocal();await?local.Remove(new?StorageAreaRemoveKeys(key));} }

    2. 6.0推出的新技術(shù):采用EFCore + Sqlite

    需要用到native的庫(kù) https://github.com/SteveSandersonMS/BlazeOrbital/blob/main/BlazeOrbital/ManufacturingHub/Data/e_sqlite3.o

    下載下來(lái)后放入工程中,然后引入

    image

    這里還有一個(gè)關(guān)鍵

    https://github.com/SteveSandersonMS/BlazeOrbital/blob/main/BlazeOrbital/ManufacturingHub/wwwroot/dbstorage.js

    下載這個(gè)js后放入工程中,這個(gè)js是將sqlite和本地的indexdb進(jìn)行同步的

    //EF的DbContext public?class?ClientSideDbContext?:?DbContext {//定義你要存儲(chǔ)的表模型public?DbSet<Part>?Parts?{?get;?set;?}?=?default!;public?ClientSideDbContext(DbContextOptions<ClientSideDbContext>?options):?base(options){}protected?override?void?OnModelCreating(ModelBuilder?modelBuilder){base.OnModelCreating(modelBuilder);//設(shè)置你的表的索引等modelBuilder.Entity<Part>().HasIndex(x?=>?x.Id);modelBuilder.Entity<Part>().HasIndex(x?=>?x.Name);modelBuilder.Entity<Part>().Property(x?=>?x.Name).UseCollation("nocase");} }//sqlite的初始化以及獲取DBContext的方法封裝 public?class?DataSynchronizer {public?const?string?SqliteDbFilename?=?"app.db";private?readonly?Task?firstTimeSetupTask;private?readonly?IDbContextFactory<ClientSideDbContext>?dbContextFactory;public?DataSynchronizer(IJSRuntime?js,?IDbContextFactory<ClientSideDbContext>?dbContextFactory){this.dbContextFactory?=?dbContextFactory;firstTimeSetupTask?=?FirstTimeSetupAsync(js);}public?async?Task<ClientSideDbContext>?GetPreparedDbContextAsync(){await?firstTimeSetupTask;return?await?dbContextFactory.CreateDbContextAsync();}private?async?Task?FirstTimeSetupAsync(IJSRuntime?js){//只加載一次?讓sqlite和indexdb同步var?module?=?await?js.InvokeAsync<IJSObjectReference>("import",?"./js/dbstorage.js");if?(RuntimeInformation.IsOSPlatform(OSPlatform.Create("browser"))){await?module.InvokeVoidAsync("synchronizeFileWithIndexedDb",?SqliteDbFilename);}using?var?db?=?await?dbContextFactory.CreateDbContextAsync();await?db.Database.EnsureCreatedAsync();}}image

    在Program.cs進(jìn)行注冊(cè)

    那么你就可以在Backgroud里面注入并在初始化方法中拿到db上下文

    [Inject]?public?DataSynchronizer?DataSynchronizer?{?get;?set;?}//db上下文 private?ClientSideDbContext?db;protected?override?async?Task?OnInitializedAsync() {await?base.OnInitializedAsync();db?=?await?DataSynchronizer.GetPreparedDbContextAsync(); }

    推薦用新的方式,EF寫(xiě)起來(lái)更爽更高效,拿到db上下文 就可以很簡(jiǎn)單的操作插件里面所有用到存儲(chǔ)配置等!

    這種方式比較適合了解.net生態(tài)的人,結(jié)合.net的一些庫(kù)還可以實(shí)現(xiàn)很多好玩的功能

    • excel導(dǎo)出

    • 二維碼生成

    • ajax攔截,轉(zhuǎn)發(fā)等


    我是正東,開(kāi)發(fā)chrome插件其實(shí)很簡(jiǎn)單,這種方式對(duì)于我來(lái)說(shuō)比較高效 哈哈

    歡迎白嫖 順手點(diǎn)個(gè)贊吧!

    總結(jié)

    以上是生活随笔為你收集整理的blazor wasm开发chrome插件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。