Backbone: Apa cara terbaik untuk memodelkan Koleksi di dalam Model?

Dibuat pada 4 Nov 2010  ·  11Komentar  ·  Sumber: jashkenas/backbone

Tim saya, bekerja dengan skema data yang menarik. Pada dasarnya yang kita miliki adalah sebuah dokumen yang memiliki nama dan versi dan sebuah array dari item-item yang ada di dalamnya. Item itu sendiri tidak memiliki id yang terkait dengannya karena termasuk dalam model yang lebih besar tetapi item dapat ditambahkan/diedit/dihapus dari dokumen utama. Modelnya terlihat seperti ini:
{
nama : "Ujian",
versi 1,
item: [
{nama: "Barang 1",
posisi : 0},
{nama: "Barang 2",
posisi : 1}]
}

Akan sangat bagus untuk menggunakan Koleksi untuk item yang mendasari dalam Model tetapi setiap kali Koleksi diperbarui, Model harus memposting kembali ke server dengan urlnya. Apa cara terbaik untuk memodelkan ini di Backbone? Saya akan dengan senang hati memposting lebih banyak dalam Intisari jika info lebih lanjut diperlukan.

question

Komentar yang paling membantu

@eranation : tidak, seharusnya hampir sama. Saat menggunakan pola ini, saya ingin menjauhkan items dari hash atribut saya sehingga saya tidak perlu menyinkronkannya. Ini mengharuskan Anda menarik objek items dari respons untuk parsing, dan menambahkannya kembali untuk serialisasi (lihat di bawah). Selain itu, Anda mungkin ingin memasukkan logika yang @rsim masukkan ke dalam initialize dalam metode constructor sebagai gantinya, dan gunakan on alih-alih bind (yang semi-usang).

Saya merasa jauh lebih mudah untuk memiliki atribut yang hanya berupa hash dangkal (tidak ada koleksi bersarang, model, dll.), Jika memungkinkan.

var Document = Backbone.Model.extend({
  constructor: function() {
    this.items = new ItemSet(null, {document: this});
    this.items.on('change', this.save, this);
    Backbone.Model.apply(this, arguments);
  },
  parse: function(resp) {
    this.items.set(resp.items, {parse: true, remove: false});
    delete resp.items;
    return resp;
  },
  toJSON: function() {
    var attrs = _.clone(this.attributes);
    attrs.items = this.items.toJSON();
    return attrs;
  }
});
var ItemSet = Backbone.Collection.extend({
  model: Item,
  initialize: function(models, options) {
    this.document = options.document;
  }
});
var Item = Backbone.Model.extend({
  // access document with this.collection.document
});
var document1 = new Document({
  name: "Test",
  version: 1,
  items: [
    {name : "Item 1", position : 0},
    {name : "Item 2", position : 1}
  ]
});

Ini tampaknya berfungsi dengan baik bahkan untuk skema yang sangat bersarang. (lihat dokumen )

Semua 11 komentar

Saya akan mengatakan Anda memiliki dua opsi utama... Yang pertama adalah membiarkan item sebagai atribut vanilla. Backbone menggunakan pemeriksaan kesetaraan mendalam ketika atribut berubah, jadi jika item dalam diperbarui, dokumen akan mengetahuinya.

Opsi lainnya adalah menarik item keluar dari dokumen dan melampirkannya sebagai model dengan haknya sendiri, di dalam koleksi yang menempel di dokumen (kami melakukan sesuatu di sepanjang baris ini di DocumentCloud). Misalnya (secara kasar):

var Document = Backbone.Model.extend({
  initialize: function() {
    this.items = new ItemSet();
    this.items.bind('change', this.save);
  }
});

Apakah salah satu dari itu bekerja dengan baik untuk Anda?

Saya akan merekomendasikan juga untuk menambahkan properti "dokumen" kembali ke objek Dokumen yang dapat diakses saat diperlukan dari item:

var Document = Backbone.Model.extend({
  initialize: function() {
    this.items = new ItemSet(this.get('items'), {document: this});
    this.items.bind('change', this.save);
  }
});
var ItemSet = Backbone.Collection.extend({
  initialize: function(models, options) {
    this.document = options.document;
  }
});
var Item = Backbone.Model.extend({
  // access document with this.collection.document
});
var document1 = new Document({
  name: "Test",
  version: 1,
  items: [
    {name : "Item 1", position : 0},
    {name : "Item 2", position : 1}
  ]
});

Saya percaya mengikat acara perubahan item ke penyimpanan dokumen adalah bagian yang hilang. Meskipun, penambahan dokumen ke ItemSet terlihat sangat membantu juga. Kami akan mencobanya hari ini dan saya akan memberi tahu kalian bagaimana hasilnya.

