设计模式-发布订阅.js
class Sub { construct(){ this.obj = {}; this.events = { key1: [], key2: [], } } change(key, value) { this.obj[key] = value if (this.events[key]) { this.events[key].forEach(fn => fn(value)); } } watch(key, fn = () => {}) { if (this.events[key]) { this.events[key].push(fn); } else { this.events[key] = [fn]; } } unWatch(key, fn) { if (!this.events[key]) return; // 此处应做严谨的事件相等判断 this.events[key].filter(a => a !== fn); }}
设计模式-实现模版渲染.js
// problemlet template = "我是{{name}},年龄{{age}},性别{{sex}}";let data = { name: "姓名", age: 18,};render(template, data); // 我是姓名,年龄18,性别undefined// answerfunction render(template, data) { const reg = /\{\{(\w+)\}\}/; // 模板字符串正则 if (reg.test(template)) { // 判断模板里是否有模板字符串 const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段 template = template.replace(reg, data[name]); // 将第一个模板字符串渲染 return render(template, data); // 递归的渲染并返回渲染后的结构 } return template; // 如果模板没有模板字符串直接返回}
设计模式-实现虚拟DOM.js
// problemlet domNode = { tagName: "ul", props: { class: "list" }, children: [ { tagName: "li", children: ["item1"], }, { tagName: "li", children: ["item1"], }, ],};// 构建一个 render 函数,将 domNode 对象渲染为 以下 dom<ul class="list"> <li>item1</li> <li>item2</li></ul>;// answerfunction render(domNode) { if (!domNode) return document.createDocumentFragment(); let $el; if (typeof domNode === "object") { $el = document.createElement(domNode.tagName); if (domNode.hasOwnProperty("props")) { for (let key in domNode.props) { $el.setAttribute(key, domNode.props[key]); } } if (domNode.hasOwnProperty("children")) { domNode.children.forEach((val) => { const $childEl = render(val); $el.appendChild($childEl); }); } } else { $el = document.createTextNode(domNode); } return $el;}