实现一个简陋的MVC框架

参考文章: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 = [];
}
//类似于观察者中的publish
SubPub.prototype.set = function (value) {
    var self = this; 
    selt.value = value;
    //异步更新队列
    setTimeout(function () {
        self.doms.forEach(function (dom) {
            dom.value = value.toString();
        })
    },0)
}
//类似于观察者中的subscribe
SubPub.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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值