javascript - 以正确的方式使用 Backbone 集合将它们传递到 subview 中,然后再传递到模板引擎中

标签 javascript design-patterns backbone.js template-engine

我正在尝试了解如何使用 Backbone collections 并将它们拉入由 创建的相关 template engine subview .

这是我在我的应用中尝试过的逻辑:

enter image description here

我的 ajax 请求 返回这个对象:

{
    "products":[
        {
            "id":"43",
            "text":"Sunset Chips",
            "image":"43.png"
        },{
            "id":"107",
            "text":"Pringles Hot & Spicy",
            "image":"107.png"
        }
    ],
    "brands":[
        {
            "id":"132",
            "text":"P&G",
            "image":"132.png"
        },{
            "id":"27",
            "text":"Kinder",
            "image":"27.png"
        }
    ]
}

我使用 jQuery$.ajax 方法获取它,并在我的 View 中为我的 Backbone 应用管理它:

<script type="text/javascript">

var search = {};

search.app = {};
search.app.id = "#search-results";

search.product = {};
search.product.defaults = {
    id:0,
    text:"<?php echo __('No results here');?>",
    image:"<?php echo $this->webroot;?>files/product/default.png",
};

$(function(){

    var SearchApp = new Search.Views.App({
        id:"#search-results"
    });

    var ProductList = new Search.Collections.Products();
    var subView;

    function parseResults (response, search) {

        for (var i = response.products.length - 1; i >= 0; i--) {
            ProductList.add([new Search.Models.Product(response.products[i])]);
        };

        subView = new Search.Views.Product ({
            collection:ProductList,
            id:"#product-results",
            template:"#results-product-template" // solo in this.options.template
        });

        updateResults();
    }

    function updateResults () {
        console.log('updateResults: Ritorno il risultato quando hunter riceve una risposta dal server');
        if ($('#search-results').length == 0) {
            $('div.main > section:first-child').before('<section id="search-results"></section>');
        }
        SearchApp.renderProductCollection(subView);
    }

    $('#search-results .close').on('click', function () {
        $('#search-results').animate({height:0}, 500, function () {
            $(this).remove();   
        })
    });

    var callbacks = {
        on_response:parseResults // function presente in backbone.search.js
    };

    $('#hunter').hunter({url:'<?php echo $this->request->base; ?>/searches/default_search', callback:callbacks, ajax_params:{limit:10, term:'%%'}});

});
</script>

这是我的主干应用程序:

var Search = {
    Models: {},
    Collections: {},
    Views: {},
    Templates:{}
}

Search.Models.Product = Backbone.Model.extend({
    defaults: search.product.defaults || {},
    initialize:function () {
        console.log("initialize Search.Models.Product");
        this.on("change", function (){
            console.log("chiamato evento change del Model Search.Models.Product");
        });
        this.on("change:text", function () {
            console.log("chiamato evento change:text del Model Search.Models.Product");
        });
    }
});

Search.Collections.Products = Backbone.Collection.extend({
    model: Search.Models.Product,
    initialize:function () {
        console.log("initialize Search.Collections.Products");
        console.log(this);
        console.log(this.length);
        console.log(this.models);
    }
});

Search.Views.App = Backbone.View.extend({
    initialize:function () {
        console.log("initialize Search.Views.App");
        this.$prd = this.$('#product-results');
    },
    render:function () {

        console.log("render Search.Views.App");
    },
    renderProductCollection:function (subView) {
        console.log("Search.Views.App > renderProductCollection");
        console.log('subView.getTemplate() => ' + subView.getTemplate());
        $(this.id).html(subView.getTemplate());
    }
});

Search.Views.Product = Backbone.View.extend({
    initialize:function () {
        console.log("initialize Search.Views.Product");
    },
    getTemplate:function (data) {
        if (data == null || data == undefined) {
            data = this.collection.toJSON() || this.model.toJSON(); 
        }
        var template = Handlebars.compile($(this.options.template).html());
        console.log(data);
        return '<ul id="product-results" class="w-1-4">' + template(data) + '</ul>';
    },
    render:function () {
        console.log("render Search.Views.Product");
        return this;
    }
});

Handlesbar 模板就是这样:

<ul class="w-1-4">
    <li>
        <b>Products</b>
    </li>
   {{#each products}}
    <li>
        <a href="{{url}}">
            <div class="origin {{type}}" title="{{name}}"><img src="'.$this->webroot.'img/icons/16/origin/{{icon}}"></div>
        </a>
        <div>
            <a href="{{url}}" class="font-default-bold {{model}}-btn">{{name}}</a>
            {{#support}}<a href="{{support.url}}" class="font-small">{{support.name}}</a>{{/support}}
        </div>
    </li>
    {{/each}}
</ul>

我的问题是当我尝试解析 Handlesbar 模板中的数据时,因为我已经解析了 sub view collection 中的数据,所以我有一个 数组 结构如下:

[
    {
        "id":"43",
        "text":"Sunset Chips",
        "image":"43.png"
    },{
        "id":"107",
        "text":"Pringles Hot & Spicy",
        "image":"107.png"
    }
]

有了这些数据,由于 View 中的 parseResults,我不再有 products 对象,我将 ajax 放在集合中。

如何在没有 products prop 名称的情况下解析 products 数组,或者如何以正确的方式保存数据?

我知道在我的应用程序中我可以做这样的事情来解决问题:

var container = new array();
container['products'] = this.collection.toJSON();
data = container;

var template = Handlebars.compile($(this.options.template).html());
return '<ul id="product-results" class="w-1-4">' + template(data) + '</ul>';

但这是正确的方法还是我遗漏了什么?

最佳答案

如果您使用的是 Backbone,则无需使用 $.ajax。

使用collection.fetch http://backbonejs.org/#Collection-fetch

看起来服务器也没有给你所需的答案,所以 Backbone 有自己的解析: http://backbonejs.org/#Collection-parse

我也是无逻辑模板的粉丝。因此通过集合的迭代必须在 View 中而不是在模板中。也请检查这个(特别是第二点): http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html

以正确的方式使用集合,然后渲染它,在 View 中你可以监听添加或重置事件并以这种方式填充集合。 this.collection.on('add', this.render);//按模型获取模型 this.collection.on('reset', this.render);//获取所有模型(需要在fetch调用中指定一个参数{reset : true}

关于javascript - 以正确的方式使用 Backbone 集合将它们传递到 subview 中,然后再传递到模板引擎中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16045549/

相关文章:

javascript - 如何在早午餐中使用 jquery

javascript - 从 ViewBag 加载文件?

javascript - 如何使用bind()代替live()?

java - 工厂方法,为什么我们使用静态调用从工厂获取对象

java - 遍历列表并汇总类型相同的所有金额

backbone.js - 按属性值过滤 Backbone 集合

javascript - 我们可以缩短 Material-ui 组件的导入时间吗?

javascript - 多个单选按钮组相互干扰

php - 在 PHP 中实例化类或使用静态方法

javascript - 如何在每个 Marionette View 渲染上记录消息?