ASP.NET Core点击下拉标签动态加载磁盘文件的实现问题
实现ASP.NET Core下拉菜单的文件懒加载方案
我明白你的需求——要把下拉菜单的文件列表改成懒加载,只有用户点击「Consulter les conventions」的时候才去加载磁盘文件并生成菜单,而不是页面一开始就全部加载。之前加onclick没生效还报函数未定义,大概率是脚本加载时机或者作用域的问题,咱们一步步来解决:
1. 调整前端下拉菜单结构
先把初始的下拉菜单设为空(或放加载提示),保留Bootstrap的下拉标记,但先不渲染菜单项:
<div class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" id="conventionsDropdownBtn">Consulter les conventions</a> <div class="dropdown-menu" id="conventionsMenuContainer"> <!-- 初始显示加载提示 --> <span class="dropdown-item-text px-3">Chargement...</span> </div> </div>
2. 编写前端懒加载脚本
用原生JS绑定点击事件,确保脚本在DOM渲染完成后执行(避免找不到元素或函数未定义的问题):
document.addEventListener('DOMContentLoaded', function() { const dropdownBtn = document.getElementById('conventionsDropdownBtn'); const menuContainer = document.getElementById('conventionsMenuContainer'); let hasLoadedFiles = false; // 标记是否已加载,避免重复请求 dropdownBtn.addEventListener('click', async function(e) { // 已加载过就直接展开下拉,不再请求 if (hasLoadedFiles) return; e.preventDefault(); // 阻止默认跳转行为 menuContainer.innerHTML = '<span class="dropdown-item-text px-3">Chargement...</span>'; try { // 调用后端API获取文件列表 const response = await fetch('/api/Files/GetConventions'); if (!response.ok) throw new Error('Échec du chargement des fichiers'); const fileList = await response.json(); menuContainer.innerHTML = ''; // 清空加载提示 // 遍历生成下拉菜单项 fileList.forEach(file => { const link = document.createElement('a'); link.className = 'dropdown-item'; link.href = `/Files/Download?fileName=${encodeURIComponent(file.FileName)}`; link.textContent = file.DisplayName || file.FileName; menuContainer.appendChild(link); }); hasLoadedFiles = true; // 手动触发Bootstrap下拉展开(如果用了Bootstrap) if (typeof $ !== 'undefined') { $(dropdownBtn).dropdown('toggle'); } else { // 原生方式展开下拉(不用jQuery) dropdownBtn.parentElement.classList.add('show'); menuContainer.classList.add('show'); } } catch (err) { menuContainer.innerHTML = `<span class="dropdown-item-text px-3 text-danger">Erreur : ${err.message}</span>`; console.error(err); } }); });
3. 后端编写文件列表API
在ASP.NET Core中创建一个API控制器,用来读取磁盘文件并返回数据:
[ApiController] [Route("api/[controller]")] public class FilesController : ControllerBase { private readonly IWebHostEnvironment _webHostEnv; public FilesController(IWebHostEnvironment webHostEnv) { _webHostEnv = webHostEnv; } // 获取约定文件列表的API [HttpGet("GetConventions")] public IActionResult GetConventionFiles() { // 替换为你实际的文件存储路径(比如wwwroot下的Conventions文件夹) var fileDir = Path.Combine(_webHostEnv.WebRootPath, "Conventions"); if (!Directory.Exists(fileDir)) { return Ok(new List<FileInfoDto>()); // 目录不存在返回空列表 } var files = Directory.GetFiles(fileDir) .Select(path => new FileInfoDto { FileName = Path.GetFileName(path), DisplayName = Path.GetFileNameWithoutExtension(path) // 可自定义显示名称 }) .ToList(); return Ok(files); } // 文件下载接口 [HttpGet("/Files/Download")] public IActionResult DownloadFile(string fileName) { var filePath = Path.Combine(_webHostEnv.WebRootPath, "Conventions", fileName); if (!System.IO.File.Exists(filePath)) { return NotFound(); } var stream = new FileStream(filePath, FileMode.Open); return File(stream, "application/octet-stream", fileName); } // 用于传递文件信息的DTO public class FileInfoDto { public string FileName { get; set; } public string DisplayName { get; set; } } }
为什么之前的onclick无效?
你遇到的「函数未定义」问题,通常是这两个原因:
- 函数定义在局部作用域(比如
DOMContentLoaded回调内),全局访问不到; - 脚本加载在元素之前,绑定事件时元素还未渲染。
用addEventListener绑定事件的方式更可靠,能确保元素存在后再绑定逻辑。
内容的提问来源于stack exchange,提问作者Crakenar
相关产品推荐
相关产品推荐

