Ошибка дочернего просмотра в приложении Marionette

#backbone.js #marionette

#backbone.js #марионетка

Вопрос:

Я новичок в backbone и marionette и узнал об этом из книги Getting Started with Backbone Marionette издательства Packpub.
Я получаю ошибку как Uncaught NoChildViewError: A "childView" must be specified , и мой код

 <!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Marionette test app</title>
  <link  rel="stylesheet" media="screen" href="{{ url_for('static', filename='bootstrap.css') }}">
   <style type="text/css">
        .container {
            margin-top: 10px;
        }
         body {
            padding-top: 60px;
            padding-bottom: 40px;
         }

   </style>
</head>
<body>

<div id="container" class="well">
    <h2>Marionette Views- CollectionView</h2>
</div>

 <script id="categoryTemplate" type="text/template">
    <a href="#<%= name%>" ><%= name%> (<%= booksOnCategory %>)</a>
        <button class="info">Details</button>
</script>


<script src="{{ url_for('static', filename='jquery.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap.js') }}"></script>
<script src="{{ url_for('static', filename='underscore.js') }}"></script>
<script src="{{ url_for('static', filename='backbone.js') }}"></script>
<script src="{{ url_for('static', filename='backbone.marionette.js') }}"></script>


<script type="application/javascript">
    // lets create new application as below;
    var BookStoreApp = new Backbone.Marionette.Application();


    var BookStoreController = Backbone.Marionette.Controller.extend({
        displayBooks : function(){
            console.log("I will display books");
        }
    });

    var BookStoreRouter = Backbone.Marionette.AppRouter.extend({
        controller : BookStoreController,
        appRoutes : {
            "":"displayBooks"
        }
    });

    BookStoreApp.addInitializer(function(){
        var controller = new BookStoreController();
        var router = new BookStoreRouter({controller: controller});
        console.log("Hello from addInit");
    });

    BookStoreApp.on("initialize:after", function(){
        if (Backbone.history){
            Backbone.history.start();
            console.log("hello from initialize:after.. .");
        }

    });


    BookModel = Backbone.Model.extend({
        defaults : {
            name : "",
            booksOnCategory:0
        }
    });

    BookCollection = Backbone.Collection.extend({
        model : BookModel
    });

    var bookModel = new BookModel({name:"Math", booksOnCategory:3});
    var bookModel2 = new BookModel({name:"Art", booksOnCategory:5});
    var bookModel3 = new BookModel({name:"Science", booksOnCategory:6});
    var bookModel4 = new BookModel({name:"Biology", booksOnCategory:1});
    var bookCollection = new BookCollection([bookModel, bookModel2, bookModel3, bookModel4]);

    var BookView = Backbone.Marionette.ItemView.extend({
        template : '#book-template',
        tagName: 'li',
        events:{
            "mouseenter .info": "showDetails",
            "mouseleave .info": "hideDetails"
        },
        showDetails: function(){
            this.$(".info").popover({
                title: this.model.get('name'),
                content: "we have "  this.model.get("booksOnCategory")   " left"
            });
            this.$(".info").popover("show");
        },
        hideDetails: function(){
            this.$(".info").popover("hide");
        }
    });

    CategoriesVieww = Backbone.Marionette.CollectionView.extend({
        tagName: 'ul',
        className: "unstyled",
        itemView: BookView
    });

    var CategoriesView = new CategoriesVieww({
        collection: bookCollection,
        el: "#container" });

    CategoriesView.render();

    BookStoreApp.start();

</script>

</body>
</html>
  

примечание: я тестирую это приложение в приложении flask-jinja2; поэтому игнорируйте url_for тег in script; поскольку они требуются для jinja2

Ответ №1:

Похоже, проблема именно в том, о чем говорится в сообщении об ошибке 😉 CollectionView создается как последовательность дочерних представлений, и вам нужно указать представлению коллекции, какой тип представления вы хотите использовать для этих дочерних представлений.

Но это не так. Возможно, просто опечатка? Попробуйте изменить свой CategoriesVieww на

 CategoriesVieww = Backbone.Marionette.CollectionView.extend({
    tagName: 'ul',
    className: "unstyled",
    childView: BookView    // <-- here
});
  

Комментарии:

1. @namit marionette не так давно обновился до версии 2.0, я помню, как читал, что одной из вещей, которые они изменили, было переименование ItemView в childView. Это произошло совсем недавно, многие справочники, вероятно, еще не успели обновиться. полный журнал изменений можно найти здесь, поскольку было несколько изменений имени, которые могли бы вас зацепить при использовании ресурса для предыдущей версии docs.google.com/document/d /…

2. Однако был бы осторожен. Я попробовал следующий учебник с новой версией библиотеки: davidsulc.com/blog/2013/02/03/… Это отлично работало с предыдущей версией, но теперь поведение, похоже, изменилось, и оно работает не так, как ожидалось.

Ответ №2:

Если вы используете CollectionView ИЛИ CompositeView из Marionette 2.2.0 или выше, имейте в виду, что ключевые слова API изменились следующим образом:

ItemView теперь называется childView itemViewContainer теперь называется childViewContainer

ДО версии 2.2.0

 CategoriesView = Backbone.Marionette.CompositeView.extend({
    template: '#template',
    className: "unstyled",
    itemView: BookView    // <-- here
    itemViewContainer: "#books-list"
});
  

Мне потребовалось некоторое время, чтобы разобраться с этим с помощью Firebug debugger. Вы можете обратиться к https://docs.google.com/document/d/1fuXb9N5LwmdPn-teMwAo3c8JTx6ifUowbqFY1NNSdp8/edit # для изменений API. Не все изменения задокументированы везде, где я могу найти.

ПОСЛЕ версии 2.2.0 :

 CategoriesView = Backbone.Marionette.CompositeView.extend({
    template: '#template',
    className: "unstyled",
    childView: BookView    // <-- here
    childViewContainer: "#books-list"
});