我个人以为mvvm框架里面最重要的一点就是VM这部分,它要与Model层建立联系,将Model层转换成可以被View层识别的数据结构;其次也要同View建立联系,将数据及时更新到View层上,并且响应View对数据的更改,同步到Model层。
MVVM的具体例子,可以看一下阮一峰老师的。
我们提取其中比较关键的点:
Model层,我们用一个对象来代表。例如:
let data = { text: 'foo' };
View层对于我们而言,可以认为是DOM节点。例如:
<div id="app"> <p>text</p> </div>
为了方便注入内容,改用JS来写,可以写成
let str = `<div id="app"><p>test</p></div>`;
至于View-Model,我们要做两件事,一是将数据及时同步到View层,二是响应用户事件,更改数据。我们设计一个函数来完成这项工作。
// 把对象转成可监听的 const ob = function (data) { // 无new构造 if (!(this instanceof ob)) { return new ob(data); } // 设定观察者列表 let observerList = []; // 暴露添加观察者方法 this.addOb = function (fn) { observerList.push(fn); } // 遍历属性,通过defineProperty来对属性变化做监听 for (let key in data) { let value = data[key]; Object.defineProperty(data, key, { enumerable:true, // 枚举 get () { return value; }, set (newVal) { value = newVal; observerList.forEach((el)=>{ el(newVal); }) } }) } };
为了简单起见,把View的渲染封装成一个函数,当然实际上不能这么操作。
const render = (text) => { document.getElementById('app').innerHTML = '<p>'+ text +'</p>'; }
然后将render和数据绑定起来。
let testObj = { name: 'liu' }; const vm = (data) => { render(testObj.name); let newOb = ob(data); newOb.addOb(function () { render(data.name); }) }; vm(testObj); // 如果直接设置testObj.name = 'test';就会触发对应的修改
以上,基本上实现了数据和视图间的绑定。
可以再继续改进,在render之前,加入virtual dom的逻辑,或者加入一些语法特性,比如类似VUE和React的语法糖。
由于直接设置对象属性其实不大安全,而且不易于追踪,可以把状态统一提取出来,进一步封装,只能通过action去触发修改,然后分发到各个调用方。保证数据的单项流动。
这里是一个简单的。
感谢阅读。
如对本文有疑问, 点击进行留言回复!!
MFC的静态库.lib、动态库.dll(包含引入库.lib)以及Unicode库示例
CTF 刷题记录(一) 白云新闻搜索(手动与自动化SQL注入)
javascript如何使用函数random来实现课堂随机点名方法详解
网友评论