实现一个简陋的MVC框架

来源:互联网 发布:mac pro 屏幕涂层脱落 编辑:程序博客网 时间:2024/05/17 03:05

参考文章:30行代码实现Javascript中的MVC

MVC过程介绍

用户对View操作以后,View捕获到这个操作,会把处理的权利交移给Controller,Controller对相应的Model进行修改,当Model变更了以后,会通过观察者模式通知View进行更新。这里的关键步骤就是实现观察者模式。

实现过程

  1. 首先我们要明确我们的目标:实现数组的排序
<input type="button" value="reverse" id="toggleBtn"/><!--页面初始化后,input会显示数组的初始化值,当点击reverse按钮后,显示反转后的数组--><input type="text" data-bind="arr"><!--用于测试多个dom结点绑定同一变量的情况--><input type="text" data-bind="arr">
new Controller(function (model){    var data = [1,2,3,4,5];    //调用set后,绑定了该数据的视图,会做相应的改变    model.arr.set(data);    var toggleBtn = document.getElementById('toggleBtn');    toggleBtn.addEventListener('click',function () {        //同样会自动更新视图        model.arr.set(data.reverse());    })});

所以,这里关键的地方就是构造一个model对象,在model对象上事先已经绑定了所有的数据和其对应的视图,一旦某一个数据被改变,相应的视图也会进行更新。
2. 设计我们的MVC框架——mvc.js
定义一个观察者模式

function SubPub() {    this.value = "";    this.doms = [];}//类似于观察者中的publishSubPub.prototype.set = function (value) {    var self = this;     selt.value = value;    //异步更新队列    setTimeout(function () {        self.doms.forEach(function (dom) {            dom.value = value.toString();        })    },0)}//类似于观察者中的subscribeSubPub.prototype.bind = function (dom) {    this.doms.push(dom);}
function Controller(callback) {    var doms = document.querySelectorAll('[data-bind]');    var model= {};    doms.forEach(function (dom) {        var data = dom.getAttribute('data-bind');        //可能多个dom结点绑定同一变量        model[data] = model[data] || new SubPub();        model[data].bind(dom);    })    callback.call(this,model);}

使用ES5的新特性——Object.defineProperty

上面的代码中,我们修改数据时是这样的:

model.arr.set(data);

不是很自然,可不可换成这样呢:

model.arr = data;

实现这个功能就要用到Object.defineProperty中的set了,这样我们也不需要定义观察者了。
最后我们的mvc.js变成这样:

function Controller(callback) {    var model = {};    var doms = document.querySelectorAll('[data-bind]');    doms.forEach(function (dom) {        var data = dom.getAttribute('data-bind');        if(model.data===undefined){            model.data = null;            var targets = document.querySelectorAll('[data-bind=' + data + ']');            Object.defineProperty(model,data,{                set: function (value) {                    model.data = value;                    targets.forEach(function (target) {                        target.value = value;                    })                }            })        }    })    callback.call(this,model);}
0 0
原创粉丝点击