javascript - 在 Backbonejs 中更新集合和 View

标签 javascript backbone.js

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

我正在重置集合并在用户搜索时为其提供一个新的 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());;

})();

最佳答案

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

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

因为您已经在这里处理了 reddit url。不要害怕在 Backbone 扩展对象( View 、模型、集合等)中为自己创建一些实用函数和 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;
    }
});

不要害怕有很多 View ,应该使用 Backbone View 来包装小的组件逻辑。

所以这是项目:

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

});

而列表只是我们 Root View 的一个子组件( subview )。

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 的目的,该目的部分是应用 MVC 概念在 jQuery 之上。

贴出的代码的一些注释

花点时间了解发生了什么。您的问题中有几行代码没有执行任何操作,或者根本不起作用。


虽然它已在您的答案中删除,但以下内容没有意义,因为集合构造函数是 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 var 是在“app”级别定义的,不需要它。

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

主干集合会在成功时自动填充模型的新实例。您不需要在成功回调中重新解析它(除了与 redditData 的歧义之外)。

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

我并不是有意无礼,我花时间写下这么长的答案是为了帮助您和任何 future 的读者。

关于javascript - 在 Backbonejs 中更新集合和 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40219846/

相关文章:

javascript - Backbone 延伸断裂

javascript - 如何避免在 Marionette 中生成空文本节点?

c# - 将流直接返回到 Web 浏览器

javascript - 如何通过单击页面上的任意位置来关闭下拉菜单?

javascript - 使 HTML 输入的第一个字符不可编辑 - javascript

javascript - Backbone.js 内联模板在 Opera 中不起作用

javascript - d3 条形图上的 y 刻度

javascript - 访问多维数组中的项目

backbone.js - JavaScript - Backbone.js 应用程序中的交互式图表

javascript - this.model 不是函数