发布订阅模式
我把发布订阅的实现类单独提出来,这样代码看起来简洁
/*
* 发布订阅
**/
class Pubsub {
static instance = null;
// 单例
static getInstance() {
if (Pubsub.instance == null) {
Pubsub.instance = new Pubsub;
}
return Pubsub.instance;
}
// 注册的事件和处理器关联集合
eventAndHandel = {};
// 触发
emit(eventName, params) {
if (this.eventAndHandel.hasOwnProperty(eventName)) {
this.eventAndHandel[eventName].forEach(hander => {
hander(params)
});
}
}
// 注册or订阅
on(eventName, cbc) {
if (!this.eventAndHandel.hasOwnProperty(eventName)) {
this.eventAndHandel[eventName] = [cbc]
} else {
this.eventAndHandel[eventName].push(cbc)
}
}
}
第一版本
最普通的语法
<!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>
</head>
<body>
<div>
<h1 d-bind="name"></h1>
<span d-bind="name"></span>:<span d-bind="age"></span>
</div>
<div>
姓名:<input d-model="name" type="text"></br>
性别:<input d-model="age" type="text"></br>
</div>
<!-- <script src="./lodash.js"></script> -->
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js"></script>
<script src="./helper.js"></script>
<script>
// ---------------------一个vue实例开始----------------------------
const data = {
name: '丁少华',
age: 20
};
// v-model的实现
const models = document.querySelectorAll(`[d-model]`);
models.forEach(item => {
const v = item.getAttribute('d-model');
item.oninput = function ({ target: { value } }) {
data[v] = value;
}
})
// 双向绑定的实现
const pubsub = Pubsub.getInstance();
const data_ = _.cloneDeep(data);
for (const key in data) {
Object.defineProperty(data, key, {
set(newValue) {
data_[key] = newValue;
pubsub.emit('vm', {
id: key,
value: newValue
})
},
get() {
return data_[key];
}
})
}
pubsub.on('vm', ({ id, value }) => {
// 给普通节点复制
const binds = document.querySelectorAll(`[d-bind=${id}]`);
binds.forEach(item => {
item.innerText = value;
})
// 给表单控件赋值
const models = document.querySelectorAll(`[d-model=${id}]`);
models.forEach(item => {
item.value = value;
})
});
// 初始化赋值
for (const key in data) {
data[key] = data[key];
}
</script>
</body>
</html>