基于JS对象批量生成CMS自定义按钮及绑定点击函数的问题求助
问题描述
正在通过Tampermonkey为CMS添加带点击函数的自定义UI按钮,现有代码可正常运行,但正优化为基于对象键值对渲染按钮HTML(此部分已实现)。当前需求是将每个按钮的独立点击函数合并为单个函数,根据遍历的对象键注入对应值,但在注入函数时遇到阻碍。
新格式(基于对象)代码
let campaignButtonsObj = [ { name: 'tenZeroZero', id: 'ten-zero-zero', cta: '1000', width:'45', onclick: 'tenZeroZeroClick', function: 'tenZeroZeroButtonClick', searchQuery: '#10 #00 - 1000', addFunction: 'addTenZeroZero', clickValue: 'NEW1000' }, { name: 'twentyOnly', id: 'twenty-only', cta: '20', width: '35', onclick: 'twentyClick', function: 'twentyButtonClick', searchQuery: '#20 - 20', addFunction:'addTwentyOnly', clickValue: 'NEW20' } ]; const generatedHtml = Object.keys(campaignButtonsObj).reduce((accum, currKey) => accum + `<span class="sc-GQHCi fjxikX" style="display: block;"><button onclick="${campaignButtonsObj[currKey].onclick}()"class="sc-cUEOzv hEBGGF eEeywh" id="${campaignButtonsObj[currKey].id}" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: ${campaignButtonsObj[currKey].width}px;display: flex;align-items: center;justify-content: center;">${campaignButtonsObj[currKey].cta}</div></button></span>`, ''); // 此处报错,需要帮助 const buttonClick = Object.keys(campaignButtonsObj).reduce((accum, currKey) => accum + `function ${campaignButtonsObj[currKey].onclick}(){document.querySelector('[id="${campaignButtonsObj[currKey].id}"]').innerHTML = '${campaignButtonsObj[currKey].clickValue}';`, ''); const buttonAdd = Object.keys(campaignButtonsObj).reduce((accum, currKey) => accum + `function ${campaignButtonsObj[currKey].addFunction}(){document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', ${campaignButtonsObj[currKey].name});document.getElementById("${campaignButtonsObj[currKey].id}").onclick = function() {${campaignButtonsObj[currKey].onclick}();};}`, ''); let newButtonContainer = '<div id="new-button-container" style="display:flex;align-items:center"></div>'; document.querySelector('[id="myDiv"]').insertAdjacentHTML('afterend', newButtonContainer); document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', generatedHtml);
初始独立元素与函数写法
let tenZeroZero = '<span class="sc-GQHCi fjxikX" style="display: block;"><button id="ten-zero-zero" class="sc-cUEOzv hEBGGF eEeywh" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: 35px;display: flex;align-items: center;justify-content: center;">1000</div></button></span>'; let twentyOnly = '<span class="sc-GQHCi fjxikX" style="display: block;"><button id="twenty-only" class="sc-cUEOzv hEBGGF eEeywh" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: 35px;display: flex;align-items: center;justify-content: center;white-space:pre">20</div></button></span>'; // 希望将遍历对象的值注入到此类函数中 function tenZeroZeroClick() { var input = document.querySelector('[id="campaign-search-input"]'); var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, '#10 #00 - 1000'); var ev2 = new Event('input', { bubbles: true }); input.dispatchEvent(ev2); } function twentyClick() { var input = document.querySelector('[id="campaign-search-input"]'); var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, '#20 - 20'); var ev2 = new Event('input', { bubbles: true }); input.dispatchEvent(ev2); } function addTenZeroZero() { document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', tenTwenty); document.getElementById("ten-zero-zero").onclick = function() { tenZeroZeroClick(); }; } function addTwentyOnly() { document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', twentyOnly); document.getElementById("twenty-only").onclick = function() { twentyClick(); }; }
解决方案
核心思路
放弃通过字符串拼接生成函数的方式,改用通用处理函数结合事件绑定的方案,直接利用对象中的配置参数完成逻辑,避免动态生成函数带来的语法错误和维护问题。
优化后代码
let campaignButtonsObj = [ { name: 'tenZeroZero', id: 'ten-zero-zero', cta: '1000', width:'45', searchQuery: '#10 #00 - 1000', clickValue: 'NEW1000' }, { name: 'twentyOnly', id: 'twenty-only', cta: '20', width: '35', searchQuery: '#20 - 20', clickValue: 'NEW20' } ]; // 通用点击处理函数 function handleButtonClick(config) { // 更新按钮显示文本 document.getElementById(config.id).innerHTML = `<div style="height: 20px;width: ${config.width}px;display: flex;align-items: center;justify-content: center;">${config.clickValue}</div>`; // 执行搜索输入逻辑 const input = document.querySelector('[id="campaign-search-input"]'); const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, config.searchQuery); const ev2 = new Event('input', { bubbles: true }); input.dispatchEvent(ev2); } // 通用添加按钮函数 function addButton(config) { const buttonHtml = `<span class="sc-GQHCi fjxikX" style="display: block;"><button class="sc-cUEOzv hEBGGF eEeywh" id="${config.id}" style="margin-right: 0.571429rem;background-color: rgb(36, 137, 169);color:#fff;border-radius:300px;border:none"><div style="height: 20px;width: ${config.width}px;display: flex;align-items: center;justify-content: center;">${config.cta}</div></button></span>`; document.querySelector('[id="new-button-container"]').insertAdjacentHTML('beforeend', buttonHtml); // 绑定点击事件,传入当前按钮配置 document.getElementById(config.id).addEventListener('click', () => handleButtonClick(config)); } // 初始化容器并渲染所有按钮 const newButtonContainer = '<div id="new-button-container" style="display:flex;align-items:center"></div>'; document.querySelector('[id="myDiv"]').insertAdjacentHTML('afterend', newButtonContainer); // 遍历对象,批量添加按钮 campaignButtonsObj.forEach(config => addButton(config));
优化点说明
- 移除冗余字段:删除了对象中
onclick、function、addFunction等冗余字段,直接通过配置对象传递参数。 - 通用函数复用:创建
handleButtonClick和addButton两个通用函数,分别处理按钮点击逻辑和按钮添加逻辑,无需为每个按钮单独定义函数。 - 事件绑定更可靠:使用
addEventListener绑定事件,避免内联onclick属性的安全风险和维护问题,同时通过箭头函数直接传入当前按钮的配置对象。 - 避免字符串拼接函数:彻底放弃动态生成函数字符串的方案,消除语法错误隐患,代码可读性和可维护性大幅提升。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

