如何封装可复用的jQuery $.getJSON与$.each逻辑以减少重复代码
问题分析与解决方案
封装可行性与价值
这种封装完全可行,且实际价值很高。重复逻辑抽离后,后续调整商品HTML模板、统一加埋点、统一加加载状态都只需要修改一处代码,大幅降低维护成本。
报错原因
你遇到的报错有两个核心诱因:
- 调用通用函数时直接传入
data.bundle.products,但此时AJAX请求还未发起,data根本不存在,你传入的是未定义的变量,自然无法被$.each正常遍历 - 第三个参数你传入的是选择器字符串(比如
.bundle),通用函数中直接调用.html()方法不生效,需要先转为jQuery对象
另外原有代码还有个隐藏bug:products.join('');没有赋值给变量,执行后products还是数组,插入DOM时可能不符合预期。
调整后的实现方案
第一步:修正通用函数
我们把第二个参数改成数据提取函数,等请求拿到data后再执行这个函数拿到对应的商品数组,即可解决data不存在的问题:
function createProductContent(url, dataExtractor, containerSelector) { return $.getJSON(url, function(data) { // 调用传入的提取函数,从返回的data里拿到商品数组 const productList = dataExtractor(data); const products = []; $.each(productList, function(index, product) { const productHtml = `<div class="item">${product.title}</div>`; products.push(productHtml); }); // 把join的结果赋值,同时转成jQuery对象再插入内容 $(containerSelector).html(products.join('')); }); }
第二步:调整调用方式
调用的时候第二个参数传一个函数,用来从返回的data里提取对应的商品数组:
function abc() { createProductContent('url-to-a', (data) => data.bundle.products, '.bundle'); } function xyz() { createProductContent('url-to-different-location', (data) => data.search.products, '.search'); }
可选优化
如果后续需要灵活调整不同场景的商品HTML结构,你还可以把单个商品的渲染逻辑也抽成参数,灵活度更高:
// 新增第四个参数:单个商品渲染函数 function createProductContent(url, dataExtractor, containerSelector, renderItem) { return $.getJSON(url, function(data) { const productList = dataExtractor(data); const products = productList.map(product => renderItem(product)); $(containerSelector).html(products.join('')); }); } // 调用示例 function abc() { createProductContent( 'url-to-a', (data) => data.bundle.products, '.bundle', (product) => `<div class="item">${product.title},售价:${product.price}</div>` ); }
内容的提问来源于stack exchange,提问作者Meules
相关产品推荐
相关产品推荐

