Blazor 混合开发_MAUI+Vue_WPF+Vue

Blazor 混合开发_MAUI+Vue_WPF+Vue

  • 背景
    • 混合开发的核心
    • 为什么必须使用 wwwroot 文件夹放置 Web 项目文件
  • 创建 MAUI 项目
    • 创建 wwwroot 文件夹
    • 服务注册
    • 创建 _import.razor
    • 添加 Main.razor 组件
    • 修改 MainPage.xaml 文件
  • 创建 WPF 项目
    • 创建 wwwroot 文件夹
    • 服务注册
    • 创建 _import.razor
    • 添加 Shell.razor 组件
    • 修改 MainWindow.xaml 文件
  • 创建 Vue 项目
    • 修改创建好的 Vue 项目
    • 执行 npm run build 命令
    • Copy dist
    • 修改 index.html 内容
  • 效果预览
  • Demo 下载

背景

  在 MAUI 微软的官方方案是使用 Blazor 开发,但是当前市场大多数的 Web 项目使用 Vue、React 等技术构建,用Blazor重写整个项目并不现实。

  Vue 是当前流行的 Web 框架, 简单来说是一套模板引擎,利用 “模板” 和 “绑定” 两大特性实现Web页面 MVVM 模式开发。利用 .NET MAUI 框架可以将 Vue 应用嵌入到 Web 容器中,可以实现跨平台的混合开发。

混合开发的核心

  • 混合开发的核心工作是构建 Web 与 .NET 的互操作,我们将利用 Blazor 引擎的如下功能:
    • 资源的统一管理
    • js 代码的注入
    • js 调用 C# 代码
    • C# 调用 js 代码

为什么必须使用 wwwroot 文件夹放置 Web 项目文件

这个文件夹将是混合开发Web部分的根目录,这个名称不能随便定义
在这里插入图片描述

Microsoft.AspNetCore.Components.WebView.Maui 库会将 wwwroot 文件夹里的内容作为 Maui 资源(MauiAsset)类型设置标签,编译器则会根据 MauiAsset 标签将这些内容打包进各个平台的资源文件夹。

创建 MAUI 项目

项目名字 MAUI.Vue.hybirddev
在这里插入图片描述
创建完成后编辑Hybrid.Maui.csproj,在Sdk最末尾加上.Razor,VS 会自动安装Microsoft.AspNetCore.Components.WebView.Maui 依赖包
不要手动 Nuget 添加这个包,否则程序无法运行
在这里插入图片描述
在这里插入图片描述

创建 wwwroot 文件夹

创建之后会自动变成网络资源文件夹在这里插入图片描述

服务注册

  • 使用扩展方法 builder.Services.AddMauiBlazorWebView() 对 BlazorMauiWebView 组件服务进行注册
