例子:
HOC高阶类
1. 在父类中使用了子类才有的东西
2. 类写完不直接用 - 包裹一下
class Store{constructor() {this._state = {};}get(key) {if(key in this._state) {return this._state[key];} else {throw new Error(`${key} is not find`);}}set(key, value) {this._state[key] = value}connect(cls) {const store = this;return class extends cls {constructor(...args) {super(...args);this.get = store.get.bind(store);this.set = store.set.bind(store);}}}}const store = new Store();const A = store.connect(class {constructor() {}show() {this.set('a', 24);console.log(this.get('a'));}});const B = store.connect(class {constructor() {}setA() {this.set('a', 12);}});let a = new A();let b = new B();b.setA();a.show();
可响应对象
属性可以被监听的
访问器 - 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);
2. defineProperty 缺陷可指定一些行为,操作数组内部东西-无响应```html<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/assert.js"></script></head><body><div id="hotList"></div><script>class HotList{constructor(options) {assert(options, 'options不能没有');this._root = this._getRoot(options);this._defineData(options);this.update = false;}// 创建根元素_getRoot(options) {assert(options.root, 'root不能没有');if(typeof options.root === 'string') {// 根据查询节点寻找return document.querySelector(options.root);// 如果没找到 提示错误assert(root, `没有找到 ${options.root}`);} else if(options.root instanceof HTMLElement) {return options.root;} else {assert(false, 'root不合法')}}// 定义data_defineData(options) {assert(options.data, 'options.data不能没有');assert(typeof options.data === 'function', 'options.data必须是函数');const data = options.data();assert(data, 'options.data 必须有返回值');assert(typeof data === 'object', 'data必须是object');this.data = data;for(let name in data){Object.defineProperty(this, name, {configurable: true,get() {return data[name];},set(val) {data[name] = val;this.render();}})}}// 为了处理 defineProperty操作数组内部东西-无响应$set(obj, name, val){this.update = false;obj[name] = val;if(!this.update) {this.render();}}render() {let div = document.createElement('div');div.className = "v-hd";div.innerHTML = this.title;const ul = document.createElement("ul");ul.className = "user-list";for(let v of this.data){const li = document.createElement("li");li.innerHTML = `<div class='title'>${v.title}</div><div class='detail'>${v.detail}</div><div class="author">${v.author}</div>`;ul.appendChild(li);}this._root.innerHTML = '';this._root.appendChild(div);this._root.appendChild(ul);}}let list = new HotList({root: '#hotList',data() {return {title: '热门主播',data: [{title: '热门1',detail: '独家独家独家独家',author: '定海村'},{title: '热门2',detail: '的独家独家独家独家经典',author: '大口袋'},{title: '热门3',detail: '独家独家独家独家',author: '定海村'}]}}});list.render();</script></body></html>
Proxy
前身: observe
Proxy - 基本使用及常见的方法 ```javascript /*- 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)
}
},
})
4. Proxy可以和函数配合<br /> apply() 专门监听函数调用的```javascriptlet _data = function (a, b, c) {console.log(a+b+c);}const p = new Proxy(_data, {// 监听函数apply(fn, thisValue, args){fn(...args);}});p(2, 3, 4);
Proxy可以和数组配合
let _data = [1, 2, 3];const p = new Proxy(_data, {get(data, name){console.log('get');// 获取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;},});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’;
将类变成可响应```javascriptlet A = new Proxy(class {render(){console.log('render');}},{construct(Cls, args) {const obj = new Cls();return new Proxy(obj, {set(obj, key, value) {obj[key] = value;obj.render();}})}});const a = new A();
