日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

blazor wasm开发chrome插件

發布時間:2023/12/4 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 blazor wasm开发chrome插件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用blazor(Wasm)開發了一個chrome插件感覺效率挺高的,分享給大家

先簡單介紹下WebAssembly的原理:

“WebAssembly是一種用于基于堆棧的虛擬機的二進制指令格式”

image

如上圖,瀏覽器在執行js時是會經歷 Parser轉成語法樹->Compiler轉成字節碼->JIT即時字節碼解釋執行

因為WebAssembly 模塊已經被編譯成一種 JavaScript 字節碼形式,現代支持 WebAssembly 的 JavaScript 引擎可以在其 JIT 組件中可以直接解釋執行!

mono團隊把開源跨平臺.NET運行時Mono(也是unity3d的運行時)編譯成了WebAssembly ,那么開發的.net程序就可以通過這個運行時在瀏覽器中加載net程序執行。

近日vs2022發布了,blazor的功能得到進一步提升,

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

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

進入正題

開發瀏覽器插件,常見的就是按照插件的這幾塊api來進行擴展

  • 右鍵菜單擴展

  • Backgroud(可以理解為每個插件都有一個后臺一直運行的模塊)

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

  • contentScript(嵌入到你想要嵌入的網站內執行)

  • devtools(開發面板擴展模塊)

首先基于這個大佬的模板搭建工程

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

基于模板的話會幫你引入哪些包

image

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

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

  • Backgroud用csharp寫

  • popup,option等的html不要用balzor寫,balzor加載html沒有任何優勢

  • contentScript用js寫,內嵌到網站的,如果是balzor的話會初始化的時候卡1~2s左右,這個會嚴重影響體驗

  • js和csharp交互

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

    右鍵菜單擴展

    在BackGround里面寫,包括響應事件

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

    contentScript/popup等

    用js寫,有2種方式來和Backgroud通訊

    1. 事件一來一回的方式

    contentScript中發送消息給BackGround

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

    BackGround注冊事件用來接收js發過來的消息

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

    2. 長連接方式

    js端

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

    csharp端

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

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

    配置/存儲相關

    有兩種方法:

    1. chrome.storage.local

    這里我封裝了一個類專門操作

    public?class?ChromLocalStorage {private?readonly?IWebExtensionsApi?_webExtensionsApi;private?readonly?IJSRuntime?_jsRuntime;public?ChromLocalStorage(IWebExtensionsApi?webExtensionsApi,?IJSRuntime?JsRuntime){_webExtensionsApi?=?webExtensionsApi;_jsRuntime?=?JsRuntime;}///?<summary>///?調用chrom.storage.local?set?把?key?和?value設置進去///?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);}//轉成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推出的新技術:采用EFCore + Sqlite

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

    下載下來后放入工程中,然后引入

    image

    這里還有一個關鍵

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

    下載這個js后放入工程中,這個js是將sqlite和本地的indexdb進行同步的

    //EF的DbContext public?class?ClientSideDbContext?:?DbContext {//定義你要存儲的表模型public?DbSet<Part>?Parts?{?get;?set;?}?=?default!;public?ClientSideDbContext(DbContextOptions<ClientSideDbContext>?options):?base(options){}protected?override?void?OnModelCreating(ModelBuilder?modelBuilder){base.OnModelCreating(modelBuilder);//設置你的表的索引等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進行注冊

    那么你就可以在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寫起來更爽更高效,拿到db上下文 就可以很簡單的操作插件里面所有用到存儲配置等!

    這種方式比較適合了解.net生態的人,結合.net的一些庫還可以實現很多好玩的功能

    • excel導出

    • 二維碼生成

    • ajax攔截,轉發等


    我是正東,開發chrome插件其實很簡單,這種方式對于我來說比較高效 哈哈

    歡迎白嫖 順手點個贊吧!

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 永久免费视频网站直接看 | 久久另类ts人妖一区二区 | 精品福利视频一区二区 | 国产精品三级在线观看无码 | 国产又大又粗又长 | 国产又粗又长又黄视频 | 日本污污网站 | 久色国产| 性盈盈影院中文字幕 | youjizzcom日本 | www99热| 成了校长的性脔h文 | 国产性猛交xxxx免费看久久 | 嫩草影院av| 高清av网址| 国产成人综合视频 | 2019av视频| 色片免费看 | 可以直接在线观看的av | 在线观看二区 | 欧美美女一级片 | 欧美一区二区最爽乱淫视频免费看 | 午夜蜜桃视频 | 无码黑人精品一区二区 | 99热一区二区三区 | 日本人体视频 | 91精品黄色 | 国产在线精品福利 | 亚洲爆乳无码精品aaa片蜜桃 | 国产一在线 | 激情文学亚洲 | 97高清国语自产拍 | 九九超碰| 成年人在线免费观看视频网站 | 操一操视频 | 久久久久久久网 | 久久视频免费在线观看 | 欧美日韩性生活视频 | 久久久综合网 | 亚洲精品一区二区三区婷婷月 | av无码一区二区三区 | 小少妇哺乳喂奶播放 | 久久人人爽人人爽人人片av高清 | 精品久久久久久久 | 国产精品久久综合视频 | 日本一区二区观看 | 免费中文字幕av | 波多野结衣国产 | xnxx国产| 乱子伦一区二区三区 | 久久久久国产一区二区三区 | 一本色道久久综合狠狠躁 | 天堂在线观看av | 亚洲一区二区免费电影 | 欧美国产在线视频 | 日本69熟| 久久精品第一页 | 久久人人看 | 欧美日韩色图片 | 中文字幕一级片 | 男人天堂av在线播放 | 激情五月激情 | 无码人妻精品一区二区三区99不卡 | 久久国产精品一区二区三区 | 探花精品| 首尔之春在线看 | 香蕉视频污在线观看 | 欧美老肥妇做.爰bbww视频 | 日韩av综合网 | 精品九九在线 | 精品日韩一区二区 | 农村老女人av | 午夜精品美女久久久久av福利 | 麻豆视频在线观看免费网站 | 中文有码视频 | 欧美一级在线观看 | 蜜桃视频欧美 | 夜夜嗨av一区二区三区网页 | 猛1被调教成公厕尿便失禁网站 | 黄色不卡av | 亚洲国产精品无码久久久 | 日韩精品一区二区三区不卡在线 | 久久另类ts人妖一区二区 | 岛国a视频| 毛片网站在线免费观看 | 欧美精产国品一二三区 | 91视色| 4438全国成人免费 | 精品在线视频免费观看 | 亚洲一区欧美二区 | 亚洲天堂av免费在线观看 | 午夜视频一区 | 亚洲AV无码一区二区伊人久久 | 香港三级日本三级韩国三级 | 亚洲天堂网在线视频 | 无码精品人妻一区二区三区漫画 | 中文字幕在线观看亚洲 | 色婷婷久 | 大战熟女丰满人妻av |