using Microsoft.Extensions.Logging;namespace MAUI.Vue.hybirddev
{public static class MauiProgram{public static MauiApp CreateMauiApp(){var builder = MauiApp.CreateBuilder();builder.UseMauiApp<App>().ConfigureFonts(fonts =>{fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");});builder.Services.AddMauiBlazorWebView(); // 注册#if DEBUGbuilder.Services.AddBlazorWebViewDeveloperTools();builder.Logging.AddDebug();
#endifreturn builder.Build();}}
}

创建 _import.razor

添加 → 类 → Razor 组件
在这里插入图片描述
导入 namespace

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Hybrid.Maui @*当前项目名称*@

添加 Main.razor 组件

  • 被JS调用的方法必须是静态的
  • Dispose 销毁页面资源,防止内存溢出
@inject IJSRuntime JSRuntime
@implements IDisposable@code {[JSInvokable]public static Task<string> Test(){return Task.FromResult("Maui Test Function");}public void Dispose(){}
}

修改 MainPage.xaml 文件

建立 BlazorWebView 控件铺满屏幕,并设置 HostPage 为Web部分的主页 index.html

<?xml version="1.0" encoding="utf-8" ?>
<ContentPagex:Class="Hybrid.Maui.MainPage"xmlns="http://schemas.microsoft.com/dotnet/2021/maui"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:local="clr-namespace:Hybrid.Maui"Shell.NavBarIsVisible="False"><BlazorWebView HostPage="wwwroot/index.html"><BlazorWebView.RootComponents><RootComponent ComponentType="{x:Type local:Main}" Selector="#blazorApp" /></BlazorWebView.RootComponents></BlazorWebView></ContentPage>

创建 WPF 项目

项目名字 Hybrid.Wpf
在这里插入图片描述
创建完成后编辑Hybrid.Wpf.csproj,在Sdk最末尾加上.Razor
同时在项目文件的现有 <PropertyGroup> 中,添加 <RootNamespace>Hybrid.Wpf</RootNamespace> 标记
在这里插入图片描述

安装 Nuget 包 Microsoft.AspNetCore.Components.WebView.Wpf
在这里插入图片描述

创建 wwwroot 文件夹

创建之后会自动变成网络资源文件夹
在这里插入图片描述

服务注册

  • 通过依赖注入容器注入 AddWpfBlazorWebView() 服务
  • 在资源中添加已注册的服务 Resources.Add("services", Services)
  • 删除App.xaml 中的 StartupUri="MainWindow.xaml"
using System.Windows;
using Microsoft.Extensions.DependencyInjection;namespace Hybrid.Wpf
{/// <summary>/// Interaction logic for App.xaml/// </summary>public partial class App : Application{public App(){Services = ConfigureServices();Resources.Add("services", Services);}public new static App Current => (App)Application.Current;public IServiceProvider Services { get; }protected override void OnStartup(StartupEventArgs e){Services.GetRequiredService<MainWindow>().Show();}private static IServiceProvider ConfigureServices(){var serviceCollection = new ServiceCollection();serviceCollection.AddSingleton<MainWindow>();serviceCollection.AddWpfBlazorWebView();#if DEBUGserviceCollection.AddBlazorWebViewDeveloperTools();
#endifreturn serviceCollection.BuildServiceProvider();}}
}

创建 _import.razor

添加 → 类 → Razor 组件
在这里插入图片描述
导入 namespace

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Hybrid.Wpf @*Object Namespace*@

添加 Shell.razor 组件

  • 被JS调用的方法必须是静态的
  • Dispose 销毁页面资源,防止内存溢出
@inject IJSRuntime JSRuntime
@implements IDisposable@code {[JSInvokable]public static Task<string> Test(){return Task.FromResult("Wpf Test Function");}public void Dispose(){}
}

修改 MainWindow.xaml 文件

建立 BlazorWebView 控件铺满屏幕,并设置 HostPage 为Web部分的主页 index.html

<Windowx:Class="Hybrid.Wpf.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:blazor="clr-namespace:Microsoft.AspNetCore.Components.WebView.Wpf;assembly=Microsoft.AspNetCore.Components.WebView.Wpf"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:Hybrid.Wpf"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Title="Hybrid.Wpf"d:Height="200"d:Width="450"WindowStartupLocation="CenterScreen"mc:Ignorable="d"><blazor:BlazorWebView HostPage="wwwroot\index.html" Services="{DynamicResource services}"><blazor:BlazorWebView.RootComponents><blazor:RootComponent ComponentType="{x:Type local:Shell}" Selector="#blazorApp" /></blazor:BlazorWebView.RootComponents></blazor:BlazorWebView></Window>

创建 Vue 项目

通过命令 npm create vue@latest 前提是已安装 Node.js
在这里插入图片描述

执行命令尝试运行项目
在这里插入图片描述

在这里插入图片描述

修改创建好的 Vue 项目

DotNet.invokeMethodAsync("Hybrid.Maui", "Test") 第一个参数是容器项目的 Namespace,第二个参数是要调用的方法。

<script setup>
import { RouterLink, RouterView } from 'vue-router';
import HelloWorld from './components/HelloWorld.vue';/*** 访问 Hybrid.Wpf 项目中的 Test 方法*/
async function getTest() {await DotNet.invokeMethodAsync("Hybrid.Maui", "Test").then(res => {console.log(res);});
}
</script><template><header><img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" /><div class="wrapper"><HelloWorld msg="You did it!" /><nav><RouterLink to="/">Home</RouterLink><RouterLink to="/about">About</RouterLink></nav><button @click="getTest">To Hybrid.Maui Test</button></div></header><RouterView />
</template><style scoped>
header {line-height: 1.5;max-height: 100vh;
}.logo {display: block;margin: 0 auto 2rem;
}nav {width: 100%;font-size: 12px;text-align: center;margin-top: 2rem;
}nav a.router-link-exact-active {color: var(--color-text);
}nav a.router-link-exact-active:hover {background-color: transparent;
}nav a {display: inline-block;padding: 0 1rem;border-left: 1px solid var(--color-border);
}nav a:first-of-type {border: 0;
}@media (min-width: 1024px) {header {display: flex;place-items: center;padding-right: calc(var(--section-gap) / 2);}.logo {margin: 0 2rem 0 0;}header .wrapper {display: flex;place-items: flex-start;flex-wrap: wrap;}nav {text-align: left;margin-left: -1rem;font-size: 1rem;padding: 1rem 0;margin-top: 1rem;}
}
</style>

执行 npm run build 命令

执行 npm run build 命令发布 Vue 项目
在这里插入图片描述

Copy dist

将 dist 文件夹下的所有文件复制到容器项目下的 wwwroot 文件夹下
在这里插入图片描述

修改 index.html 内容

  • JS、CSS 文件名一定要与编译后的文件名一致
  • head 中的 JS 导入添加 crossorigin="anonymous" 跨域支持
  • 在 body 中导入 _framework/blazor.webview.js 必须的,没有它玩不成
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><script type="module" crossorigin="anonymous" src="/assets/index-lGWBURTF.js"></script><link rel="stylesheet" crossorigin href="/assets/index-bTbjHxa7.css">
</head>
<body><div id="app">Loading...</div><div id="blazorApp"></div><!-- Maui 项目需要添加 autostart="false" --><script src="_framework/blazor.webview.js" autostart="false"></script><!-- Wpf 项目不需要 --><script src="_framework/blazor.webview.js"></script>
</body>
</html>

效果预览

点击 To Hydrid.Wpf Test 按钮就可以在控制台打印出 C# 代码中的返回值
在这里插入图片描述

Demo 下载

https://github.com/Gun319/Hybrid

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/296047.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 pytest.ini 文件控制输出 log 日志

一、前置说明 pytest.ini 文件中可以配置参数来控制 pytest 的运行行为,其存放路径要求与 conftest.py 一样。 项目根目录project_root/ ├── pytest.ini ├── tests/ │ └── test_demo.py以test开头的测试子目录project_root/ ├── tests/ │ ├── pytest.in…

一文详解SpringBoot 定时任务(cron表达式)

IDE&#xff1a;IntelliJ IDEA 2022.2.3 x64 操作系统&#xff1a;win10 x64 位 家庭版 JDK: 1.8 文章目录 一、如何开启一个SpringBoot定时任务&#xff1f;二、cron表达式详解2.1 语法格式2.2 符号解析2,2.1 通用符号: , - * /2.2.2 专有符号&#xff1a;&#xff1f;L w 2.3…

STM32——CAN协议

文章目录 一.CAN协议的基本特点1.1 特点1.2 电平标准1.3 基本的五个帧1.4 数据帧 二.数据帧解析2.1 帧起始和仲裁段2.2 控制段2.3 数据段和CRC段2.4 ACK段和帧结束 三.总线仲裁四.位时序五.STM32CAN控制器原理与配置5.1 STM32CAN控制器介绍5.2 CAN的模式5.3 CAN框图 六 手册寄存…

智能优化算法应用:基于材料生成算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于材料生成算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于材料生成算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.材料生成算法4.实验参数设定5.算法结果6.…

【内存泄漏】内存泄漏及常见的内存泄漏检测工具介绍

内存泄漏介绍 什么是内存泄漏 内存泄漏是指程序分配了一块内存&#xff08;通常是动态分配的堆内存&#xff09;&#xff0c;但在不再需要这块内存的情况下未将其释放。内存泄漏会导致程序浪费系统内存资源&#xff0c;持续的内存泄漏还导致系统内存的逐渐耗尽&#xff0c;最…

Kafka日志

位置 server.properties配置文件中通过log.dir指定日志存储目录 log.dir/{topic}-{partition} 核心文件 .log 存储消息的日志文件&#xff0c;固定大小为1G&#xff0c;写满后会新增一个文件&#xff0c;文件名表示当前日志文件记录的第一条消息的偏移量。 .index 以偏移…

【SpringCloud笔记】(8)服务网关之GateWay

GateWay 概述简介 官网地址&#xff1a; 上一代网关Zuul 1.x&#xff1a;https://github.com/Netflix/zuul/wiki&#xff08;有兴趣可以了解一下&#xff09; gateway&#xff1a;https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/…

讲座思考 | 周志华教授:新型机器学习神经元模型的探索

12月22日&#xff0c;有幸听了南京大学周志华教授题为“新型机器学习神经元模型的探索”的讲座。现场热闹非凡&#xff0c;大家像追星一样拿着“西瓜书”找周教授签名。周教授讲得依旧循循善诱&#xff0c;由浅入深&#xff0c;听得我很入迷&#xff0c;故作此记。 周教授首先就…

Python电能质量扰动信号分类(二)基于CNN模型的一维信号分类

目录 前言 1 电能质量数据集制作与加载 1.1 导入数据 1.2 制作数据集 2 CNN-2D分类模型和训练、评估 2.1 定义CNN-2d分类模型 2.2 定义模型参数 2.3 模型结构 2.4 模型训练 2.5 模型评估 3 CNN-1D分类模型和训练、评估 3.1 定义CNN-1d分类模型 3.2 定义模型参数 …

【已解决】Python Bresenham 3D算法

放一段使用Python实现Bresenham 3D 算法的代码&#xff0c;并通过Matplot可视化 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from numba import njitnjit def bresenham_safe(grid, x0, y0, z0, x1, y1, z1, value_to_fill…

锯齿云服务器租赁使用教程

首先登陆锯齿云账号 网盘上传数据集与代码 随后我们需要做的是将所需要的数据集与代码上传到网盘&#xff08;也可以直接在租用服务器后将数据集与代码传到服务器的硬盘上&#xff0c;但这样做会消耗大量时间&#xff0c;造成资源浪费&#xff09; 点击工作空间&#xff1a;…

谷粒商城-商品服务-新增商品功能开发(商品图片无法展示问题没有解决)

在网关配置路由 - id: member_routeuri: lb://gulimemberpredicates:- Path/api/gulimember/**filters:- RewritePath/api/(?<segment>.*),/$\{segment}并将所有逆向生成的工程调式出来 获取分类关联的品牌 例如&#xff1a;手机&#xff08;分类&#xff09;-> 品…