JS自定义Templater类嵌套方法正常但链式调用报错问题求助
问题原因
当前所有元素生成方法(div/span/p等)直接返回HTML字符串,字符串原型上不存在你定义的元素方法,链式调用时会抛出方法未定义错误。
改造方案
需要做3处核心调整:
- 给Templater类新增内部缓存属性,存储累计生成的HTML字符串
- 所有元素方法生成标签片段后追加到缓存,返回当前类实例
this支持链式调用 - 自定义
toString方法返回缓存的完整HTML字符串,可按需配置调用后是否清空缓存以支持实例复用
改造后完整代码
class Templater { // 私有属性存储HTML缓存 #htmlBuffer = ''; transform(tags) { // 兼容嵌套的Templater实例,自动转成字符串 return tags.map(item => item instanceof Templater ? item.toString() : item).join(""); } // 返回值结构:[属性字符串, inner内容数组] attributesCheck(tags) { let attributeObject = {}; tags.forEach((item) => { if(typeof item === 'object' && item !== null && !Array.isArray(item) && !(item instanceof Templater)) { attributeObject = item; } }) const content = tags.filter(item => (typeof item !== 'object' || item instanceof Templater)) let objectArr = Object.entries(attributeObject); let classIndex; let idIndex; objectArr.forEach((item, index) => { if(item[0] === 'class') { classIndex = index; } if (item[0] === 'id') { idIndex = index; } }) const classItem = objectArr[classIndex]; const idItem = objectArr[idIndex]; objectArr = objectArr.filter(item => item[0] !== 'class' && item[0] !== 'id') if (idItem) { objectArr.unshift(idItem); } if (classItem) { objectArr.unshift(classItem); } let attrString = ''; objectArr.forEach(item => { attrString += ` ${item[0]}="${item[1]}"` }) return [attrString, content]; } // 抽离单个标签生成逻辑,返回字符串,兼容嵌套场景 #createTag(tagName, ...tags) { const [attrString, content] = this.attributesCheck(tags); if(tagName === 'br') { if(tags.length) throw new Error('Nested content is not allowed'); return `<br>`; } return `<${tagName}${attrString}>${this.transform(content)}</${tagName}>`; } div(...tags) { this.#htmlBuffer += this.#createTag('div', ...tags); return this; } span(...tags) { this.#htmlBuffer += this.#createTag('span', ...tags); return this; } br() { this.#htmlBuffer += this.#createTag('br'); return this; } p(...tags) { this.#htmlBuffer += this.#createTag('p', ...tags); return this; } // 自定义toString,返回结果后默认清空缓存,不需要清空可删除第二行 toString() { const result = this.#htmlBuffer; this.#htmlBuffer = ''; return result; } }
测试用例验证
const template = new Templater(); // 单个标签场景 console.log(template.div('1454', {id: 'fixing'}).toString()); // 输出:<div id="fixing">1454</div> console.log(template.div('World of Templates', {id: "card", class: 'first'}).toString()); // 输出:<div class="first" id="card">World of Templates</div> // 嵌套场景 console.log(template.div( template.p('Hello', {id: 'fix', class: "first-p"}), template.p('World') ).toString()); // 输出:<div><p class="first-p" id="fix">Hello</p><p>World</p></div> // 链式调用场景 console.log(template.span('Hello').span('World').toString()); // 输出:<span>Hello</span><span>World</span>
内容的提问来源于stack exchange,提问作者Rurohi53
相关产品推荐
相关产品推荐

