网络营销企业网站,湖南网络广告策划推广,绵阳 网站设计,高唐企业网站建设文章目录 Vue在混合开发中的特点创建MAUI项目创建Vue应用使用element-ui组件库JavaScript和原生代码的交互传递根组件参数从设备调用Javascript代码从Vue页面调用原生代码 读取设备信息项目地址 .NET MAUI结合Vue的混合开发可以使用更加熟悉的Vue的语法代替Blazor语法#xff… 文章目录 Vue在混合开发中的特点创建MAUI项目创建Vue应用使用element-ui组件库JavaScript和原生代码的交互传递根组件参数从设备调用Javascript代码从Vue页面调用原生代码 读取设备信息项目地址 .NET MAUI结合Vue的混合开发可以使用更加熟悉的Vue的语法代替Blazor语法你现有项目不必重写。之前写过一篇
[MAUI] 在.NET MAUI中结合Vue实现混合开发 其中介绍了如何创建一个vue应用并将其打包至MAUI项目这种方式依赖vue-cli创建和打包静态站点好处是可以使用Node.js 的构建但MAUI仅仅作为容器。开发应用需要一个独立的host项目 这次用集成的方式。将vue作为MAUI的一部分这样就可以在MAUI项目中直接使用vue了。 Vue在混合开发中的特点
首先要说的是Vue框架是渐进性的所谓渐进性就是Vue不会强求你使用所有的框架特性你可以根据需要逐步使用。
同样地element-ui也可以通过引入样式和组件库配合Vue使用
因此我们不需要Vue Router、Vuex、Vue CLI、单文件组件这些高级特性仅仅引入Vue.js即可使用Vue模板语法。我们将利用Blazor引擎的如下功能
组件化开发静态资源管理js代码的注入js调用C#代码C#调用js代码
由.NET MAUI提供的功能
路由管理状态管理
由Vue提供模板语法事件处理计算属性/侦听器等以及Element-UI提供交互组件。
创建MAUI项目
创建一个MAUI项目这里使用的是Visual Studio 2022 17.7.3创建一个Blazor MAUI App项目命名MAUI-Vue-Hybriddev-Integrated选择Android和iOS作为目标平台选择.NET 7.0作为目标框架。 从Vue官网下载最新的Vue.js 将其放置在wwwroot目录下然后在index.html中引入 script srclib/vuejs/vue.js/script创建Vue应用
在Views目录下创建 HomePage.xaml作为Vue应用的容器在页面中创建BlazorWebView视图元素并设置HostPage为wwwroot/index.html这样就可以在MAUI中使用Vue了。
BlazorWebView x:NameblazorWebViewHostPagewwwroot/index.htmlBlazorWebView.RootComponentsRootComponent Selector#appx:NamerootComponentComponentType{x:Type views:HomePageWeb} //BlazorWebView.RootComponents
/BlazorWebView每个BlazorWebView控件包含根组件RootComponent定义ComponentType是在应用程序启动时加载页面时的类型该类型需要继承自Microsoft.AspNetCore.Components.IComponent由于我们的导航是由MAUI处理的因此我们不需要使用Blazor路由直接使用Razor组件
在Views目录下创建HomePageWeb.razor这是Vue应用页面相当于Vue的单文件组件这里可以使用Vue的模板语法而不是Blazor的Razor语法。
我们在HomePageWeb.razor中写下Vue官方文档中Hello Vue示例代码 div idvue-app{{ message }}
/divscript typetext/javascriptvar app new Vue({el: #vue-app,data: {message: Hello Vue!,}})/script注意Vue的根元素名称不要跟Blazor的根元素名称相同否则会报错。 此时更改JavaScript里的内容你会发现Blazor页面不会热加载。 请勿将 script 标记置于 Razor 组件文件 (.razor) 中因为 script 标记无法由Blazor 动态更新。 于是需要将script部分代码放置在外部此时有两种方案一个是放在wwwroot/js目录下然后在wwwroot/index.html中引入还有一种是使用并置的js文件这种方式是所谓的CodeBehind因为更利于组织代码这里我们使用并置的js文件。
创建一个HomePageWeb.razor.js文件将script部分代码放置在其中然后在HomePageWeb.razor中引入 protected override async Task OnAfterRenderAsync(bool firstRender)
{if (firstRender){await JSRuntime.InvokeAsyncIJSObjectReference(import, ./Views/HomePageWeb.razor.js);}
}发布应用后框架会自动将脚本移动到 Web 根目录。 在此示例中脚本被移动到./wwwroot/Views/HomePageWeb.razor.js
使用element-ui组件库
同样我们在element-ui官方CDN下载样式文件和组件库首先在index.html中引入样式和组件库
link hrefcss/app.css relstylesheet /
...
script srclib/element-ui/index.js/script然后在HomePageWeb.razor中使用组件
div idvue-app{{ message }}el-input v-modelinput placeholder请输入内容/el-inputel-button clickshowDialog true提交/el-buttonel-dialog :visible.syncshowDialog title消息p{{input}}/pp提交成功/p/el-dialog
/divCodeBehind中引入组件
var app new Vue({el: #vue-app,data: {message: Hello Vue!,showDialog: false,input: text message from vue}
})运行效果如下 JavaScript和原生代码的交互
Blazor组件中的代码可以通过注入IJSRuntime来调用JavaScript代码JavaScript代码可以通过调用DotNet.invokeMethodAsync来调用C#代码。
传递根组件参数
如果被调用的代码位于其他类中需要给这个Blazor组件传递实例还记得刚才提及的根组件RootComponent吗我们用它来传递这个实例称之为根组件参数详情请查看官方文档 在 ASP.NET Core Blazor Hybrid 中传递根组件参数
创建SecondPage.xaml根据刚才的步骤创建一个BlazorWebView并注入vuejs代码 html部分创建一个el-dialog组件当消息被接收时显示对话框 using Microsoft.Maui.Controls
inject IJSRuntime JSRuntimediv idvue-app{{ message }}el-dialog :visible.syncshowDialog titleNative device msg recived!p{{msg}}/p/el-dialog
/div
在code代码段中创建SecondPage对象。 code {[Parameter]public SecondPage SecondPage { get; set; }...
}
回到SecondPage.xaml.cs在构造函数中将自己传递给根组件参数
public SecondPage()
{InitializeComponent();rootComponent.Parameters new Dictionarystring, object{{ SecondPage, this }};
}
从设备调用Javascript代码
在SecondPage.xaml中创建一个Post按钮点击按钮后将文本框PostContentEntry的内容传递给Vue代码
StackLayout Grid.Row1Entry x:NamePostContentEntry TextHello,this is greetings from native device/EntryButton TextPost To VueHorizontalOptionsCenterVerticalOptionsEndHeightRequest40ClickedPost_Clicked/Button/StackLayout在SecondPage.razor.js中, 创建greet方法用于接收从原生代码传递过来的参数并显示在对话框中。
window.app new Vue({el: #vue-app,data: {message: Vue Native interop,showDialog: false,msg: },methods: {greet: function (content) {this.msg content;this.showDialog true;}},在SecondPage.xaml.cs中创建一个OnPost事件当Post按钮被点击时触发该事件 public event EventHandlerOnPostEventArgs OnPost;private void Post_Clicked(object sender, EventArgs args)
{OnPost?.Invoke(this, new OnPostEventArgs(this.PostContentEntry.Text));
}
在SecondPage.razor中订阅OnPost事件当事件被触发时调用greet方法将参数传递给JavaScript代码 public async void Recived(object o, OnPostEventArgs args)
{await JSRuntime.InvokeAsyncstring(window.app.greet, args.Content);
}protected override async Task OnAfterRenderAsync(bool firstRender)
{try{if (firstRender){SecondPage.OnPost this.Recived;await JSRuntime.InvokeAsyncIJSObjectReference(
import, ./Views/SecondPageWeb.razor.js);}}catch (Exception ex){Console.WriteLine(ex);}}
在页面销毁时要取消订阅事件避免内存泄漏。 implements IDisposable...public void Dispose()
{SecondPage.OnPost - this.Recived;
}
运行效果如下 从Vue页面调用原生代码
原生代码指的是.NET MAUI平台的C#代码比如要在设备上显示一个弹窗需要调用Page.DisplayAlert方法它隶属于Microsoft.Maui.Controls命名空间属于MAUI组件库的一部分。
因此需要将MAUI类型的对象通过引用传递给JavaScript调用调用方式是通过将对象实例包装在 DotNetObjectReference 中传递给JavaScript。使用该对象的invokeMethodAsync从 JS 调用 .NET 实例方法。详情请查看官方文档 JavaScript 函数调用 .NET 方法
在code代码段中界面加载时创建DotNetObjectReference对象
code {private DotNetObjectReferenceSecondPageWeb? objRef;protected override void OnInitialized(){objRef DotNetObjectReference.Create(this);}
页面加载完成时将DotNetObjectReference对象传递给JavaScript代码 protected override async Task OnAfterRenderAsync(bool firstRender)
{try{if (firstRender){SecondPage.OnPost this.Recived;await JSRuntime.InvokeAsyncIJSObjectReference(
import, ./Views/SecondPageWeb.razor.js);await JSRuntime.InvokeAsyncstring(window.initObjRef, this.objRef);}}catch (Exception ex){Console.WriteLine(ex);}}window.app new Vue({...data: {...objRef: null},})
window.initObjRef function (objRef) {window.app.objRef objRef;
}
在SecondPage.razor中创建el-input组件和el-button组件当按钮被点击时调用Post方法将文本框的内容传递给原生代码
div idvue-app{{ message }}el-input v-modelinput placeholder请输入内容/el-inputel-button clickpostPost To Native/el-buttonel-dialog :visible.syncshowDialog titleNative device msg recived!p{{msg}}/p/el-dialog
/div按钮和对话框的显示逻辑与之前相同不再赘述。 在SecondPage.razor中创建Post方法方法被调用时将触发MAUI组件库的原生代码
[JSInvokable]
public async Task Post(string content)
{await SecondPage.DisplayAlert(Vue msg recived!, content, Got it!);}vue绑定的函数中调用DotNet.invokeMethodAsync将文本框的内容传递给原生代码 window.app new Vue({el: #vue-app,data: {message: Vue Native interop,showDialog: false,msg: ,input: Hi, I am a text message from Vue,deviceDisplay: null,objRef: null},methods: {greet: function (content) {this.msg content;this.showDialog true;},post: function () {this.objRef.invokeMethodAsync(Post, this.input);}}
})运行效果如下 读取设备信息
可以使用Vue的watch属性监听数据变化当MAUI对象加载完成时调用原生代码读取设备信息
div idvue-app...pDevice Display/pp{{deviceDisplay}}/p
/divCodeBehind代码如下
watch: {objRef: async function (newObjRef, oldObjRef) {if (newObjRef) {var deviceDisplay await this.objRef.invokeMethodAsync(ReadDeviceDisplay);console.warn(deviceDisplay);this.deviceDisplay deviceDisplay;}}
},原生代码如下 [JSInvokable]
public async Taskstring ReadDeviceDisplay()
{return await Task.FromResult(SecondPage.ReadDeviceDisplay());}在ReadDeviceDisplay方法中我们读取设备分辨率、屏幕密度、屏幕方向、屏幕旋转、刷新率等信息
public string ReadDeviceDisplay()
{System.Text.StringBuilder sb new System.Text.StringBuilder();sb.AppendLine($Pixel width: {DeviceDisplay.Current.MainDisplayInfo.Width} / Pixel Height: {DeviceDisplay.Current.MainDisplayInfo.Height});sb.AppendLine($Density: {DeviceDisplay.Current.MainDisplayInfo.Density});sb.AppendLine($Orientation: {DeviceDisplay.Current.MainDisplayInfo.Orientation});sb.AppendLine($Rotation: {DeviceDisplay.Current.MainDisplayInfo.Rotation});sb.AppendLine($Refresh Rate: {DeviceDisplay.Current.MainDisplayInfo.RefreshRate});var text sb.ToString();return text;
}当页面加载时会在HTML页面上显示设备信息
项目地址
Github:maui-vue-hybirddev
关注我学习更多.NET MAUI开发知识