Umbraco v13中实现按钮触发的分类图片动态过滤渲染的方案与最佳实践
Umbraco v13中实现按钮触发的分类图片动态过滤渲染的方案与最佳实践
嘿,针对你在Umbraco v13里遇到的图片分类动态过滤问题,我来分享一套实用的实现方案和最佳实践,帮你搞定高效的无刷新过滤,同时完美适配Umbraco的后台配置~
一、先把Umbraco后台数据结构捋顺(基础中的基础)
首先要确保你的图片和分类的关联逻辑符合Umbraco的内容管理规范,避免后期维护头疼:
- 创建
ImageCategory文档类型:用来管理所有分类(比如Festival、Sports、Activity),可以只加一个Name字段,后台创建对应的分类节点。 - 创建
GalleryImage文档类型:包含两个核心字段:GalleryMedia:Media Picker类型,用来选择要展示的图片ImageCategory:Content Picker类型,关联到刚才创建的ImageCategory节点(或者用Dropdown List预定义固定分类,看你是否需要动态新增分类)
- 创建
GalleryPage文档类型:设置为允许包含GalleryImage子节点,这样编辑人员可以在后台直接给这个页面添加图片和分类。
二、改进Razor视图:从硬编码到动态生成(适配Umbraco数据)
你之前的代码里硬编码了按钮和图片路径,这在Umbraco里完全没必要,我们可以直接从CMS数据动态生成所有内容,后期修改分类或图片都不用改代码:
@{ // 获取当前GalleryPage下的所有GalleryImage子节点 var galleryImages = Model.ChildrenOfType("GalleryImage").ToList(); // 获取所有唯一的分类(这里假设ImageCategory字段存的是分类节点的名称,你也可以用别名) var categories = galleryImages .Select(x => x.Value<IPublishedContent>("imageCategory")?.Name) .Distinct() .Where(name => !string.IsNullOrEmpty(name)) .ToList(); } <!-- 动态生成过滤按钮 --> <ul class="uk-navbar-nav"> <li class="uk-active" uk-filter-control=""><a href="#">All</a></li> @foreach (var category in categories) { <li uk-filter-control="[data-filter='@category']"> <a href="#">@category</a> </li> } </ul> <!-- 动态生成图片列表 --> <ul class="img-gallery-container js-filter uk-child-width-1-2 uk-child-width-1-3@m uk-text-center" uk-grid> @foreach (var image in galleryImages) { var mediaItem = image.Value<IPublishedContent>("galleryMedia"); // 使用Umbraco的ImageProcessor生成缩略图,提升加载速度 var imgUrl = mediaItem?.GetCropUrl(width: 600, height: 400) ?? ""; var categoryName = image.Value<IPublishedContent>("imageCategory")?.Name ?? ""; var altText = image.Value<string>("imageAltText") ?? "Gallery image"; <li data-filter="@categoryName"> <img src="@imgUrl" alt="@altText" class="img-gal"> </li> } </ul>
三、优化JS逻辑:提升大量图片的过滤效率
你之前的hover交互效果很棒,但针对大量图片的过滤,我们可以做一些优化,同时确保逻辑更健壮:
// 缓存DOM元素,避免重复查询 const galleryContainer = document.querySelector('.img-gallery-container'); const filterButtons = document.querySelectorAll('.uk-navbar-nav li'); const imgItems = galleryContainer.querySelectorAll('li'); // 封装图片交互事件的绑定函数 function bindImageInteractions(imgEl) { const height = imgEl.clientHeight; const width = imgEl.clientWidth; const handleMove = (e) => { const xVal = e.layerX; const yVal = e.layerY; const yRotation = 20 * ((xVal - width / 2) / width); const xRotation = -20 * ((yVal - height / 2) / height); imgEl.style.transform = `perspective(500px) scale(1.01) rotateX(${xRotation}deg) rotateY(${yRotation}deg)`; }; imgEl.addEventListener('mousemove', handleMove); imgEl.addEventListener('mouseout', () => { imgEl.style.transform = 'perspective(500px) scale(1) rotateX(0) rotateY(0)'; }); imgEl.addEventListener('mousedown', () => { imgEl.style.transform = 'perspective(500px) scale(0.9) rotateX(0) rotateY(0)'; }); imgEl.addEventListener('mouseup', () => { imgEl.style.transform = 'perspective(500px) scale(1.1) rotateX(0) rotateY(0)'; }); } // 给所有图片绑定交互事件 galleryContainer.querySelectorAll('.img-gal').forEach(bindImageInteractions); // 自定义过滤逻辑(如果不想依赖UIkit的filter组件,也可以自己实现) filterButtons.forEach(button => { button.addEventListener('click', (e) => { e.preventDefault(); // 更新按钮激活状态 filterButtons.forEach(btn => btn.classList.remove('uk-active')); button.classList.add('uk-active'); // 获取当前要过滤的分类 const filterValue = button.getAttribute('uk-filter-control')?.replace(/\[data-filter='(.*)'\]/, '$1') || ''; // 批量处理图片显示/隐藏,比逐个操作更高效 imgItems.forEach(item => { item.style.display = !filterValue || item.getAttribute('data-filter') === filterValue ? 'block' : 'none'; }); }); });
四、Umbraco专属最佳实践
性能优化:
- 始终使用
GetCropUrl()生成缩略图,避免加载原图,Umbraco的ImageProcessor会自动缓存裁剪后的图片 - 给
GalleryPage启用输出缓存,在后台设置缓存时长,减少服务器重复渲染的压力 - 如果图片数量超过100张,考虑实现懒加载,结合Umbraco的
loading="lazy"属性或者第三方懒加载库
- 始终使用
后台易用性:
- 在
GalleryImage文档类型里把ImageCategory和GalleryMedia设为必填字段,避免编辑人员遗漏信息 - 如果分类是固定的,用Dropdown List代替Content Picker,减少编辑操作步骤
- 在
可维护性:
- 把过滤按钮和图片列表抽成独立的Partial View(比如
_GalleryFilterButtons.cshtml和_GalleryImages.cshtml),方便在其他页面复用 - 把JS逻辑封装成单独的模块文件(比如
gallery-filter.js),不要直接写在Razor视图里,便于调试和维护
- 把过滤按钮和图片列表抽成独立的Partial View(比如
备注:内容来源于stack exchange,提问作者Test 1
相关产品推荐
相关产品推荐

