0°

使用jQuery实现MVC

针对业界MVC的DEMO-todo的例子(项目主页:http://todomvc.com/),简单对比使用jQuery实现mvc及各框架对MVC的实现。

先了解这个todo-demo——

1. 初始化查询列表——

2.添加记录——

3.删除记录——

4.修改记录——

5.对model集合的操作(标示那些完成、清除完成项)

app.html

<section id="todoapp"><header id="header"><h1>todos</h1><input id="new-todo" placeholder="What needs to be done?" autofocus></header><section id="main"><input id="toggle-all" type="checkbox"><label for="toggle-all">Mark all as complete</label><ul id="todo-list"></ul></section><footer id="footer"><span id="todo-count"><strong>0</strong> item left</span><button id="clear-completed">Clear completed</button></footer>
</section>
<footer id="info"><p>Double-click to edit a todo</p><p>Created by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p><p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>

<!-- ************************************* template begin *********************************** -->
<!-- 针对模型的模板 -->
<script id="todo-template" type="text/x-handlebars-template"><!-- 这里对todo模型数组进行迭代循环 -->
    {{#this}}
    <!-- 会看到,这里具有简单的if语句,即这里具备显示逻辑 --><li {{#if completed}}class="completed"{{/if}} data-id="{{id}}"><div class="view"><input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}><label>{{title}}</label><button class="destroy"></button></div><input class="edit" value="{{title}}"></li>
    {{/this}}
</script>
<!-- /针对模型的模板 -->
<!-- footer模板,记录还剩下多少没有完成等 -->
<script id="footer-template" type="text/x-handlebars-template"><span id="todo-count"><strong>{{activeTodoCount}}</strong> {{activeTodoWord}} left</span>
    {{#if completedTodos}}
        <button id="clear-completed">Clear completed ({{completedTodos}})</button>
    {{/if}}
</script>
<!-- /footer模板 -->
<!-- ************************************* template end *********************************** -->

<script src="js/base/base.js"></script>
<script src="js/lib/jquery.js"></script>
<script src="js/lib/handlebars.js"></script>

<!-- app begin -->
<script src="js/app.js"></script>

app.js

jQuery(function() {
    'use strict';
    
    // 这里是一些工具函数的抽取,包括// 1.ID生成器// 2.显示格式化// 3.localStorage存储var Utils = {
        uuid : function() {
            /*jshint bitwise:false */var i, random;
            var uuid = '';

            for ( i = 0; i < 32; i++) {
                random = Math.random() * 16 | 0;
                if (i === 8 || i === 12 || i === 16 || i === 20) {
                    uuid += '-';
                }
                uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16);
            }

            return uuid;
        },
        pluralize : function(count, word) {
            return count === 1 ? word : word + 's';
        },
        store : function(namespace, data) {
            if (arguments.length > 1) {
                return localStorage.setItem(namespace, JSON.stringify(data));
            } else {
                var store = localStorage.getItem(namespace);
                return (store && JSON.parse(store)) || [];
            }
        }
    };
    
    var Todo = function(id, title, completed) {
        this.id = id;
        this.title = title;
        this.completed = completed;
    }
    
    var App = {
        
        init: function() {
            this.ENTER_KEY = 13;
            this.todos = Utils.store('todos-jquery');
            this.cacheElements();
            this.bindEvents();
        },
        
        // 这里是缓存一些必要的dom节点,提高性能
        cacheElements: function() {
            this.todoTemplate = Handlebars.compile($('#todo-template').html());
            this.footerTemplate = Handlebars.compile($('#footer-template').html());
            this.$todoApp = $('#todoapp');
            this.$header = this.$todoApp.find('#header');
            this.$main = this.$todoApp.find('#main');
            this.$footer = this.$todoApp.find('#footer');
            this.$newTodo = this.$header.find('#new-todo');
            this.$toggleAll = this.$main.find('#toggle-all');
            this.$todoList = this.$main.find('#todo-list');
            this.$count = this.$footer.find('#todo-count');
            this.$clearBtn = this.$footer.find('#clear-completed');
        },
        
        // 模拟Controller实现:所有的事件监听在这里绑定
        bindEvents: function() {
            var list = this.$todoList;
            this.$newTodo.on('keyup', this.create);
            this.$toggleAll.on('change', this.toggleAll);
            this.$footer.on('click', '#clear-completed', this.destroyCompleted);
            list.on('change', '.toggle', this.toggle);
            list.on('dblclick', 'label', this.edit);
            list.on('keypress', '.edit', this.blurOnEnter);
            list.on('blur', '.edit', this.update);
            list.on('click', '.destroy', this.destroy);
        },
        
        // 渲染记录列表:当模型数据发生改变的时候,对应的事件处理程序调用该方法,从而实现对应DOM的重新渲染
        render: function() {
            this.$todoList.html(this.todoTemplate(this.todos));
            this.$main.toggle(!!this.todos.length);
            this.$toggleAll.prop('checked', !this.activeTodoCount());
            this.renderFooter();
            Utils.store('todos-jquery', this.todos);
        },
        
        // 渲染底部
        renderFooter: function () {
            var todoCount = this.todos.length;
            var activeTodoCount = this.activeTodoCount();
            var footer = {
                activeTodoCount: activeTodoCount,
                activeTodoWord: Utils.pluralize(activeTodoCount, 'item'),
                completedTodos: todoCount - activeTodoCount
            };

            this.$footer.toggle(!!todoCount);
            this.$footer.html(this.footerTemplate(footer));
        },
        
        // 创建记录
        create: function (e) {
            var $input = $(this);
            var val = $.trim($input.val());

            if (e.which !== App.ENTER_KEY || !val) {
                return;
            }
            
            App.todos.push({
                id: Utils.uuid(),
                title: val,
                completed: false
            });

            // 记录添加后,通知重新渲染页面
            App.render();
        },
        
        // 其他业务逻辑函数
        edit: function() {},
        destroy: function() {}
        /* ... */
        
    }
    
    App.init();

}); 

这样,我们使用jQuery实现了mvc架构的小应用程序,我再分析一下这个小demo的特点——

1.维护的model是todo实例的列表,这样,我们对增加记录、删改某一条记录,都要重新渲染整个列表,这样,导致性能的拙劣行。当然,改进的方式是对每一个实例进行对应dom的绑定。
2.这里的View中,我们看到其中参杂了一些显示逻辑,显然,我提倡这样去做,而非在js中去控制业务逻辑。然而,我们在实际开发的过程当中,我们必然涉及到复杂的显示逻辑,这样,我们可以向之前所说的那样,利用单独编写显示逻辑helper,这与MVC的设计思想并不违背,确保高维护性及扩展性。
3.这里有关模型todos的业务逻辑,并没有严格抽象出来,而是写入对应的事件当中。

本文转载自https://www.cnblogs.com/jinguangguo/p/3534422.html

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论