Ini berhasil dengan baik. Masalah terbesar yang kami alami sekarang adalah dengan mongoid. Terima kasih atas bantuannya.

Bagaimana cara saya menyimpan semua item sekaligus? Saya tidak ingin membuat permintaan setiap kali item diubah tetapi saya ingin menyimpan semuanya dengan satu permintaan pada tindakan pengguna. Saya sedang berpikir untuk mengumpulkan semuanya ketika dokumen disimpan dan memperbarui atribut 'item' dokumen. Apakah itu solusi yang bagus?

Selama item Anda diatur dalam dokumen, maka ketika Anda melakukan document.save() item akan dikirim ke server juga.

Tapi katakanlah jika saya menambahkan item ke koleksi document1.items saat runtime, itu tidak ditambahkan ke atribut 'items' dari document1 juga secara otomatis. Jadi jika saya kemudian melakukan document1.save(), model baru yang saya tambahkan ke koleksi tidak akan dikirim ke server. Saya tidak dapat melihat bagaimana perubahan pada koleksi dapat menyebar dalam atribut model yang dikirim dengan simpan.

Jadi, inilah cara kami menanganinya: dokumen memiliki larik item default. Pada inisialisasi, dalam metode set yang kelebihan beban, saya membuat koleksi item baru dari atribut dan mengaturnya pada dokumen.

class Document extends Backbone.Model
  defaults:
    items: []

  set: (attrs, options) ->
    items = attrs['items']
    if _( items ).isArray()
      if _( items ).isEmpty()
        attrs['items'] = new DocumentItemsCollection
        newItem = new Item
        attrs['items'].add(newItem, { silent: true })
      else
        attrs['items'] = new DocumentItemsCollection items

Pada saat itu Anda hanya berurusan dengan metode pengumpulan item dengan 'get', 'set', 'add' dan 'remove'. Anda tidak main-main dengan notasi titik. Saya bahkan memiliki metode di kelas Dokumen saya yang disebut addItem dan deleteItem untuk mengaktifkan peristiwa perubahan pada dokumen itu sendiri. Ketika Anda melakukan save() pada dokumen itu akan memanggil keJSON pada koleksi item Anda.

Sejujurnya, ini hanya kasus sederhana untuk dokumen kami dan kami memiliki sub-dokumen yang lebih dalam. Berurusan dengan jumlah kerumitan ini dengan tulang punggung, dan membebani beberapa metode pada model, adalah masalah besar yang nyata. Kami sekarang melihat untuk mengganti tulang punggung dengan sproutcore di masa depan.

Jika Anda harus berurusan dengan dokumen yang sangat rumit maka saya sarankan untuk melihat ExtJS atau sproutcore. Backbone sangat bagus untuk proyek kecil dengan model sederhana tetapi berantakan dengan cepat ketika objek/interaksi mulai meningkat.

Apakah ada "praktik terbaik" baru untuk ini untuk 1.0?

@eranation : tidak, seharusnya hampir sama. Saat menggunakan pola ini, saya ingin menjauhkan items dari hash atribut saya sehingga saya tidak perlu menyinkronkannya. Ini mengharuskan Anda menarik objek items dari respons untuk parsing, dan menambahkannya kembali untuk serialisasi (lihat di bawah). Selain itu, Anda mungkin ingin memasukkan logika yang @rsim masukkan ke dalam initialize dalam metode constructor sebagai gantinya, dan gunakan on alih-alih bind (yang semi-usang).

Saya merasa jauh lebih mudah untuk memiliki atribut yang hanya berupa hash dangkal (tidak ada koleksi bersarang, model, dll.), Jika memungkinkan.

var Document = Backbone.Model.extend({
  constructor: function() {
    this.items = new ItemSet(null, {document: this});
    this.items.on('change', this.save, this);
    Backbone.Model.apply(this, arguments);
  },
  parse: function(resp) {
    this.items.set(resp.items, {parse: true, remove: false});
    delete resp.items;
    return resp;
  },
  toJSON: function() {
    var attrs = _.clone(this.attributes);
    attrs.items = this.items.toJSON();
    return attrs;
  }
});
var ItemSet = Backbone.Collection.extend({
  model: Item,
  initialize: function(models, options) {
    this.document = options.document;
  }
});
var Item = Backbone.Model.extend({
  // access document with this.collection.document
});
var document1 = new Document({
  name: "Test",
  version: 1,
  items: [
    {name : "Item 1", position : 0},
    {name : "Item 2", position : 1}
  ]
});

Ini tampaknya berfungsi dengan baik bahkan untuk skema yang sangat bersarang. (lihat dokumen )

@akre54 terima kasih, ini adalah contoh yang bagus, sangat dihargai

Apakah halaman ini membantu?
0 / 5 - 0 peringkat