效果图如下:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.personalData {
display: none;
}
</style>
</head>
<body>
<div class="dataInputArea">
<div>
<span>请输入个人的姓名</span>
<input type="text" placeholder="姓名" class="nameData">
</div>
<div>
<span>请输入个人的年龄</span>
<input type="text" placeholder="年龄" class="ageData">
</div>
<div>
<span>请输入个人的特长</span>
<input type="text" placeholder="特长" class="specData">
</div>
<div class="personalData">
<p>
本人: <span class="name">王大少</span>,今年芳龄 <span class="age">0</span>,擅长 <span class="spec">吃饭</span>
</p>
</div>
</div>
<script>
//MVC模式
class MVC {
constructor (options) {
this.model = options.model //获取操作元素 负责事件的订阅与发布
this.controller = options.controller //事件绑定并订阅事件
this.view = options.view //更新页面数据
this.controller.bundle(this) //激活控制器
}
}
let mvc = new MVC({
model: {
data: {
vNameObj: document.querySelector('.nameData'),
vAgeObj: document.querySelector('.ageData'),
vSpecObj: document.querySelector('.specData'),
oName: document.querySelector('.name'),
oAge: document.querySelector('.age'),
oSpec: document.querySelector('.spec'),
oPersonal: document.querySelector('.personalData'),
nameValue: 0,
ageValue: 0,
specValue: 0
},
observe: {
clientList: {},
//订阅
listen (key, fn) {
if (!this.clientList[key]) {
this.clientList[key] = []
}
this.clientList[key].push(fn)
},
//发布
trigger () {
//获取第一个参数 发布的函数数组键名
let key = Array.prototype.shift.call(arguments)
let fns = this.clientList[key]
if (!fns || fns.length === 0) {
return false
}
for (let i=0, fn; fn =fns[i++];) {
fn.apply(this,arguments)
}
},
update (o, key, value) { //(MVC的this, '发布事件名', '改变的值')
let valueKey = '',
targetKey = '';
switch (key) {
case 'vNameObj':
valueKey = "nameValue" //数据内容变量
targetKey = "oName" //对应标签
break;
case 'vAgeObj':
valueKey = "ageValue"
targetKey = "oAge"
break;
case 'vSpecObj':
valueKey = "specValue"
targetKey = "oSpec"
break;
}
//更改MVC的this内的nameValue,ageValue,specValue值
o.model.data[valueKey] = value
//发布事件oName,oAge,oSpec
o.model.observe.trigger(targetKey, value)
}
}
},
controller: {
bundle (o) { //o指向MVC的this
let that = o
//给input标签添加监听事件
that.model.data.vNameObj.oninput = function () {
//通过更新事件 刷新数据(MVC的this, '发布事件名', '改变的值')
that.model.observe.update(that, "vNameObj", this.value)
}
that.model.data.vAgeObj.oninput = function () {
that.model.observe.update(that, "vAgeObj", this.value)
}
that.model.data.vSpecObj.oninput = function () {
that.model.observe.update(that, "vSpecObj", this.value)
}
//订阅事件oName,oAge,oSpec
that.model.observe.listen("oName", function (value) {
that.view.update(that, "oName", value)
})
that.model.observe.listen("oAge", function (value) {
that.view.update(that, "oAge", value)
})
that.model.observe.listen("oSpec", function (value) {
that.view.update(that, "oSpec", value)
})
}
},
view: {
update (o, targetKey, value) {
let that = o
//给页面标签设置内容
that.model.data[targetKey].innerText = value,
{nameValue, ageValue, specValue, oPersonal} = that.model.data;
//监听.oPersonal标签是否显示
if (nameValue && ageValue && specValue) {
oPersonal.style.display = "block"
} else {
oPersonal.style.display = "none"
}
}
}
})
/* MVC原理:
controller.bundle()绑定订阅事件 ——> 输入触发oninput事件
——> model.observe.update发布订阅事件 ——>执行对应订阅的事件
——> view.update() 修改页面对应数据
*/
/* 普通模式
let vNameObj = document.querySelector('.nameData'),
vAgeObj= document.querySelector('.ageData'),
vSpecObj = document.querySelector('.specData'),
oName = document.querySelector('.name'),
oAge = document.querySelector('.age'),
oSpec = document.querySelector('.spec'),
oPersonal = document.querySelector('.personalData'),
nameValue, ageValue, specValue;
// Controller控制模块
vNameObj.onchange = function (ev) {
nameValue = this.value
setObjInnerText(oName, nameValue)
}
vAgeObj.onchange = function (ev) {
ageValue = this.value
setObjInnerText(oAge, ageValue)
}
vSpecObj.onchange = function (ev) {
specValue = this.value
setObjInnerText(oSpec, specValue)
}
// view视图模块
function setObjInnerText(obj, value) {
obj.innerText = value
if (nameValue && ageValue && specValue) {
oPersonal.style.display = "block"
} else {
oPersonal.style.display = "none"
}
}
*/
</script>
</body>
</html>
逻辑结构图如下: