例子:
    HOC高阶类
    1. 在父类中使用了子类才有的东西
    2. 类写完不直接用 - 包裹一下

    1. class Store{
    2. constructor() {
    3. this._state = {};
    4. }
    5. get(key) {
    6. if(key in this._state) {
    7. return this._state[key];
    8. } else {
    9. throw new Error(`${key} is not find`);
    10. }
    11. }
    12. set(key, value) {
    13. this._state[key] = value
    14. }
    15. connect(cls) {
    16. const store = this;
    17. return class extends cls {
    18. constructor(...args) {
    19. super(...args);
    20. this.get = store.get.bind(store);
    21. this.set = store.set.bind(store);
    22. }
    23. }
    24. }
    25. }
    26. const store = new Store();
    27. const A = store.connect(class {
    28. constructor() {}
    29. show() {
    30. this.set('a', 24);
    31. console.log(this.get('a'));
    32. }
    33. });
    34. const B = store.connect(class {
    35. constructor() {}
    36. setA() {
    37. this.set('a', 12);
    38. }
    39. });
    40. let a = new A();
    41. let b = new B();
    42. b.setA();
    43. a.show();

    可响应对象
    属性可以被监听的

    1. 访问器 - get / set
      优点:好用 ```javascript class A{ constructor() { this._count = 0; }

      get count() { return this._count }

      set count(val) { this._count = val; } };

    let a = new A(); a.count = 55; console.log(a.count);

    1. 2. defineProperty 缺陷
    2. 可指定一些行为,操作数组内部东西-无响应
    3. ```html
    4. <!DOCTYPE html>
    5. <html lang="en">
    6. <head>
    7. <meta charset="UTF-8">
    8. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    9. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    10. <title>Document</title>
    11. <script src="js/assert.js"></script>
    12. </head>
    13. <body>
    14. <div id="hotList"></div>
    15. <script>
    16. class HotList{
    17. constructor(options) {
    18. assert(options, 'options不能没有');
    19. this._root = this._getRoot(options);
    20. this._defineData(options);
    21. this.update = false;
    22. }
    23. // 创建根元素
    24. _getRoot(options) {
    25. assert(options.root, 'root不能没有');
    26. if(typeof options.root === 'string') {
    27. // 根据查询节点寻找
    28. return document.querySelector(options.root);
    29. // 如果没找到 提示错误
    30. assert(root, `没有找到 ${options.root}`);
    31. } else if(options.root instanceof HTMLElement) {
    32. return options.root;
    33. } else {
    34. assert(false, 'root不合法')
    35. }
    36. }
    37. // 定义data
    38. _defineData(options) {
    39. assert(options.data, 'options.data不能没有');
    40. assert(typeof options.data === 'function', 'options.data必须是函数');
    41. const data = options.data();
    42. assert(data, 'options.data 必须有返回值');
    43. assert(typeof data === 'object', 'data必须是object');
    44. this.data = data;
    45. for(let name in data){
    46. Object.defineProperty(this, name, {
    47. configurable: true,
    48. get() {
    49. return data[name];
    50. },
    51. set(val) {
    52. data[name] = val;
    53. this.render();
    54. }
    55. })
    56. }
    57. }
    58. // 为了处理 defineProperty操作数组内部东西-无响应
    59. $set(obj, name, val){
    60. this.update = false;
    61. obj[name] = val;
    62. if(!this.update) {
    63. this.render();
    64. }
    65. }
    66. render() {
    67. let div = document.createElement('div');
    68. div.className = "v-hd";
    69. div.innerHTML = this.title;
    70. const ul = document.createElement("ul");
    71. ul.className = "user-list";
    72. for(let v of this.data){
    73. const li = document.createElement("li");
    74. li.innerHTML = `<div class='title'>${v.title}</div><div class='detail'>${v.detail}</div><div class="author">${v.author}</div>`;
    75. ul.appendChild(li);
    76. }
    77. this._root.innerHTML = '';
    78. this._root.appendChild(div);
    79. this._root.appendChild(ul);
    80. }
    81. }
    82. let list = new HotList({
    83. root: '#hotList',
    84. data() {
    85. return {
    86. title: '热门主播',
    87. data: [
    88. {
    89. title: '热门1',
    90. detail: '独家独家独家独家',
    91. author: '定海村'
    92. },
    93. {
    94. title: '热门2',
    95. detail: '的独家独家独家独家经典',
    96. author: '大口袋'
    97. },
    98. {
    99. title: '热门3',
    100. detail: '独家独家独家独家',
    101. author: '定海村'
    102. }
    103. ]
    104. }
    105. }
    106. });
    107. list.render();
    108. </script>
    109. </body>
    110. </html>
    1. Proxy

      前身: observe
      Proxy - 基本使用及常见的方法 ```javascript /*

      1. Proxy 好用 前身: observe Proxy - 基本使用及常见的方法 */

    // 真实的数据 let _data = { a: 12, arr: [1, 2, 3], json: {a: 12, b:5} };

    const p = new Proxy(_data, { has(data, name){ if(name in data) { return true; } }, get(data, name){ // 获取 if(data[name]) { return data[name] } else { throw new Error(${data[name]} is not defined) } }, set(data, name, val){ // 设置 console.log(‘set’); data[name] = val; }, deleteProperty(data, name) { // 删除属性 if(name in data) { return delete data[name] } else { throw new Error(${data[name]} is not defined) } },

    })

    1. 4. Proxy可以和函数配合<br /> apply() 专门监听函数调用的
    2. ```javascript
    3. let _data = function (a, b, c) {
    4. console.log(a+b+c);
    5. }
    6. const p = new Proxy(_data, {
    7. // 监听函数
    8. apply(fn, thisValue, args){
    9. fn(...args);
    10. }
    11. });
    12. p(2, 3, 4);
    1. Proxy可以和数组配合

      1. let _data = [1, 2, 3];
      2. const p = new Proxy(_data, {
      3. get(data, name){
      4. console.log('get');
      5. // 获取
      6. if(data[name]) {
      7. return data[name]
      8. } else {
      9. throw new Error(`${data[name]} is not defined`)
      10. }
      11. },
      12. set(data, name, val){
      13. // 设置
      14. console.log('set');
      15. data[name] = val;
      16. },
      17. });
      18. console.log(p);

      6.Proxy可以和类配合 ```javascript class A{ render() { console.log(‘渲染’); } }

    let a = new Proxy(new A(), { set(obj, name, val){ obj[name] = val; obj.render(); } });

    a.name = ‘summer’;

    1. 将类变成可响应
    2. ```javascript
    3. let A = new Proxy(class {
    4. render(){
    5. console.log('render');
    6. }
    7. },
    8. {
    9. construct(Cls, args) {
    10. const obj = new Cls();
    11. return new Proxy(obj, {
    12. set(obj, key, value) {
    13. obj[key] = value;
    14. obj.render();
    15. }
    16. })
    17. }
    18. }
    19. );
    20. const a = new A();