Blazor 使用JS脚本库
1、前言
由于项目需求,需要BS与CS同时存在,一开始使用WPF已经写好了页面,要转成BS端也能实现,目前比较好的工具就是UNO和Avalonia两大工具,能使用xaml编写UI界面。
首先试用了Avalonia,发现他web端使用的wasm,对中文的支持不太好,web端显示的中文直接变成方框,网上搜了一大堆,也没找到好的解决方案。
然后是Uno platform,说实话体验确实比Avalonia好,也支持web端中文,同样是wasm。不过还是有问题,首先当前项目需要将数据以图表的形式显示出来,图表还需支持多个y轴,自由缩放等功能,而uno支持的图表少之甚少,就是 生态 不行。而且对原生的api也有做修改,对与原本开发好的xaml文件需要一边看报错和官方文档一边修改代码。
最最重要的是,我认为最理想的跨平台开发,就是写一套UI代码,换平台的时候只需要编译一下就能运行了,而这两个官方提供的模板里的共享UI项目是.shproj,和默认是.csporj不一样,装不上nuget包,研究了一天找不到解决办法,看别人安装都是给其他跨平台项目里安装,可是安装后直接报错,遂放弃,以后有机会再研究吧。
对于其他的几个平台,比如MAUI,微软新出的跨平台解决方案,我个人感觉还有待改进,并不成熟,用在项目里有风险;Electron在互联网使用的很多,相对成熟,可是他用的是js编写的,用html和css设计界面,我对js不熟悉,从头搞一套框架学习成本略高。一开始找xaml跨平台方案就是不想写js。
最后只能选择妥协却不完全妥协的方案,那就是Blazor,用c#代替js,虽然还是html+css,好在有对应的组件库可以使用,并且是支持js调用的,不用担心找不到需要的图表组件,撸少量js代码实现功能还是能接受的。其中Blazor Server的加载速度也比wasm快得多,并且MAUI就支持Blazor组件,挺看好生态的。
以下以导入chartjs这个图表库为例。
2、安装ChartJs
首先去github下载最新的js包,复制到共享UI库的wwwroot文件夹下,我这里是放在js文件夹下。官方文档
修改Pages下的_Layout.cshtml ,标签加入以下代码,_Layout.cshtml是web端页面,wpf下是index.html
文档推荐的是用cdn链接,我们已经下载了源码就直接使用了,_content表示项目内容,后面跟着引用的项目名称,再接着就是wwwroot下的目录。
官方
3、使用自己的js脚本
安装chartjs官方的教程还需要用js创建数据,同样在js文件夹下创建js文件。
mychart.js代码
const labels = [
'January',
'February',
'March',
'April',
'May',
'June',
];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
}, {
label: 'My Srcond dataset',
backgroundColor: 'rgb(55, 99, 132)',
borderColor: 'rgb(55, 99, 132)',
data: [0, 20, 15, 22, 40, 10, 65],
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
function myChartJsRun() {
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
在_Layout.cshtml 中加入引用,wpf就是index.html,后面就不再赘述了。
4、示例
Pages文件夹下创建Chart.razor,注入IJSRuntime,创建按钮,点击后执行调用js脚本。
@page "/chart"
@inject IJSRuntime JS
Chart
Chart
@code
async Task clickConsole()
{
await JS.InvokeVoidAsync("myChartJsRun");
}
}
执行结果,点击console后生成图表。
4、 JavaScript 隔离
相当于按需加载js,这样就不需要每次都在_Layout.razor的中添加引用了。
JS 隔离具有以下优势:
- 导入的 JS 不再污染全局命名空间。
- 库和组件的使用者不需要导入相关的 JS。
首先js脚本需要做一点修改,使用export导出函数。
const labels = [
'January',
'February',
'March',
'April',
'May',
'June',
];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
}, {
label: 'My Srcond dataset',
backgroundColor: 'rgb(55, 99, 132)',
borderColor: 'rgb(55, 99, 132)',
data: [0, 20, 15, 22, 40, 10, 65],
}]
};
const config = {
type: 'line',
data: data,
options: {}
};
export { myChartJsRun };
function myChartJsRun() {
const myChart = new Chart(
document.getElementById('myChart'),
config
);
}
Chart.razor 添加页面第一次加载时加载js脚本,并且在加载后执行图表创建。
@page "/chart"
@inject IJSRuntime JS
Chart
Chart
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync("import",
"./_content/ManagerBlazor.Shared/js/myjs/mychart.js");
await module.InvokeVoidAsync("myChartJsRun");
}
}
}
在调试中能看到打开主页是没有mychart.js的加载,转到chart页面后才加载。
5、结语
web很强大,我甚至感觉是未来,生态的真的好。Blazor结合了web和c#语言的优势,潜力巨大!