在Backbone View中更新like按钮的状态

时间:2014-11-11 14:25:16

标签: ajax backbone.js model

在下面的代码中,我有一个从另一个视图扩展的视图(但不继承任何功能,只渲染模板)和我想要实现的模型。我的观点是一个类似按钮,我需要在每次加载页面时从服务器检索类似按钮的状态。我不知道如何使用该模型。我是否需要在模型中从服务器检索状态时进行Ajax调用,或者该调用是否属于视图?

这是我的代码:

var likeButton = Backbone.Model.extend ({

    initialize: function () {
        this.isLiked = /* need something here! Ajax call to get state of button from server? */
    }
});

var LikeButtonView = BaseButtonView.extend({ // extends form a previews view which simply extends from backbone and render's the template

    template: _.template($('#like-button').html()),
    sPaper: null,
    sPolyFill: null,
    sPolyEmpty: null,
    isLiked: false,

    events: {
        "click .icon": "like",
    },

    model: new likeButton (),

    initialize: function (options) {
        BaseButtonView.prototype.initialize.apply(this, [options]); // inherit from BaseButtonView
        this.likeButn = $("button.icon", this.$el);
        this.svgNode = this.likeButn.find("svg").get(0); // find the svg in the likeButn and get its first object
        this.sPaper = Snap(this.svgNode); // pass in the svg object into Snap.js
        this.sPolyFill = this.sPaper.select('.symbol-solid');
        this.sPolyEmpty = this.sPaper.select('.symbol-empty');

        if (this.model.isLiked) {
            this.likeButn.addClass("liked");
        } else if (!this.model.isLiked) {
            this.likeButn.addClass("unliked");
        }

    },

    like: function() {
        this._update();
    },

    _update: function () {
        if ( !this.isLiked ) { // if isLiked is false, remove class, add class and set isLiked to true, then animate svg to liked position
            this._like();
        } else if ( this.isLiked ) { // is isLiked is false, remove class, add class, set isLiked to false, then animate svg to unliked position
            this._unlike();
        }
    },

    _like: function() {
        this.likeButn.removeClass("unliked");
        this.likeButn.addClass("liked");
        this.isLiked = true;
        this.sPolyFill.animate({ transform: 't9,0' }, 300, mina.easeinout);
        this.sPolyEmpty.animate({ transform: 't-9,0' }, 300, mina.easeinout);
    },

    _unlike: function() {

        this.likeButn.removeClass("liked");
        this.likeButn.addClass("unliked");
        this.isLiked = false;
        this.sPolyFill.animate({ transform: 't0,0'}, 300, mina.easeinout);
        this.sPolyEmpty.animate({ transform: 't0,0' }, 300, mina.easeinout);
    }
});

1 个答案:

答案 0 :(得分:1)

有三种方法可以实现'喜欢'按钮对页面当前状态的了解:从HTML传递的隐藏字段,对服务器的Ajax调用,或者生成javascript服务器端,类似模型的状态已经激活。

让我们从基础开始。你的代码有点混乱。 模型包含应用程序的状态,视图只不过是一种显示状态的方式,在状态更改以更新节目时接收消息,以及向模型发送消息以更改状态。模型和视图通过Backbone.Events进行通信,视图和DOM通过jQuery.Events进行通信。你必须学会​​将这两者分开。

在这里,我已经转过你的"喜欢"模型化为实际模型,以便Backbone.Event中心可以看到您所做的更改。

var likeButton = Backbone.Model.extend ({
    defaults: {
        'liked': false
    }
});

现在在您的视图中,初始渲染将从模型中获取get的状态。当DOM事件(在'事件'对象中描述)发生时,您的工作就是将其转换为模型的状态更改,因此我的" toggleLike"只更改模型,而不是视图。但是,当模型发生变化时(显式地,当模型的"喜欢"字段发生变化时),视图将自动更新。

这是什么让Backbone如此酷。视图自动反映模型现实的方式。您只需要使模型正确,视图就可以工作。您可以协调视图在初始化代码中反映模型的方式,它可以很小并且很容易推断出您所关心的模型中的事件。

var LikeButtonView = BaseButtonView.extend({ 

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

    events: {
        "click .icon": "toggleLike",
    },

    initialize: function (options) {
        BaseButtonView.prototype.initialize.call(this, options); // inherit from BaseButtonView
        // A shortcut that does the same thing.
        this.likeButn = this.$("button.icon");
        this.model.on('change:liked', this._updateView, this);
    },

    render: function() {
        BaseButtonView.prototype.render.call(this);
        // Don't mess with the HTML until after it's rendered.
        this.likeButn.addClass(this.model.isLiked ? "liked", "unliked");
    },

    toggleLike: function() {
        this.model.set('liked', !this.model.get('liked'));
    },

    _updateView: function () {
        if (this.model.get('liked')) {
            this._showLikedState();
        } else {
            this._showUnlikedState();
        }
    }
});

如上所述,模型的初始化如何由您决定。您可以在模型的选项上设置一个URL,并在页面的启动代码中告诉它" fetch",在这种情况下,它会从某个REST端点获取状态在你的服务器上。或者您可以将其设置为默认值' false'。或者您可以在隐藏的HTML(隐藏的div或其他东西)中设置它,然后使用您的页面启动代码来找到它:

new LikeButtonView({model: new LikeButton({}, {url: "/where/page/state/is"}));

new LikeButtonView({model: new LikeButton({liked: $('#hiddendiv').data('liked')}, {}));

如果您要保存喜欢的状态,我建议您使用该网址。然后你就有了保存数据的地方。