如何实现一个简单的MVVM框架

接触过web开发的同学想必都接触过MVVM,业界著名的MVVM框架就有AngelaJS。今天闲来无事,决定自己实现一个简单的MVVM框架玩一玩。所谓简单,就是仅仅实现一个骨架,仅表其意,不摹其形。

分析

MVVM最大的特点莫过于双向绑定了,数据的变化能及时更新到视图上,同时视图的变化也能及时的更新到数据中。
那么怎么实现这样的双向绑定呢?最直接的方式莫过于事件了。
所以,我们需要实现一个事件的订阅与分发机制,这个功能很常见,网上搜一搜一大堆。
有了这么一套事件的订阅与分发机制,我们就可以通过它将Model和View关联起来,这样不管是Model还是View有变化,都可以通过事件通知到对方了。

实现

首先要实现一套事件的订阅与分发机制,直接贴代码了:

function Event() {  
    this.handlers = {};  
}

Event.prototype.on = function (eventName, handler) {
    if (!this.handlers) {
        this.handlers = {};
    }
    if (this.handlers[eventName]) {
        this.handlers[eventName].push(handler);
    } else {
        this.handlers[eventName] = [handler];
    }
}

Event.prototype.fire = function (eventName, eventData) {
    if (this.handlers[eventName]) {
        this.handlers[eventName].forEach(function (handler) {
            handler(eventData);
        });
    }
}

Event.prototype.off = function (eventName, handler) {
    if (this.handlers[eventName]) {
        for (var i = 0; i < this.handlers[eventName].length; i++) {
            if (this.handlers[eventName][i] === handler) {
                this.handlers[eventName].splice(i, 1);
            }
        }
    }
}  

上诉代码实现了某个事件的监听、触发与移除操作。

有了事件,如何将其与View和Model结合起来呢? 继承。

function Model(data) {
    this.data = data;
}

Model.prototype = new Object(Event.prototype);
Model.prototype.constructor = Model;

Model.prototype.set = function (key, value) {
    if (this.data[key]) {
        this.data[key] = value;
    }
    this.fire("change", value);
}


Model.prototype.get = function (key) {
    console.log("key: ", key, " value: ", this.data[key]);
}
function View(model, el) {
    this.el = el;
    this.model = model;

    this.init();
}

View.prototype.init = function () {
    var me = this;
    this.model.on("change", function (value) {
        me.model.get("value");
        if (me.el.type === "text") {
            me.el.value = value;
        } else {
            me.el.innerText = value;
        }       
    });
    if (this.el.type === "text") {
        this.el.addEventListener("change", function () {
            me.model.set("value", this.value);
        });
    } else {
        this.el.addEventListener("click", function () {
            var num = new Number(this.innerText || 0);
            me.model.set("value", num + 1);
        });
    }

}

View中为了简单处理,直接进行了硬编码,实际应用过程中需要详细处理。

到此,Model和View都有了,下面再加一段代码将他们关联起来:


function MVVM() {
    this.cache = {};
}

MVVM.prototype.bind = function (data, el) {
    var model = new Model(data);
    var view = new View(model, el);
    var key = "key_" + (new Date()).getTime();
    this.cache[key] = {
        model: model,
        view: view
    };
}

测试代码如下:

< !DOCTYPE html>
< html>
< head>
    < title>MVVM</title>
    < script type="text/javascript" src="./Event.js"></script>
    < script type="text/javascript" src="./Model.js"></script>
    < script type="text/javascript" src="./View.js"></script>
    < style type="text/css">
        #inputId {
            width: 300px;
            height: 30px;
            border: 1px solid grey;
            margin: 10px;
        }
        #textId {
            width: 300px;
            height: 100px;
            text-align: center;
            border: 1px solid black;
            line-height: 100px;
            font-size: 20px;
        }
    < /style>
< /head>
< body>
< div>
    < input id="inputId" type="text"></input>
    < div id="textId">0</div>
< /div>
< script type="text/javascript" src="./index.js"></script>
< script type="text/javascript">
var mvvm = new MVVM();
mvvm.bind({
    value: "text input"
}, document.getElementById("inputId"));
mvvm.bind({
    value: "div text"
}, document.getElementById("textId"));
< /script>
< /body>
< /html>

测试代码中绑定了一个输入框和一个div,当输入框中值发生改变时,Model中的值也会相应改变(查看控制台打印信息)。当点击div时,div中的文本数字会加一,对应Model中的数据也会改变。

到此所有的功能就实现完了,虽说简单了点,但是基本意思算是都到了,收工~~。

转载于:https://www.cnblogs.com/bingooo/p/5323228.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值