Blazor如何在按钮点击事件中同时执行C#与JS函数?
问题描述
我有两个按钮:一个用于执行JavaScript函数,代码如下:
<button class="btn-orange btn" onclick="expand(this.closest('.profile'))">JavaScript</button>
另一个用于执行C#逻辑并根据布尔值切换图标,代码如下:
<button class="btn-orange btn" @onclick="@(() => { if (tempBool) { tempBool = !tempBool; } else { tempBool = true; } })"> <i class="fa @(tempBool ? "fa-compress" : "fa-expand")" aria-hidden="true"></i> </button>
我希望将这两个按钮的功能合并,即实现按钮点击事件同时执行C#逻辑与JavaScript函数。尝试过使用OnClientClick事件、调用JsRuntime.InvokeVoidAsync("expand(this.closest(.profile))");,以及将两者放在同一个onclick事件中,但均未成功。
我的JavaScript代码位于EventPageExpandable.js:
function expand(card) { card.classList.toggle('profile--expanded'); // If card is not expanded after toggle, add 'unexpanded' class if (!card.classList.contains('profile--expanded')) card.classList.toggle('profile--unexpanded'); // Else if card is expanded after toggle and still contains 'unexpanded' class, remove 'unexpanded' else if (card.classList.contains('profile--expanded') && card.classList.contains('profile--unexpanded')) card.classList.toggle('profile--unexpanded'); }
尝试的JsRuntime调用方式如下:
await JsRuntime.InvokeVoidAsync("EventPageExpandable.expand", "this.closest('.profile')");
或者:
await JsRuntime.InvokeVoidAsync("expand", "this.closest('.profile')");
但两种方式都无法正常工作,请问如何实现该需求?
解决方案
核心问题分析
你之前的调用失败是因为向JS函数传递了字符串"this.closest('.profile')",而非实际的DOM元素。JS函数expand需要接收DOM节点才能调用classList相关方法,字符串参数无法满足要求。
正确实现步骤
1. 定义元素引用与状态变量
在Blazor组件代码中,添加用于获取.profile元素的ElementReference,以及状态变量tempBool:
@inject IJSRuntime JsRuntime <!-- 给.profile元素添加@ref绑定 --> <div class="profile" @ref="_profileElement"> <!-- 合并后的按钮 --> <button class="btn-orange btn" @onclick="HandleToggle"> <i class="fa @(tempBool ? "fa-compress" : "fa-expand")" aria-hidden="true"></i> </button> <!-- 其他内容 --> </div> @code { private ElementReference _profileElement; private bool tempBool = false; private async Task HandleToggle() { // 执行C#逻辑:简化原有的if-else,直接取反状态 tempBool = !tempBool; // 调用JS函数,传入实际的DOM元素引用(Blazor会自动转换为JS可识别的DOM节点) await JsRuntime.InvokeVoidAsync("expand", _profileElement); } }
2. 确保JS文件正确引入
确认EventPageExpandable.js已在项目中正确加载,比如在wwwroot/index.html(WebAssembly)或Pages/_Layout.cshtml(Server)中添加:
<script src="EventPageExpandable.js"></script>
替代方案(无需ElementReference)
如果不想使用ElementReference,也可以给.profile元素添加唯一ID,然后在JS中通过ID查找元素:
C#代码:
private bool tempBool = false; private async Task HandleToggle() { tempBool = !tempBool; // 传入元素ID让JS查找 await JsRuntime.InvokeVoidAsync("expandById", "unique-profile-id"); }
修改JS函数:
function expandById(cardId) { const card = document.getElementById(cardId); if (!card) return; card.classList.toggle('profile--expanded'); if (!card.classList.contains('profile--expanded')) card.classList.toggle('profile--unexpanded'); else if (card.classList.contains('profile--expanded') && card.classList.contains('profile--unexpanded')) card.classList.toggle('profile--unexpanded'); }
同时给.profile元素添加ID:
<div class="profile" id="unique-profile-id">...</div>
内容的提问来源于stack exchange,提问作者SideSky
相关产品推荐
相关产品推荐

