在Backbonejs中更新集合和视图

时间:2016-10-24 13:34:28

标签: javascript backbone.js

我创建了一个搜索栏,但是当从用户收集数据时,它会再次显示默认数据,而不是用户新的搜索条件。

我在用户搜索时重置了该集合并为其提供了新的网址,但它似乎无法正确更新,而且我无法确定我的问题所在是

(function(){
    'use strict';
    var red = red || {};

    //model////////////////////////////////////////////////

    red.RedditModel = Backbone.Model.extend({
        defaults: {
            urlTarget: $('#textBox').val(),
            urlStart: 'https://www.reddit.com/r/',
            urlEnd: '.json'
        },

        initialize: function() {

            this.on('change:urlTarget', function() {
                console.log('The Url Target has changed to ' + this.get("urlTarget"));
            });

            this.on('change:concatURL', function() {
                console.log('The model Url has changed to ' + this.get("concatURL"));
            });

            this.on('change:url', function() {
                console.log('The collection url has changed to: ' + this.get('url'));
            });

        }
    });
    var redditModel = new red.RedditModel();

    var fullURL = new red.RedditModel({

        concatURL: redditModel.attributes.urlStart + redditModel.attributes.urlTarget + redditModel.attributes.urlEnd
    });

    var listElmement,
        $list = $('.list');

    //collections//////////////////////////////////////////
    red.redditCollection = Backbone.Collection.extend({
        model: red.RedditModel,
        url: fullURL.attributes.concatURL,
        parse: function(response) {
            var redditData = response.data.children;
            return redditData;
        }
    });

    //view////////////////////////////////////

    red.RedditView = Backbone.View.extend({
        model: fullURL,
        collection: redditCollection,
        el: '.searchBar',
        events: {

            'click .searchButton': function(e) {
                this.updateModel(e);
                this.updateCollection(e);
            },
            'change #textBox': 'initialize'
        },

        updateModel: function() {
            this.$urlTarget = $('#textBox').val()
            this.model.set('urlTarget', this.$urlTarget);
            this.model.set('concatURL', redditModel.attributes.urlStart + this.$urlTarget + redditModel.attributes.urlEnd);
        },

        updateCollection: function() {
            this.collection.reset();
            this.$urlTarget = $('#textBox').val();
            var newUrl = redditModel.attributes.urlStart + this.$urlTarget + redditModel.attributes.urlEnd;
            this.collection.add({ urlTarget: this.$urlTarget });
            this.collection.add({ url: newUrl });
            console.log(newUrl);
        },

        tagName: 'li',
        className: 'listItems',

        initialize: function() {
            $list.html('');
            this.collection.fetch({
                success: function(redditData) {
                    redditData.each(function(redditData) {
                        redditData = redditData.attributes.data.title

                        listElmement = $('<li></li>').text(redditData);
                        $list.append(listElmement);

                    })
                }
            });
        },
        render: function() {

        }
    });

    var redditCollection = new red.redditCollection({
        redditModel,
        fullURL
    });

    var myRedditView = new red.RedditView({
        model: redditModel,
        collection: redditCollection
    });


    $('.page').html(myRedditView.render());;

})();

1 个答案:

答案 0 :(得分:2)

解析模型,并将其用于预期目的。无需在模型中存储reddit url和其他搜索相关信息。

red.RedditModel = Backbone.Model.extend({
    parse: function(data) {
        return data.data;
    },
})

因为你已经在这里处理了reddit网址。不要害怕在Backbone扩展对象(视图,模型,集合等)中为自己制作一些实用函数和getter / setter。

red.RedditCollection = Backbone.Collection.extend({
    url: function() {
        return 'https://www.reddit.com/r/' + this.target + this.extension;
    },

    initialize: function(models, options) {
        this.extension = '.json'; // default extension
    },

    setExtension: function(ext) {
        this.extension = ext;
    },
    setTarget: function(target) {
        this.target = target;
    },

    parse: function(response) {
        return response.data.children;
    }
});

不要害怕拥有很多观点,应该使用Backbone视图来包装小组件逻辑。

所以这是项目:

red.RedditItem = Backbone.View.extend({
    tagName: 'li',
    className: 'listItems',
    render: function() {
        this.$el.text(this.model.get('title'));
        return this;
    }
});

列表使用的是:

red.RedditList = Backbone.View.extend({
    tagName: 'ul',
    initialize: function() {
        this.listenTo(this.collection, 'sync', this.render);
    },
    render: function() {
        this.$el.empty();
        this.collection.each(this.renderItem, this);
        return this;
    },
    renderItem: function(model) {
        var view = new red.RedditItem({ model: model });
        this.$el.append(view.render().el);
    }

});

该列表只是我们根视图的子组件(子视图)。

red.RedditView = Backbone.View.extend({
    el: '.searchBar',
    events: {
        'click .searchButton': 'onSearchClick',
    },

    initialize: function() {
        // cache the jQuery element for the textbox
        this.$target = $('#textBox');

        this.collection = new red.RedditCollection();

        this.list = new red.RedditList({
            collection: this.collection,
            // assuming '.list' is within '.searchBar', and it should
            el: this.$('.list'),
        });
    },
    render: function() {
        this.list.render();
        return this;
    },

    onSearchClick: function(e) {
        this.collection.setTarget(this.$target.val());
        console.log(this.collection.url());
        this.collection.fetch({ reset: true });
    },

});

然后,您只需要以下内容即可使用它:

var myRedditView = new red.RedditView();
myRedditView.render();

注意几乎不存在全局jQuery选择器的使用。如果您正在使用Backbone以及您使用$('#my-element')的任何地方,那么您将击败 Backbone的目的,这部分是在jQuery之上应用MVC概念。

关于发布的代码的一些注释

花点时间了解发生了什么。你的问题中有几行代码没有做任何事情,或者根本就没有工作。

虽然在您的回答中已将其删除,但以下内容没有意义,因为集合构造函数为Backbone.Collection([models], [options]),此处您所拥有的内容转换为传递options对象(使用ES6 shorthand property names { a, b, c})到models参数。

var redditCollection = new red.redditCollection({
    redditModel,
    fullURL
});

此行没有任何作用,因为.render()没有做任何事情并且没有返回任何内容。

$('.page').html(myRedditView.render());

在这里,您可以使用jQuery手动创建新元素,而Backbone会为您执行此操作。

$('<li></li>').text(redditData);

请勿直接使用attributes,除非您有充分理由不使用.get('attributeKey'),否则请始终使用redditModel.attributes.urlStart

listElement

尽可能支持局部变量。这里的listElmement = $('<li></li>').text(redditData); $list.append(listElmement); var是在&#34; app&#34;中定义的。水平而不需要它。

redditData

成功时,Backbone集合会自动填充新的模型实例。您无需在成功回调中重新解析该问题(除了this.collection.fetch({ success: function(redditData) { redditData.each(function(redditData) { redditData = redditData.attributes.data.title; 的歧义之外)。

mathDiagram :: Diagram B
mathDiagram = stroke $ textSVG "`2 + \sqrt{\pi}`:math:" 1

我不是故意粗鲁,我花了很多时间写下这么长的答案,试图帮助你,以及任何未来的读者。