《BackboneJS框架的技巧及模式》(2)

简介: 《BackboneJS框架的技巧及模式》(2)本文紧接第一部分:《BackboneJS框架的技巧及模式(1)》作者:chszs,转载需注明。

《BackboneJS框架的技巧及模式》(2)

本文紧接第一部分:《BackboneJS框架的技巧及模式(1)》

作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs

二、为对象创建Façade外观模式

在实际项目中,需求是经常变化的,因此,终端返回的JSON数据格式也是如此。如果你的视图和下层的数据模型是紧耦合的,那么这是一种痛苦。有鉴于此,我为所有的对象都创建getter和setter函数。

此模式使用较广。如果任何底层的数据结构发生了变化,那么视图层无需随之更新;你会有一个数据访问点,所以你不太可能忘记做深度复制,编写的代码将会更易于维护和调试。此模式的缺点在于它可能会导致模型或集合有一点点膨胀。

下面我们看一个例子来阐明此模式。假想我们有一个Hotel模型,它包含了rooms和当前有效的rooms,而且我们希望可以通过床位大小来获取rooms。

var Hotel = Backbone.Model.extend({
    defaults: {
        "availableRooms": ["a"],
        "rooms": {
            "a": {
                "size": 1200,
                "bed": "queen"
            },
            "b": {
                "size": 900,
                "bed": "twin"
            },
            "c": {
                "size": 1100,
                "bed": "twin"
            }
        },

        getRooms: function() {
            $.extend(true, {}, this.get("rooms"));
        },

        getRoomsByBed: function(bed) {
            return _.where(this.getRooms(), { "bed": bed });
        }
    }
});

现在我们假设明天你要发布项目,但你发现终端开发者忘记告诉你rooms的数据结构发生了修改。你的代码现在看起来会像下面这样:

var Hotel = Backbone.Model.extend({
    defaults: {
        "availableRooms": ["a"],
        "rooms": [
            {
                "name": "a",
                "size": 1200,
                "bed": "queen"
            },
            {
                "name": "b",
                "size": 900,
                "bed": "twin"
            },
            {
                "name": "c",
                "size": 1100,
                "bed": "twin"
            }
        ],

        getRooms: function() {
            var rooms = $.extend(true, {}, this.get("rooms")),
             newRooms = {};

            // transform rooms from an array back into an object
            _.each(rooms, function(room) {
                newRooms[room.name] = {
                    "size": room.size,
                    "bed": room.bed
                }
            });
        },

        getRoomsByBed: function(bed) {
            return _.where(this.getRooms(), { "bed": bed });
        }
    }
});

我们仅修改了一个函数,以便将Hotel的结构转变为应用程序所期望的结构,以便整个应用程序仍然能像我们所预期的那样工作。如果这里没有getter函数,我们很可能不得不为rooms的每个访问点进行代码修改。理想情况下,你会修改所有函数,以适应新的数据结构,但如果你有项目发布的时间压力,此模式可以为你节省时间。

顺便说一句,此模式既可以被认为是Facade装饰模式,因为它隐藏了创建对象复制的复杂性,也可以认为是Bridge桥接模式,因为它可以用于将数据转换为所期望的格式。

最佳实践是对任何对象都使用getters 和setters 函数。

三、不通过服务器存储数据

尽管Backbone.js有模型和集合映射到RESTful端点的规则,有时候你可能会花大量时间查找你想要的存储在服务器端的数据或集合。

有一些关于Backbone.js的文章,描述了此模式。下面让我们一起来快速看一个小例子。假设你有一个ul元素列表。

<ul>
	<li><a href="#" data-id="1">One</a></li>
	<li><a href="#" data-id="2">Two</a></li>
    . . .
	<li><a href="#" data-id="n">n</a></li>
</ul>

列表有200项,当使用者点击列表中的某项时,选择的项变成被选中状态:

var Model = Backbone.Model.extend({
    defaults: {
        items: [
            {
                "name": "One",
                "id": 1           
            },
            {
                "name": "Two",
                "id": 2           
            },
            {
                "name": "Three",
                "id": 3           
            }
        ]
    }
});

