设计模式-发布订阅.js

  1. class Sub {
  2. construct(){
  3. this.obj = {};
  4. this.events = {
  5. key1: [],
  6. key2: [],
  7. }
  8. }
  9. change(key, value) {
  10. this.obj[key] = value
  11. if (this.events[key]) {
  12. this.events[key].forEach(fn => fn(value));
  13. }
  14. }
  15. watch(key, fn = () => {}) {
  16. if (this.events[key]) {
  17. this.events[key].push(fn);
  18. } else {
  19. this.events[key] = [fn];
  20. }
  21. }
  22. unWatch(key, fn) {
  23. if (!this.events[key]) return;
  24. // 此处应做严谨的事件相等判断
  25. this.events[key].filter(a => a !== fn);
  26. }
  27. }

设计模式-实现模版渲染.js

  1. // problem
  2. let template = "我是{{name}},年龄{{age}},性别{{sex}}";
  3. let data = {
  4. name: "姓名",
  5. age: 18,
  6. };
  7. render(template, data); // 我是姓名,年龄18,性别undefined
  8. // answer
  9. function render(template, data) {
  10. const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
  11. if (reg.test(template)) {
  12. // 判断模板里是否有模板字符串
  13. const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
  14. template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
  15. return render(template, data); // 递归的渲染并返回渲染后的结构
  16. }
  17. return template; // 如果模板没有模板字符串直接返回
  18. }

设计模式-实现虚拟DOM.js

  1. // problem
  2. let domNode = {
  3. tagName: "ul",
  4. props: { class: "list" },
  5. children: [
  6. {
  7. tagName: "li",
  8. children: ["item1"],
  9. },
  10. {
  11. tagName: "li",
  12. children: ["item1"],
  13. },
  14. ],
  15. };
  16. // 构建一个 render 函数,将 domNode 对象渲染为 以下 dom
  17. <ul class="list">
  18. <li>item1</li>
  19. <li>item2</li>
  20. </ul>;
  21. // answer
  22. function render(domNode) {
  23. if (!domNode) return document.createDocumentFragment();
  24. let $el;
  25. if (typeof domNode === "object") {
  26. $el = document.createElement(domNode.tagName);
  27. if (domNode.hasOwnProperty("props")) {
  28. for (let key in domNode.props) {
  29. $el.setAttribute(key, domNode.props[key]);
  30. }
  31. }
  32. if (domNode.hasOwnProperty("children")) {
  33. domNode.children.forEach((val) => {
  34. const $childEl = render(val);
  35. $el.appendChild($childEl);
  36. });
  37. }
  38. } else {
  39. $el = document.createTextNode(domNode);
  40. }
  41. return $el;
  42. }