任务: 有一个用C#编写的类库。有必要让一种方法可用于从 ReactJS 调用。我决定使用 Blazor WebAssembly 来完成此任务。我的目的是
dotnet publish
一个用 BWASM 编写的项目。之后,需要通过ReactJS连接已发布的文件,以便进一步从这些已发布的文件中调用函数。
需要调用 MdProcessor.ParseAndRender 函数,向其传递一个字符串作为输入,并从中获取字符串结果
解决方案: BWASM 的 Program.cs:
using MarkdownProcessorWasm;
using MdPWASM;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.JSInterop;
using System;
using System.Threading.Tasks;
using MarkdownProcessor;
using MarkdownProcessor.Classes;
using MarkdownProcessor.Interfaces;
using MarkdownProcessor.Structs.Tags;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
var host = builder.Build();
var jsRuntime = host.Services.GetRequiredService<IJSRuntime>();
await jsRuntime.InvokeVoidAsync("console.log", "Hello World from Blazor WebAssembly!");
var jsInterop = new MarkdownProcessorInterop();
await jsRuntime.InvokeVoidAsync("blazorInterop.registerProcessor", DotNetObjectReference.Create(jsInterop));
await host.RunAsync();
public class MarkdownProcessorInterop
{
private MdProcessor _markdownProcessor;
public MarkdownProcessorInterop()
{
var ital = new ItalicsTag();
var bold = new BoldTag();
var link = new Link();
var header = new HeaderTag();
var main = new MainTag();
var list = new List<ITag> { bold, ital, link, header, main };
_markdownProcessor = new MdProcessor(new StringParser(list), new ConsoleMdRenderer());
}
[JSInvokable]
public string ParseMarkdown(string markdownText)
{
return _markdownProcessor.ParseAndRender(markdownText);
}
}
WASM 的index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MdPWASM</title>
<base href="/" />
<link rel="stylesheet" href="css/app.css" />
<!-- If you add any scoped CSS files, uncomment the following to load them
<link href="MdPWASM.styles.css" rel="stylesheet" /> -->
</head>
<body>
<script>
window.blazorInterop = {
registerProcessor: function (processor) {
window.processor = processor;
},
parseMarkdown: async function (markdownText) {
if (!window.processor) {
throw new Error("WASM module is not ready yet.");
}
return await window.processor.invokeMethodAsync("ParseMarkdown", markdownText);
}
};
</script>
<script src="_framework/blazor.webassembly.js"></script>
<script src="Interop.js"></script>
</body>
</html>
我们的想法是为 window 添加 parseMarkdown 属性,以便稍后通过 DOM 我们可以在 JS 中调用所需的函数。
这是 React 中客户端的代码:
useEffect(() => {
const loadBlazor = async () => {
try {
await import('http://localhost:8080/_framework/blazor.webassembly.js');
await window.Blazor.start({
loadBootResource: (type, name, defaultUri, integrity) => {
return `http://localhost:8080/_framework/${name}`;
}
}).then(() => {
console.log('Blazor WebAssembly is initialized');
}).catch(error => {
console.error('Blazor WebAssembly initialization error:', error);
});
} catch (error) {
console.error('Error while fetching Blazor WebAssembly:', error);
}
};
loadBlazor();
}, []);
const processMarkdown = async () => {
try {
if (window.processor) {
const parsedHtml = await window.blazorInterop.parseMarkdown(markdownText);
setHtmlOutput(parsedHtml);
} else {
console.error('Blazor WebAssembly is not loaded');
}
} catch (error) {
console.error('Error while parsing Markdown:', error);
}
};
通过 localhost:8080,我们收到将 C# 编写的代码集成到 JS 所需的 dotnet 发布的文件。 WebAssembly加载成功,即使用Blazor编写的console.log调用函数也能成功,但下一行出现错误: ManagedError:发生一个或多个错误。 (找不到“blazorInterop.registerProcessor”(“blazorInterop”未定义)。 错误:找不到“blazorInterop.registerProcessor”(“blazorInterop”未定义)。
问题: 问题是当我们尝试打电话时
await jsRuntime.InvokeVoidAsync("blazorInterop.registerProcessor", DotNetObjectReference.Create(jsInterop));
在 BWASM 中,blazorInterop 属性尚未在 window 上创建。我试图延迟访问 blazorInterop 的时刻,直到它被声明,但我陷入了无限循环。看起来它永远不会被宣布。如何解决这个问题呢?如何在 window 上声明 blazorInterop 作为其属性?有什么方法可以将我的 MdProcessor 类库转换为 wasm 但保留 ReactJS 作为主要且唯一的前端框架?我将非常感谢任何帮助,最好是建设性的帮助
我通过添加解决了问题
<script>
window.blazorInterop = {
registerProcessor: function (processor) {
window.processor = processor;
},
parseMarkdown: async function (markdownText) {
if (!window.processor) {
throw new Error("WASM module is not ready yet.");
}
return await window.processor.invokeMethodAsync("ParseMarkdown", markdownText);
}
};
</script>
React 客户端代码中的index.html 所以当 Blazor 尝试使用注册处理器时
await jsRuntime.InvokeVoidAsync("blazorInterop.registerProcessor", DotNetObjectReference.Create(jsInterop));
处理器将已经在 DOM 中。