You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从NFT元数据动态生成无重复值的筛选菜单

动态构建NFT特征筛选菜单方案

核心思路

先批量获取所有NFT元数据,统一处理去重特征,再生成符合要求的嵌套筛选菜单,同时完成藏品渲染。

具体实现步骤

1. 重构异步数据获取逻辑

原循环逐个发起异步请求会导致数据处理顺序混乱,改用Promise.all批量获取所有元数据:

var loopFunction = async function(dataIsLoading) {
    var itemURI = "https://ikzttp.mypinata.cloud/ipfs/QmQFkLSQysj94s5GvTHPyzTxrawwtjgiiYS2TBLgrvw8CW/";
    // 生成所有请求的Promise数组
    const dataPromises = [];
    for (let i = 0; i < 100; i++) {
        dataPromises.push($.getJSON(itemURI + i));
    }

    // 等待所有请求完成
    const allNFTData = await Promise.all(dataPromises);

    // 处理数据生成筛选菜单和渲染藏品
    buildFilterMenu(allNFTData);
    renderNFTItems(allNFTData);
};

2. 构建去重的特征分类对象

用对象存储特征类型,结合Set自动去重特征值:

function buildFilterMenu(nftDataList) {
    // 存储特征分类:key为trait_type,value为存储唯一值的Set
    const traitCategories = {};

    nftDataList.forEach(data => {
        data.attributes.forEach(entry => {
            const traitType = entry.trait_type;
            // 处理特征值,移除空格和原逻辑保持一致
            const traitValue = entry.value.replace(/ /g, '');
            
            if (!traitCategories[traitType]) {
                traitCategories[traitType] = new Set();
            }
            // 自动去重添加特征值
            traitCategories[traitType].add(traitValue);
        });
    });

    // 生成筛选菜单HTML结构
    let menuHTML = '<ul>';
    for (const [traitType, values] of Object.entries(traitCategories)) {
        menuHTML += `<li>
            <h2>${traitType}</h2>
            <ul>`;
        // 将Set转为数组遍历生成选项
        values.forEach(value => {
            menuHTML += `<li data-trait-type="${traitType}" data-trait-value="${value}">${value}</li>`;
        });
        menuHTML += `</ul></li>`;
    }
    menuHTML += '</ul>';

    // 将菜单插入页面指定容器(比如添加一个class为filter-menu的容器)
    $('.filter-menu').html(menuHTML);
}

3. 批量渲染NFT藏品

复用原渲染逻辑,整合到批量数据处理流程中:

function renderNFTItems(nftDataList) {
    let allItemsHTML = '';
    nftDataList.forEach((data, index) => {
        var itemName = data.name;
        var classes = "";
        var traitList = "";

        $.each(data.attributes,function(index,entry) {
            var str = entry.value.replace(/ /g, '');
            classes += `${entry.trait_type}${str} `;
            traitList += `<span class="item-trait-type">${entry.trait_type}:</span> ${str}<br />`;
        });

        let eachItem = `<div class="cstm-grid-item cstm-width-1-2 cstm-width-large-1-3 cstm-width-x-large-1-4 ${classes}" id="${index}">
            <div class="img-placeholder">
                <img class="lazy" data-src="https://ikzttp.mypinata.cloud/ipfs/QmYDvPAXtiJg7s8JdRBSLWdgSphQdac8j1YuQNNxcGE1hg/${index}.png" width="100%" height="auto" />
            </div>
            <span class="item-title">${itemName}</span>
            <p class="item-traits">${traitList}</p>
        </div>`;

        allItemsHTML += eachItem;
    });

    $('.cstm-grid').html(allItemsHTML);
}

4. 绑定筛选功能(可选)

给菜单选项绑定点击事件,通过类名匹配实现藏品筛选:

// 可放在buildFilterMenu函数末尾,或单独绑定事件
$(document).on('click', '.filter-menu li[data-trait-value]', function() {
    const traitType = $(this).data('trait-type');
    const traitValue = $(this).data('trait-value');
    const targetClass = `${traitType}${traitValue}`;

    // 切换选项选中状态
    $(this).toggleClass('active');
    
    // 获取所有选中的筛选类名
    const activeClasses = $('.filter-menu li.active').map(function() {
        return `${$(this).data('trait-type')}${$(this).data('trait-value')}`;
    }).get();

    if (activeClasses.length === 0) {
        // 无选中项时显示所有藏品
        $('.cstm-grid-item').show();
    } else {
        // 仅显示包含所有选中类的藏品
        $('.cstm-grid-item').hide();
        $('.cstm-grid-item').filter(`.${activeClasses.join('.')}`).show();
    }
});

关键说明

  • 用Promise.all解决异步请求的顺序问题,确保所有元数据获取完成后再处理
  • 借助Set自动去重特征值,无需手动判断重复
  • 给筛选选项添加自定义data-*属性,方便后续绑定筛选逻辑
  • 藏品类名与筛选选项一一对应,保证筛选时的精准匹配

内容的提问来源于stack exchange,提问作者JavaScriptLearner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:40:35