栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

Blzaor的Wasm和Server模式无缝切换,混合使用

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Blzaor的Wasm和Server模式无缝切换,混合使用

网上已经有很多资料,但大多都是只支持一个模式切换,这次实现了Wasm和Server无缝切换,并且去掉了Wasm首次加载时间过长的问题,利用Server先进行访问,等后台资源下载完成后,切换到Wasm模式,减少占用服务器资源和长连接的问题

先看视频,如果不是想要的效果就不用往下看了

Blazor的Wasm和Server模式无缝切换https://www.bilibili.com/video/BV1L3411e7o9/

首先,没有单独写例子,集成到了我的开源软件里,可以查看 Caviar-Blazor,内容有点多,慢慢来分解一下。

有些限制,需要编写的时候按照Wasm进行编码,也就是所有的数据请求需要用Http,不能直接使用对象,然后建立两个项目,一个是server模式,一个是wasm模式,server模式的引用wasm模式就可以,需要把wasm模式里一段代码屏蔽掉,按照自己的来

builder.RootComponents.Add("#app");

然后就是在server的_Host.cshtml加载两个模型

@page "_Host"
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using Caviar.AntDesignUI
@using Caviar.Infrastructure
@using Caviar.SharedKernel
@using Microsoft.Extensions.Options

@{
    var IsServer = Request.Query.ContainsKey(CurrencyConstant.ServerName);
    var host = Request.Host;
    var serverHost = $"{Request.Scheme}://{host}?{CurrencyConstant.ServerName}";

}




    
    
    Caviar
    




    @if(IsServer)
    {
        
            
            
        
        
    }
    else
    {
        
            
        
        
            
        
        
    }

    
    
    
    
    


当然这里做了一些处理,如果同时加载两个模型,因为会同事订阅事件,会互相处理,所以会卡死,我们直接用iframe进行隔离,我们先显示server模式,把wasm模式隐藏起来,这样就像直接使用srever模式一样。自动切换我们等会再说 ,我们先实现手动切换

现在思路就很清除了,我们可以隐藏iframe也可以直接去掉来节省资源,我们只需要两个js就能搞定

function switch_wasm() {
	wasm_app = document.getElementById("wasm_app");
	iframe_div = document.getElementById("iframe_div");
	wasm_app.style.display = "block";
	iframe_div.style.display = "none";
	var iframe = document.getElementById("iframe_Server");
	iframe.parentNode.removeChild(iframe);
}

function switch_server(url) {
	wasm_app = document.getElementById("wasm_app");
	wasm_app.style.display = "none";
	iframe_div = document.getElementById("iframe_div");
	iframe_div.innerHTML = ''
	iframe_div.style.display = "block"

}

切换wasm模式时,直接移除iframe,然后将wasm显示

切换wasm模式时,重新加载iframe,然后隐藏wasm,非常完美

后面我们需要在wasm加载完毕时,自动切换,那么切换数据的时机很重要,不能在用户操作时候切换,需要在用户切换页面的时候,直接将wasm放出来,用户就感觉不到了。所以我们需要一个事件,当用户切换页面时触发事件,如果加载好了就切换没有加载好就不切换。

这就涉及到了iframe和外面进行通信,好在已经有解决方案

//iframe内发送消息
function iframeMessage(message) {
	window.parent.postMessage(message, '*');
}


//iframe外监听
window.addEventListener('message', function (e) { 
	console.log(e.data);
	DotNet.invokeMethod("Caviar.AntDesignUI", "JsNavigation", e.data)
})

iframe只需要调用postMessage,外面就可以监听到,这样通信也有了

            //在server模式下且需要自动切换
            if (Config.IsServer && UserConfig.IsAutomaticSwitchWasm)
            {
                var iframeMessage = new IframeMessage();
                iframeMessage.Pattern = Pattern.Wasm;
                iframeMessage.Url = menuItem.RouterLink;
                _ = jSRuntime.InvokeVoidAsync("iframeMessage", iframeMessage);
            }

在你需要切换的位置进行调用,当然我们需要判断一下当前是否为server模式,不然在wasm也会调用,还需要判断一下是否需要自动切换,当我们调用js以后,js会调用c#的一个静态方法

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Caviar.AntDesignUI
{
    /// 
    /// iframe与框架通信类
    /// 
    public class IframeMessage
    {
        /// 
        /// 调用的模式
        /// 
        public Pattern Pattern { get; set; }
        /// 
        /// 转到的地址
        /// 
        public string Url { get; set; }
        /// 
        /// 传输的数据
        /// 
        public object Data { get; set; }


        public delegate void JSScheduling(IframeMessage message);

        public static event JSScheduling SwitchWasm;

        [JSInvokable]
        public static void JsNavigation(IframeMessage message)
        {
            switch (message.Pattern)
            {
                case Pattern.Wasm:
                    SwitchWasm?.Invoke(message);
                    break;
                default:
                    break;
            }
        }
    }

    public enum Pattern
    {
        Wasm,
        Server
    }
}

在方法里调用事件即可,剩下的就是合适注册事件,所有的组件都是从app开始的,所以app里写再合适不过了

@using Caviar.AntDesignUI.Helper;
@using System.Web

    
        
            
                
                    
                    @**@
                
                
                    
                
            
        
        
            
        
    
    

@code {
    [Inject]
    UserConfig UserConfig { get; set; }

    [Inject]
    NavigationManager NavigationManager { get; set; }
    [Inject]
    IJSRuntime JSRuntime{ get; set; }


    protected override void OnParametersSet()
    {
        if (!Config.IsServer)
        {
            //wasm模式初始化完成,接收事件
            IframeMessage.SwitchWasm += SwitchWasm_RefChanged;
        }
        else
        {
            var uri = new Uri(NavigationManager.Uri);
            var collection = HttpUtility.ParseQueryString(uri.Query);
            if (!string.IsNullOrEmpty(collection["IsAutomaticSwitchWasm"]))
            {
                UserConfig.IsAutomaticSwitchWasm = bool.Parse(collection["IsAutomaticSwitchWasm"]);
            }
        }
        
        base.OnParametersSet();
    }

    private void SwitchWasm_RefChanged(IframeMessage message)
    {
        NavigationManager.NavigateTo(message.Url);
        JSRuntime.InvokeVoidAsync("switch_wasm");
    }

}

在OnParametersSet时判断一下是否为wasm模式,如果是就注册事件既可,事件里进行wasm跳转,并且切换到wasm模式。

当然,在url里需要表明当前是否需要自动切换,不然就不能使用server模式了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/984176.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号