水水月牙

文章 评论 浏览 658

水水月牙 2022-05-04 13:30:20

利用Proxy实现一个简化版的MVVM
参照vue的响应式设计模式,将数据劫持部分的Obejct.defineProperty替换为Proxy即可,其他部分,如compile(编译器没有实现,用写好的html模拟已完成编译),watcher,dep,事件监听等基本保持不变,简单实现代码如下:

<!-- html部分 -->
<div></div>
<input type="text" name=""/>
// js部分
class Watcher{
	constructor(cb){
		this.cb = cb;
	}
	update(){
		this.cb()
	}
}
class Dep{
	constructor(){
		this.subs = [];
	}
	publish(){
		this.subs.forEach((item)=>{
			item.update && item.update();
		})
	}
}
class MVVM{
	constructor(data){
		let that = this;
		this.dep = new Dep();
		this.data = new Proxy(data,{
			get(obj, key, prox){
				that.dep.target && that.dep.subs.push(that.dep.target);
				return obj[key]
			},
			set(obj, key, value, prox){
				obj[key] = value;
				that.dep.publish();
				return true;
			}
		})
		this.compile();
	}
	compile(){
		
		let divWatcher = new Watcher(()=>{
			this.compileUtils().div();
		})
		this.dep.target = divWatcher;
		this.compileUtils().div();
		this.dep.target = null;
		
		let inputWatcher = new Watcher(()=>{
			this.compileUtils().input();
		})
		this.dep.target = inputWatcher;
		this.compileUtils().input();
		this.compileUtils().addListener();
		this.dep.target = null;
	}
	compileUtils(){
		let that = this;
		return {
			div(){
				document.getElementById('foo').innerHTML = that.data.foo;
			},
			input(){
				document.getElementById('bar').value = that.data.bar;
			},
			addListener(){
				document.getElementById('bar').addEventListener('input', function(){
					that.data.bar = this.value;
				})
			}
		}
	}
}
let mvvm = new MVVM({foo: 'foo233', bar: 'bar233'})

通过mvvm.data.foo或者mvvm.data.bar可以操作数据,可以观察到view做出了改变;在输入框改变输入值,也可以通过mvvm.data观察到数据被触发改变

第 74 题: 使用 JavaScript Proxy 实现简单的数据绑定

更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文