日韩性视频-久久久蜜桃-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插件的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 精品黄色av | 天天射天天干天天色 | 一极毛片 | 久久免费看片 | 日韩久久影视 | 久久艳片www.17c.com | 中文字幕人妻熟女人妻a片 麻豆91视频 | 97人人视频 | 在线免费观看 | 亚洲狼人av | 国产一级特黄aaa大片 | 理论片第一页 | 丰满人妻在公车被猛烈进入电影 | 大陆av片| 黄色应用在线观看 | 91精品国产综合久久精品图片 | 91亚洲国产成人精品一区 | 在线观看av的网址 | 手机在线观看av网站 | 狠狠狠狠狠干 | 粗大的内捧猛烈进出在线视频 | 超碰在线国产 | 精品视频久久久久久 | av夜色| 天堂中文在线看 | 久久久久久久久久久久久久久久久久久久 | 伊人网在线视频 | 一区二区三区福利视频 | 涩里番在线观看 | 久久伊人操 | 国产精品麻豆果冻传媒在线播放 | 成人免费在线视频网站 | 亚洲精品911 | 奇米网久久| 亚洲欧美日韩国产一区二区三区 | 亚洲精品国产精品国自产观看浪潮 | 欧美a级黄色 | 欧美成人黄色网 | 日韩av免费在线看 | 毛片专区 | 国产精品久久久久久三级 | 国产夫绿帽单男3p精品视频 | 天天天天干 | 亚洲精品鲁一鲁一区二区三区 | 在线观看欧美国产 | 韩国三级hd中文字幕的背景音乐 | 国产主播中文字幕 | 五月激情久久 | 91在线中文 | 高清国产一区二区三区四区五区 | 亚洲精品一二三四区 | 中文字幕日韩一区二区三区 | 桃色一区 | 久久精久久 | 色屁屁在线 | jizz日本视频 | 最近中文字幕免费视频 | 欧美老熟妇乱xxxxx | 成人短视频在线免费观看 | av九九九 | 一区二区三区国产精品 | 91黄版| 精久久久 | 成人极品| 久久久久一区二区三区四区 | 深夜福利免费视频 | 992tv在线影院| 成人免费网站在线观看 | 国产亚洲片 | 午夜视频导航 | 99er热精品视频 | 亚洲男女网站 | 欧美黑人巨大xxx极品 | 激情国产在线 | 国产一区视频在线播放 | 狼人精品一区二区三区在线 | 久久99久久99精品 | 欧美成人一二三区 | 精品少妇一区二区三区免费观 | 波多野结衣 久久 | 黑帮大佬和我的三百六十五天 | 国产伦精品一区二区三区视频痴汉 | 久久久无码一区二区三区 | 香蕉视频亚洲 | 欧美激情69 | 99久久99| 亚洲一区视频在线 | 久久久青青 | 男人天堂欧美 | 一区二区三区在线视频观看 | 麻豆免费观看网站 | av污在线观看 | 一女被多男玩喷潮视频 | 国产51精品 | 国产艳妇疯狂做爰视频 | 欧美男女交配 | 亚洲第一成人网站 | 亚洲aa| 精品人妻av一区二区 |