你好英雄

导航

dotnet9 MAUI + Vue 项目

MAUI是dotnet的跨平台技术,支持windows平台、android平台、ios平台等。使用MAUI作为基础平台,在其上运行一个前端项目,比如Vue,可以同时享受开发效率与跨平台的好处。使用dotnet9后MAUI提供的组件HybridWebView,可以实现将前端项目嵌入到MAUI项目Page中的效果。支持C#与javascript的互操作。

新建MAUI项目

  • 使用dotnet9
  • 在MainPage.xaml中使用HybridWebView
        <?xml version="1.0" encoding="utf-8" ?>
        <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                     x:Class="MauiApp1.MainPage">

            <ScrollView>
                <HybridWebView x:Name="hybridWebView"/>
            </ScrollView>

        </ContentPage>
  • 在MainPage.xaml.cs中,增加代码
        public partial class MainPage : ContentPage
        {
            public MainPage()
            {
                InitializeComponent();
                hybridWebView.SetInvokeJavaScriptTarget(this);
            }
        }
  • 为了Debug,再在MauiProgram.cs中增加代码
        public static class MauiProgram
        {
            public static MauiApp CreateMauiApp()
            {
            // ......
            #if DEBUG
                        builder.Services.AddHybridWebViewDeveloperTools();
                        builder.Logging.AddDebug();
            #endif

                return builder.Build();
            }
        }

 完成了以上准备后,就可以将前端编译好的文件,放在Resouces/Raw/wwwroot/下面了

前端项目

前端项目build默认输出到dist文件,为了方便开发部署,可以在vite.config.js中修改outDir,使其直接编译到MAUI项目的Resouces/Raw/wwwroot/文件夹中

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

const dest = "MAUI项目绝对或相对目录/Resources/Raw/wwwroot";

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  build: {
    outDir: dest,
    emptyOutDir: true,
  },
});

MAUI与Vue交互

这样一个场景:MAUI作为后端,提供一个PersonService,其中维护一个List<Person>数据列表;前端Vue要获取、增加这个列表的数据。

  • 编写PersonService.cs
public class PersonService
{
    private readonly List<Person> persons = new();
    private int maxId { get { return persons.Count; } set { value = persons.Count; } }

    public void Add(string name) // 增加Person接口
    {
        persons.Add(new(maxId + 1, name));
    }

    public List<Person> GetAll(int limit = 0) // 获取所有Person接口
    {
        if (limit == 0) return persons;
        else return persons.Take(Math.Abs(limit)).ToList();
    }
}
  • 让PersonService能被作为依赖注入,修改MauiProgramm.cs,增加
        builder.Services.AddScoped<PersonService>();
  •  在MainPage.cs中注入PersonService,并编写用来响应前端的方法
        public partial class MainPage : ContentPage
        {
            private readonly PersonService _personService;
            public MainPage(PersonService personService)
            {
                InitializeComponent();
                _personService = personService;
                hybridWebView.SetInvokeJavaScriptTarget(this);
            }

            public List<Person> GetAllPersons()
            {
                return _personService.GetAll();
            }

            public void AddPerson(string name)
            {
                _personService.Add(name);
            }
        }
  • 接下来修改前端 

前端javascript代码调用MAUI后端方法,需要使用一个脚本HybridWebView.js

在微软示例中,这个脚本是直接用src标签在index.html中引用的,但是我们使用了vue工程,因此需要模块化这个脚本。将脚本最后的window.HybridWebView.Init()放入一个export default function中即可

export default function(){
    window.HybridWebView.Init();
}

然后再在index.html中加入。注意,HybridWebView.js要放在main.js的上面

<body>
  <div id="app"></div>
  <script type="module" src="/src/scripts/HybridWebView.js"></script>
  <script type="module" src="/src/main.js"></script>
</body>

 最后,编写vue组件

<script setup>
import { ref, onMounted } from "vue";

const name = ref("");
const persons = ref([]);


onMounted(async () => {
  await flush_persons(); // 在mounted钩子中初始化persons列表
});

async function btn_add_person() {
  await window.HybridWebView.InvokeDotNet("AddPerson", [name.value]); // 调用MAUI后端方法AddPerson,并传参
  flush_persons();
}

async function flush_persons() {
  persons.value = await window.HybridWebView.InvokeDotNet("GetAllPersons"); // 调用MAUI后端方法GetAllPersons
}
</script>

<template>
  <input type="text" v-model="name" placeholder="person name" />
  <button @click="btn_add_person">Add Person</button>
  <li v-for="p in persons">
    {{ p }}
  </li>
</template>

<style scoped></style>

posted on 2024-12-18 16:38  HalloHerö  阅读(3)  评论(0编辑  收藏  举报