简体   繁体   English

在Backbonejs中更新集合和视图

[英]Updating collection and view in Backbonejs

I've created a search bar, but when the data is gathered from the user, it displays the default data over again rather then the users new search criteria. 我创建了一个搜索栏,但是当从用户收集数据时,它会再次显示默认数据,而不是用户新的搜索条件。

I'm resetting the collection and giving it a new URL when the user searches, but it doesn't seem to update correctly, and I'm having trouble figuring out where my problem(s) are. 我正在重置集合并在用户搜索时给它一个新的URL,但它似乎没有正确更新,而且我无法弄清楚我的问题在哪里。

(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());;

})();

Parse within the model, and use it for its intended purpose. 在模型中解析,并将其用于其预期目的。 No need to store the reddit url and other search related info in a model. 无需在模型中存储reddit url和其他搜索相关信息。

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

Since you already take care of the reddit url here. 既然您已经在这里处理了reddit网址。 Don't be afraid to make yourself some utility functions and getters/setters in your Backbone extended objects (views, model, collection, etc). 不要害怕在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;
    }
});

Don't be afraid to have a lot of views, Backbone views should be used to wrap small component logic. 不要害怕拥有很多视图,应该使用Backbone视图来包装小组件逻辑。

So here's the item: 所以这是项目:

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

Which is used by the list: 列表使用哪个:

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);
    }

});

And the list is just a sub-component (sub-view) of our root view. 列表只是我们根视图的子组件(子视图)。

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 });
    },

});

Then, you only need the following to use it: 然后,您只需要以下内容即可使用它:

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

Notice the almost non-existent use of the global jQuery selector. 注意几乎不存在全局jQuery选择器的使用。 If you're using Backbone and everywhere you're using $('#my-element') , you're defeating the purpose of Backbone which is, in part, to apply MVC concepts on top of jQuery. 如果您正在使用Backbone并且在任何地方使用$('#my-element') ,那么您将破坏Backbone的目的,这部分是在jQuery之上应用MVC概念。

Some notes on the code posted 关于代码的一些注释发布

Take time to understand what's going on. 花点时间了解发生了什么。 There are several lines of code in your question that doesn't do anything, or just don't work at all. 你的问题中有几行代码没有做任何事情,或者只是根本不工作。


Though it's been removed in your answer, the following doesn't make sense because the collection constructor is Backbone.Collection([models], [options]) and what you have here translates to passing an options object (using ES6 shorthand property names { a, b, c} ) to the models parameter. 虽然它已在你的答案中被删除,但以下没有意义,因为集合构造函数是Backbone.Collection([models], [options]) ,你在这里转换为传递一个options对象(使用ES6速记属性名 { a, b, c} )到models参数。

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

This line does nothing, because .render() doesn't do anything and doesn't return anything. 这行没有任何作用,因为.render()不做任何事情而且不返回任何内容。

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

Here, you're creating a new element manually using jQuery while you have Backbone which does this for you. 在这里,你使用jQuery手动创建一个新元素,而你有Backbone为你做这个。

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

Don't use the attributes directly, always use .get('attributeKey') unless you have a good reason not to. 不要直接使用attributes ,总是使用.get('attributeKey')除非你有充分的理由不这样做。

redditModel.attributes.urlStart

Favor local variables whenever you can. 尽可能支持局部变量。 The listElement var here is defined at the "app" level without a need for it. 这里的listElement var在“app”级别定义,而不需要它。

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

A Backbone collection is automatically filled with the new instances of models on success. Backbone集合会在成功时自动填充新的模型实例。 You do not need to re-parse that in the success callback (in addition to the ambiguity with redditData ). 您不需要在成功回调中重新解析它(除了redditData的歧义)。

this.collection.fetch({
    success: function(redditData) {
        redditData.each(function(redditData) {
            redditData = redditData.attributes.data.title;

I don't mean to be rude and I took the time to write that long answer to try to help, you, and any future reader that comes by. 我并不是故意粗鲁,而是花时间写出那么长的答案来试图帮助你,以及任何未来的读者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM