0

私は現在、backbone.js の速度を上げようとしています。これを行う最善の方法は、オンライン チュートリアルとドキュメントに取り掛かることだと考えました。オンライン チュートリアルとサンプル アプリケーションは優れていますが、知識を基に構築するために、独自のサンプル Web サイト CRUD アプリケーションを構築しようとしています。サンプルの場合、基本的に私がやろうとしているのは、現在の 2 つのオンライン サンプル/チュートリアルをマージすることです。複数のモデル、コレクション、およびビューの操作について理解を深めることを目的としています。

残念ながら行き詰まってしまいました...長々とした説明で申し訳ありませんが、初心者として、問題を可能な限り説明しようとしています...

次のチュートリアルに基づいて、Web サイト アプリケーションのサンプルを作成しました。

https://github.com/ccoenraets/backbone-cellar/tree/master/bootstrap

オンラインの例を見る:

http://coenraets.org/backbone-cellar/bootstrap/

私はこのチュートリアルに従うことができ、サイトの作業バージョンを手に入れることができました. ここで、アプリケーション (backbone.js) 構造に収まるより多くのページを含むようにアプリケーションを拡張したいと考えています。チュートリアルを表示すると、静的な html テンプレートをアプリケーションにロードするだけの「about」ページがあることがわかります。私がやりたいことは、連絡先マネージャーを表示する新しいページを追加することです。連絡先マネージャーは、次のチュートリアルから奪われています。

http://net.tutsplus.com/tutorials/javascript-ajax/build-a-contacts-manager-using-backbone-js-part-1/

注: この時点では、わかりやすくするために、チュートリアルのパート 1 のみを使用しています。

問題が発生している場所を説明します...まず、私が行ったことの概要を説明します。アプリケーションで、Directory と呼ばれる headerView に新しいリンクを追加しました。main.js ページ (元の例: https://github.com/ccoenraets/backbone-cellar/blob/master/bootstrap/js/main.js ) で、次のようにコードを追加しました。

var AppRouter = Backbone.Router.extend({

routes: {
    ""                  : "list",
    "wines/page/:page"  : "list",
    "wines/add"         : "addWine",
    "wines/:id"         : "wineDetails",
    "about"             : "about",
    "directory"         : "directory"
},

initialize: function () {
    this.headerView = new HeaderView();
    $('.header').html(this.headerView.el);
},

list: function(page) {
    var p = page ? parseInt(page, 10) : 1;
    var wineList = new WineCollection();
    wineList.fetch({success: function(){
        $("#content").html(new WineListView({model: wineList, page: p}).el);
    }});
    this.headerView.selectMenuItem('home-menu');
},

wineDetails: function (id) {
    var wine = new Wine({id: id});
    wine.fetch({success: function(){
        $("#content").html(new WineView({model: wine}).el);
    }});
    this.headerView.selectMenuItem();
},

addWine: function() {
    var wine = new Wine();
    $('#content').html(new WineView({model: wine}).el);
    this.headerView.selectMenuItem('add-menu');
},

about: function () {
    if (!this.aboutView) {
        this.aboutView = new AboutView();
    }
    $('#content').html(this.aboutView.el);
    this.headerView.selectMenuItem('about-menu');
},

directory: function () {
    if (!this.directoryView) {
        this.directorytView = new DirectoryView();
    }
    $('#content').html(this.directoryView.el);
    this.headerView.selectMenuItem('directory-menu');
}

});

utils.loadTemplate(['HeaderView', 'WineView', 'WineListItemView', 'AboutView', 'DirectoryView'], function() { app = new AppRouter(); Backbone.history.start(); });

ディレクトリ (連絡先マネージャー) ページについては、説明のために、チュートリアルに従ってモデル ビューとコレクションを単一の .js ファイルに残しました。もちろん、ファイルを (モデルとビューに) 分離することを検討します。 )一度私はそれを動作させます。チュートリアルによると、連絡先マネージャー (ディレクトリ) のコードは次のとおりです。

//demo data
window.contacts = [
    { name: "Contact 1", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
    { name: "Contact 2", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
    { name: "Contact 3", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "friend" },
    { name: "Contact 4", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "colleague" },
    { name: "Contact 5", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" },
    { name: "Contact 6", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "colleague" },
    { name: "Contact 7", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "friend" },
    { name: "Contact 8", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail@me.com", type: "family" }
];

//define product model
window.Contact = Backbone.Model.extend({
    defaults: {
        photo: "/img/placeholder.png"
    }
});

//define directory collection
window.Directory = Backbone.Collection.extend({
    model: Contact
});

//define individual contact view
window.ContactView = Backbone.View.extend({
    tagName: "article",
    className: "contact-container",
    template: $("#contactTemplate").html(),

    render: function () {
        var tmpl = _.template(this.template);

        $(this.el).html(tmpl(this.model.toJSON()));
        //alert('this model: ' + this.model.toJSON().name);

        return this;
    }
});

//define master view
window.DirectoryView = Backbone.View.extend({
    el: $("#contacts"),

    initialize: function () {
        this.collection = new Directory(contacts);
        this.render();
    },

    render: function () {
        var that = this;
        _.each(this.collection.models, function (item) {
            that.renderContact(item);
        }, this);
    },

    renderContact: function (item) {
        var contactView = new ContactView({
            model: item
        });         

        this.$el.append(contactView.render().el);
    }
});

私が行った変更は、「var」を削除して「window」に置き換えるだけです。アプリの既存の構造に適合します。例えば:

var DirectoryView = Backbone.View.extend({

になります:

window.DirectoryView = Backbone.View.extend({

今私が抱えている問題に。テンプレートを表示する html コードを出力 (レンダリング) するコードを取得できます。

問題は

//define individual contact view
window.ContactView = Backbone.View.extend({
    tagName: "article",
    className: "contact-container",
    template: $("#contactTemplate").html(),

    render: function () {
        var tmpl = _.template(this.template);

    $(this.el).html(tmpl(this.model.toJSON()));
    alert('this model: ' + this.model.toJSON().name);

    return this;
    }
});

「アラート」が名前を正しく出力しているため、データが正しく解析されていることがわかりました。私が抱えている問題は、次のコード行です。

var tmpl = _.template(this.template);

次のエラーがスローされます:「Uncaught TypeError: null のメソッド 'replace' を呼び出せません」。

問題を解決する方法がわかりません:(

DirectoryView.html テンプレート コードは次のとおりです。

<div class="row">
<div class="span12">
    <div id="contact"></div>
    <script id="contactTemplate" type="text/template">
        <img src="<%= photo %>" alt="<%= name %>" />
        <h1><%= name %><span><%= type %></span></h1>
        <div><%= address %></div>
        <dl>
            <dt>Tel:</dt><dd><%= tel %></dd>
            <dt>Email:</dt><dd><a href="mailto:<%= email %>"><%= email %></a></dd>
        </dl>
    </script>
</div>

十分な情報を提供できたことを願っています。さらに必要な情報がある場合はお知らせください。

ご覧いただきありがとうございます:)

ジェイク

4

1 に答える 1

0

nullのメソッド'replace'を呼び出すことはできません

これは、メソッド内でnullであるもの、おそらく文字列_.templateを呼び出そうとしていることを意味します。replaceundescoreメソッドは次のようになります(注釈付きソースから)

_.template = function(text, data, settings) {
  settings = _.defaults({}, settings, _.templateSettings);

  var matcher = new RegExp([
    (settings.escape || noMatch).source,
    (settings.interpolate || noMatch).source,
    (settings.evaluate || noMatch).source
  ].join('|') + '|$', 'g');

  // This is the only place where replace is used
  var index = 0;
  var source = "__p+='";
  // Replace used on variable text
  text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
    // replace used on source that can't be null
    source += text.slice(index, offset)
      .replace(escaper, function(match) { return '\\' + escapes[match]; });
    source +=
      escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
      interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
      evaluate ? "';\n" + evaluate + "\n__p+='" : '';
    index = offset + match.length;
  });
  source += "';\n";

したがって、変数textはnullである必要があります。コードtextではがthis.templateであるため、初期化時にnullである必要があります。

View作成するために拡張するときにContactView#contactTemplate要素がDOMにロードされることを確認しますか?問題はそこにあるに違いありません。コンソールロギングthis.templateを試して、それが本当にnullであるかどうかを確認してください。javascriptを実行する前にDOMがロードされていることを確認する場合は、それらをjQueryready関数でラップします。

于 2012-11-15T20:20:24.573 に答える