var View = Backbone.View.extend({
    template: _.template($('#list-template').html()),

    events: {
        "#items li a": "setSelectedItem"
    },

    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
    },

    setSelectedItem: function(event) {
        var selectedItem = $(event.currentTarget);
        // Set all of the items to not have the selected class
        $('#items li a').removeClass('selected');
        selectedItem.addClass('selected');
        return false;
    }
});
<script id="list-template" type="template">
<ul id="items">
        <% for(i = items.length - 1; i >= 0; i--) { %>
	<li>
                <a href="#" data-id="<%= item[i].id %>"><%= item[i].name %></a></li>
<% } %></ul>
</script>

现在我们能很容易的判断被选中的项,并且我们没有必要通去遍历列表。而且,如果列表非常大,遍历会是一个巨大的开销。因此,当用户点击了列表项后,我们应该存储被选择了的项。

var View = Backbone.View.extend({
    initialize: function(options) {
        // Re-render when the model changes
        this.model.on('change:items', this.render, this);
    },

    template: _.template($('#list-template').html()),

    events: {
        "#items li a": "setSelectedItem"
    },

    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
    },

    setSelectedItem: function(event) {
        var selectedItem = $(event.currentTarget);
        // Set all of the items to not have the selected class
        $('#items li a').removeClass('selected');
        selectedItem.addClass('selected');
        // Store a reference to what item was selected
        this.selectedItemId = selectedItem.data('id'));
        return false;
    }
});

现在我们可以很容易的确定哪些项被选中了,并且我们无需遍历DOM模型。此模式对于存储外部数据来说非常有用,请记住,你可以创建不需有端点相关联的且存储外部视图数据的模型和集合。

此模式的缺点是如果你存储了外部数据到你的模型或集合,它们不能真正遵循RESTful架构,因为它们不能完美的映射Web资源;另外,此模式可能会引起对象的膨胀;如果端点是严格接受JSON格式,那么它可能会引起一些烦恼。

你或许会问自己,“我如何确定我是否应该把外部数据放进视图或者放进模型?”。如果你为呈现添加了额外的属性,例如容器的高度,那么我们把它添加到视图。如果此属性跟下层的数据模型有一定的关系,然后你想把它放进模型。总之一句话,根据实际的需求进行判断。






目录
相关文章
|
3月前
|
存储 安全 Java
深度长文解析SpringWebFlux响应式框架15个核心组件源码
以上是Spring WebFlux 框架核心组件的全部介绍了,希望可以帮助你全面深入的理解 WebFlux的原理,关注【威哥爱编程】,主页里可查看V哥每天更新的原创技术内容,让我们一起成长。
|
4月前
|
移动开发 JavaScript 前端开发
Phaser和Three.js是两个非常流行的JavaScript游戏框架,它们各自拥有独特的核心功能和使用场景
【6月更文挑战第16天】Phaser是开源的2D游戏引擎,适合HTML5游戏,提供物理引擎、图像渲染和资源管理,适用于2D游戏,如消消乐。Three.js是基于WebGL的3D库,用于创建复杂的3D场景和应用,涵盖从游戏到可视化领域的多种用途。两者分别在2D和3D开发中展现强大功能,选择取决于项目需求。
44 8
|
5月前
|
开发框架 JavaScript 前端开发
什么是渐进式框架?作用是什么?如何使用?
什么是渐进式框架?作用是什么?如何使用?
346 0
|
12月前
|
JavaScript 前端开发 C++
和chatgpt学架构03-引入UI框架(elment-plus)
和chatgpt学架构03-引入UI框架(elment-plus)
|
设计模式 JavaScript 前端开发
|
前端开发 JavaScript 开发者
封装库/工具库中重要概念之UI框架
UI(User Interface)框架是前端开发中十分重要的一部分,它提供了各种组件和样式,用于构建页面和用户界面。在前端开发中,封装库/工具库可以帮助我们更加高效地使用 UI 框架。
185 0
|
存储 缓存 前端开发
【JavaScript框架封装】自己动手封装一个涵盖JQuery基本功能的框架及核心源码分享(单文件版本)
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81156178 ...
1631 0
|
JavaScript 前端开发 数据格式
【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81055973 ...
1028 0
|
存储 关系型数据库 BI
下一篇
无影云桌面