例子:
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() 专门监听函数调用的
```javascript
let _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’;
将类变成可响应
```javascript
let 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();