JS 中的数据与表现分离

刚接触 Django 的时候,碰到的最多的一句话就是 “django 是 MTV 架构的框架,是 MVC 模型的一个变种,M(model) 对应 model,T(templa) 对应 view,V(view) 对应 control”,当时对这段话不甚理解,也不明白为什么要实现表现、控制与数据分离。但在后面自己的学习过程中,我明显的发现自己项目上逻辑的混乱,特别是在 js 上,往往数据和控制混合在一起,复用性极差,自己水平也是有限,想复用同一组件就要修改很多地方。

正常情况下,我写的代码一般就像下面这样:

<!doctype html>
<head>
    <title></title>
    <script src="../jquery-1.7.1.js" type="text/javascript"></script>
    <script type="text/javascript"> $(document).ready(function () {
        var end = $('#end');
        $('#pili').change(function () {
            var name = '';
            var p = $(this).val();
            if (p == '叶小钗') {
                name = '刀狂剑痴';
            }
            if (p == '一页书') {
                name == '百世经纶';
            }
            if (p == '素还真') {
                name = '清香白莲';
            }
            end.html(name + p);
        });
    }); </script>
</head>
<body><select id="pili">
    <option value="叶小钗">叶小钗</option>
    <option value="一页书">一页书</option>
    <option value="素还真">素还真</option>
</select>
<div id="end"></div>
</body>
</doctype>

一开始觉得还不错,能实现功能了。但是,如果你的需求一旦发生改变了,你就会发现你又要修改大量地方,相当于重写代码了,比如:

  1. select 变成使用 input 模拟 select
  2. 在手机上使用 select

但是,如果用 MVC 模型写上面代码的话

<!doctype html>
<head><title></title>
    <script src="../jquery-1.7.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            //定义一个controller 
            var piliController = {
                //选择视图 
                start: function () {
                    this.view.start();
                },
                //将用户操作映射到模型更新上 
                set: function (name) {
                    this.model.setPerson(name);
                }
            };
            piliController.model = {
                piliKV: {
                    '叶小钗': '刀狂剑痴',
                    '一页书': '百世经纶',
                    '素还真': '清香白莲'
                },
                curPerson: null,
                //数据模型负责业务逻辑和数据存储 
                setPerson: function (name) {
                    this.curPerson = this.piliKV[name] ? name : null;
                    this.onchange();
                },
                //通知数据同步更新 
                onchange: function () {
                    piliController.view.update();
                },
                //相应视图对当前状态的查询 
                getPiliAction: function () {
                    return this.curPerson ? this.piliKV[this.curPerson] + this.curPerson : '???';
                }
            };
            piliController.view = {
                //用户触发change事件 
                start: function () {
                    $('#pili').change(this.onchange);
                },
                onchange: function () {
                    piliController.set($('#pili').val());
                },
                update: function () {
                    $('#end').html(piliController.model.getPiliAction());
                }
            };
            piliController.start();
        });
    </script>
</head>
<body><select id="pili">
    <option value="叶小钗">叶小钗</option>
    <option value="一页书">一页书</option>
    <option value="素还真">素还真</option>
</select>
<div id="end"></div>
</body>
</html>

初看这段代码的感觉:

  1. 代码维护困难,至少我认为很困难
  2. 徒增复杂性
  3. 我自己没看懂

不过回过头来好好审视下它,会发现不一样的东西:

  1. 我们好像就在view中使用了选择器获取dom,其它地方压根不认识dom这个丫的
  2. 我们的数据似乎在model中,我们可以随意改变,但是并不会影响到我们dom
  3. view和model是完全独立的,我们的controller恰好把他们串联起来了

看着这神奇的魔法,我似懂非懂的点了点头,你妹的MVC还真他妈够劲!!!