Các cách lưu dữ liệu mô hình Backbone.js?


86

Tôi thích phát triển giao diện người dùng hơn và gần đây đã bắt đầu khám phá Backbone.js vào ứng dụng của mình. Tôi muốn duy trì dữ liệu mô hình vào máy chủ.

Bạn có thể vui lòng giải thích cho tôi các cách khác nhau để lưu dữ liệu Mô hình (sử dụng định dạng json). Tôi đang sử dụng Java ở phía máy chủ. Ngoài ra, tôi chủ yếu thấy REST được sử dụng để lưu dữ liệu. Vì tôi là nhà phát triển giao diện người dùng nhiều hơn, tôi không biết về REST và những thứ tương tự khác.

Sẽ thật tuyệt nếu ai đó có thể giải thích cho tôi quy trình với một số ví dụ đơn giản.

Câu trả lời:


272

Về cơ bản Mô hình có một thuộc tính gọi là thuộc tính, là các giá trị khác nhau mà một mô hình nhất định có thể có. Backbone sử dụng các đối tượng JSON như một cách đơn giản để điền các giá trị này bằng các phương thức khác nhau lấy các đối tượng JSON. Thí dụ:

Donuts = Backbone.Model.extend({
    defaults: {
        flavor: 'Boston Cream',  // Some string
        price: '0.50'  // Dollars
    }
});

Để điền vào mô hình, có một số cách để làm như vậy. Ví dụ: bạn có thể thiết lập phiên bản mô hình của mình bằng cách truyền JSON HOẶC sử dụng phương thức gọi là set (), phương thức này nhận một đối tượng JSON của các thuộc tính.

myDonut = new Donut({'flavor':'lemon', 'price':'0.75'});
mySecondHelping = new Donut();
mySecondHelping.set({'flavor':'plain', 'price':'0.25'});

console.log(myDonut.toJSON());
// {'flavor':'lemon', 'price':'0.75'}
console.log(mySecondHelping.toJSON());
// {'flavor':'plain', 'price':'0.25'}

Vì vậy, điều này giúp chúng tôi lưu các mô hình và duy trì chúng trên một máy chủ. Có rất nhiều chi tiết liên quan đến "REST / RESTful là gì?" Và thật khó để giải thích tất cả điều này trong một đoạn ngắn ở đây. Đặc biệt đối với việc lưu REST và Backbone, điều bạn cần quan tâm là ngữ nghĩa của các yêu cầu HTTP và những gì bạn đang làm với dữ liệu của mình.

Có thể bạn đã quen với hai loại yêu cầu HTTP. NHẬN và ĐĂNG. Trong môi trường RESTful, những động từ này có ý nghĩa đặc biệt cho những mục đích sử dụng cụ thể mà Backbone giả định. Khi bạn muốn lấy một tài nguyên nào đó từ máy chủ, (ví dụ như mô hình bánh rán mà tôi đã lưu lần trước, một mục blog, một đặc tả máy tính) và tài nguyên đó tồn tại, bạn thực hiện yêu cầu GET. Ngược lại, khi bạn muốn tạo một tài nguyên mới, bạn sử dụng POST.

Trước khi sử dụng Backbone, tôi thậm chí chưa từng chạm vào hai phương thức yêu cầu HTTP sau. ĐẶT và XÓA. Hai động từ này cũng có ý nghĩa cụ thể đối với Backbone. Khi bạn muốn cập nhật một tài nguyên, (ví dụ: Thay đổi hương vị của bánh rán chanh thành bánh rán limon, v.v.), bạn sử dụng yêu cầu PUT. Khi bạn muốn xóa toàn bộ mô hình đó khỏi máy chủ, bạn sử dụng yêu cầu XÓA.

Những điều cơ bản này rất quan trọng vì với ứng dụng RESTful của bạn, bạn có thể sẽ có chỉ định URI sẽ thực hiện nhiệm vụ thích hợp dựa trên loại động từ yêu cầu mà bạn sử dụng. Ví dụ:

// The URI pattern
http://localhost:8888/donut/:id

// My URI call
http://localhost:8888/donut/17

Nếu tôi thực hiện GET cho URI đó, nó sẽ nhận được mô hình bánh rán với ID là 17.: id phụ thuộc vào cách bạn lưu nó ở phía máy chủ. Đây chỉ có thể là ID của tài nguyên donut trong bảng cơ sở dữ liệu của bạn.

Nếu tôi thực hiện PUT cho URI đó với dữ liệu mới, tôi sẽ cập nhật nó, lưu trên nó. Và nếu tôi XÓA URI đó, thì nó sẽ xóa nó khỏi hệ thống của tôi.

Với POST, vì bạn chưa tạo tài nguyên nên nó sẽ không có ID tài nguyên đã thiết lập. Có thể mục tiêu URI mà tôi muốn tạo tài nguyên chỉ đơn giản là:

http://localhost:8888/donut

Không có phân đoạn ID nào trong URI. Tất cả các thiết kế URI này là tùy thuộc vào bạn và cách bạn nghĩ về tài nguyên của mình. Nhưng liên quan đến thiết kế RESTful, tôi hiểu là bạn muốn giữ nguyên các động từ của hành động cho yêu cầu HTTP và các tài nguyên dưới dạng danh từ giúp URI dễ đọc và thân thiện với con người.

Bạn vẫn còn với tôi? :-)

Vì vậy, hãy quay lại suy nghĩ về Backbone. Backbone thật tuyệt vời vì nó giúp ích rất nhiều cho bạn. Để tiết kiệm donut và secondHelping của chúng tôi, chúng tôi chỉ cần thực hiện điều này:

myDonut.save();
mySecondHelping.save();

Backbone là thông minh. Nếu bạn vừa tạo tài nguyên bánh rán, nó sẽ không có ID từ máy chủ. Nó có một thứ gọi là cID, là thứ mà Backbone sử dụng nội bộ nhưng vì nó không có ID chính thức nên nó biết rằng nó nên tạo một tài nguyên mới và nó sẽ gửi một yêu cầu POST. Nếu bạn lấy mô hình của mình từ máy chủ, nó có thể sẽ có ID nếu tất cả đều đúng. Trong trường hợp này, khi bạn save () Backbone giả sử rằng bạn muốn cập nhật máy chủ và nó sẽ gửi một PUT. Để có được một tài nguyên cụ thể, bạn sẽ sử dụng phương thức Backbone .fetch () và nó sẽ gửi một yêu cầu GET. Khi bạn gọi .destroy () trên một mô hình, nó sẽ gửi DELETE.

Trong các ví dụ trước, tôi chưa bao giờ nói rõ ràng cho Backbone biết vị trí của URI. Hãy làm điều đó trong ví dụ tiếp theo.

thirdHelping = Backbone.Model.extend({
    url: 'donut'
});
thirdHelping.set({id:15});  // Set the id attribute of model to 15
thirdHelping.fetch();  // Backbone assumes this model exists on server as ID 15

Backbone sẽ NHẬN được cái thứ ba Giúp đỡ tại http://localhost:8888/donut/15Nó sẽ chỉ cần thêm / donut gốc vào gốc trang web của bạn.

Nếu bạn VẪN với tôi, tốt. Tôi nghĩ. Trừ khi bạn đang bối rối. Nhưng dù sao chúng ta cũng sẽ tiếp tục. Phần thứ hai của điều này là phía máy chủ. Chúng ta đã nói về các động từ khác nhau của HTTP và ý nghĩa ngữ nghĩa đằng sau những động từ đó. Có nghĩa là bạn, Backbone, VÀ máy chủ của bạn phải chia sẻ.

Máy chủ của bạn cần hiểu sự khác biệt giữa yêu cầu GET, POST, PUT và DELETE. Như bạn đã thấy trong các ví dụ trên, GET, PUT và DELETE đều có thể trỏ đến cùng một URI http://localhost:8888/donut/07Trừ khi máy chủ của bạn có thể phân biệt giữa các yêu cầu HTTP này, nếu không sẽ rất bối rối không biết phải làm gì với tài nguyên đó.

Đây là lúc bạn bắt đầu nghĩ về mã kết thúc máy chủ RESTful của mình. Một số người thích Ruby, một số người thích .net, tôi thích PHP. Đặc biệt tôi thích SLIM PHP micro-framework. SLIM PHP là một khuôn khổ vi mô có một bộ công cụ rất đơn giản và thanh lịch để xử lý các hoạt động RESTful. Bạn có thể xác định các tuyến (URI) như trong các ví dụ ở trên và tùy thuộc vào việc lệnh gọi là GET, POST, PUT hay DELETE, nó sẽ thực thi đúng mã. Có những giải pháp khác tương tự như SLIM như Recess, Tonic. Tôi tin rằng các khung công tác lớn hơn như Cake và CodeIgniter cũng làm những điều tương tự mặc dù tôi thích tối thiểu. Tôi đã nói rằng tôi thích Slim? ;-)

Đây là những gì mã trích dẫn trên máy chủ có thể trông (nghĩa là cụ thể liên quan đến các tuyến đường.)

$app->get('/donut/:id', function($id) use ($app) {
    // get donut model with id of $id from database.
    $donut = ...

    // Looks something like this maybe:
    // $donut = array('id'=>7, 'flavor'=>'chocolate', 'price'=>'1.00')

    $response = $app->response();
    $response['Content-Type'] = 'application/json';
    $response->body(json_encode($donut));
});

Ở đây, điều quan trọng cần lưu ý là Backbone mong đợi một đối tượng JSON. Luôn để máy chủ của bạn chỉ định loại nội dung là 'ứng dụng / json' và mã hóa nó ở định dạng json nếu bạn có thể. Sau đó, khi Backbone nhận được đối tượng JSON, nó sẽ biết cách điền vào mô hình đã yêu cầu nó.

Với SLIM PHP, các tuyến hoạt động tương tự như trên.

$app->post('/donut', function() use ($app) {
    // Code to create new donut
    // Returns a full donut resource with ID
});
$app->put('/donut/:id', function($id) use ($app) {
    // Code to update donut with id, $id
    $response = $app->response();
    $response->status(200);  // OK!
    // But you can send back other status like 400 which can trigger an error callback.
});
$app->delete('/donut/:id', function($id) use ($app) {
    // Code to delete donut with id, $id
    // Bye bye resource
});

Vậy là bạn đã gần thực hiện trọn vẹn chuyến đi khứ hồi! Đi lấy một lon nước ngọt. Tôi thích Diet Mountain Dew. Nhận một cái cho tôi quá.

Khi máy chủ của bạn xử lý một yêu cầu, thực hiện điều gì đó với cơ sở dữ liệu và tài nguyên, chuẩn bị phản hồi (cho dù đó là số trạng thái http đơn giản hay tài nguyên JSON đầy đủ), sau đó dữ liệu sẽ quay trở lại Backbone để xử lý lần cuối.

Với các phương thức save (), fetch (), v.v. - bạn có thể thêm các lệnh gọi lại tùy chọn khi thành công và có lỗi. Đây là một ví dụ về cách tôi thiết lập chiếc bánh cụ thể này:

Cake = Backbone.Model.extend({
    defaults: {
        type: 'plain',
        nuts: false
    },
    url: 'cake'
});

myCake = new Cake();
myCake.toJSON()  // Shows us that it is a plain cake without nuts

myCake.save({type:'coconut', nuts:true}, {
    wait:true,
    success:function(model, response) {
        console.log('Successfully saved!');
    },
    error: function(model, error) {
        console.log(model.toJSON());
        console.log('error.responseText');
    }
});

// ASSUME my server is set up to respond with a status(403)
// ASSUME my server responds with string payload saying 'we don't like nuts'

Có một vài điều khác nhau về ví dụ này. Bạn sẽ thấy rằng đối với chiếc bánh của tôi, thay vì đặt () nhập các thuộc tính trước khi lưu, tôi chỉ cần chuyển các thuộc tính mới vào lệnh gọi lưu của mình. Backbone là một ninja giỏi trong việc lấy dữ liệu JSON ở khắp mọi nơi và xử lý nó như một nhà vô địch. Vì vậy, tôi muốn để dành chiếc bánh của mình với dừa và các loại hạt. (Đó có phải là 2 quả hạch không?) Dù sao, tôi đã chuyển vào hai đối tượng để cứu. Đối tượng JSON thuộc tính VÀ một số tùy chọn. Đầu tiên, {wait: true} có nghĩa là không cập nhật mô hình phía máy khách của tôi cho đến khi chuyến đi phía máy chủ thành công. Cuộc gọi lại thành công sẽ xảy ra khi máy chủ trả về phản hồi thành công. Tuy nhiên, vì ví dụ này dẫn đến lỗi (trạng thái khác 200 sẽ chỉ ra cho Backbone sử dụng lệnh gọi lại lỗi), chúng tôi nhận được một đại diện của mô hình mà không có các thay đổi. Nó vẫn phải đơn giản và không có hạt. Chúng tôi cũng có quyền truy cập vào đối tượng lỗi mà máy chủ đã gửi lại. Chúng tôi đã gửi lại một chuỗi nhưng nó có thể là đối tượng lỗi JSON với nhiều thuộc tính hơn. Điều này nằm trong thuộc tính error.responseText. Vâng, 'chúng tôi không thích các loại hạt.'

Xin chúc mừng. Bạn đã thực hiện chuyến đi vòng quanh khá đầy đủ đầu tiên của mình từ việc thiết lập một mô hình, lưu nó ở phía máy chủ và quay lại. Tôi hy vọng rằng sử thi câu trả lời này cung cấp cho bạn một Ý tưởng về cách tất cả những điều này kết hợp với nhau. Tất nhiên, có rất nhiều chi tiết mà tôi đang lướt qua nhưng những ý tưởng cơ bản về Lưu đường trục, Động từ RESTful, Hành động phía máy chủ, Phản hồi đều có ở đây. Tiếp tục xem qua tài liệu Backbone (siêu dễ đọc so với các tài liệu khác) nhưng chỉ cần lưu ý rằng điều này cần thời gian để bạn hiểu. Bạn càng giữ vững nó thì bạn càng thông thạo hơn. Tôi học điều gì đó mới với Backbone mỗi ngày và điều đó thực sự thú vị khi bạn bắt đầu có những bước tiến nhảy vọt và thấy sự thông thạo của bạn trong khung này ngày càng tăng. :-)

Chúc bạn viết mã vui vẻ!

CHỈNH SỬA: Các tài nguyên có thể hữu ích:

Các câu trả lời tương tự khác trên SO: Cách tạo ID mô hình bằng Backbone

Trên REST: http://rest.elkstein.org/ http://www.infoq.com/articles/rest-introduction http://www.recessframework.org/page/towards-restful-php-5-basic- lời khuyên


9
Tôi đã kết thúc một chút điên rồ về điều này. Tôi nhớ khi tôi lần đầu tiên bắt đầu Backbone và có những câu hỏi giống như người hỏi và tôi cảm thấy rất vui khi viết ra một câu trả lời. Tôi chắc rằng trong lúc vội vàng, tôi đã mắc một số lỗi hoặc bỏ lỡ một số "ah-ha!" các khía cạnh vì vậy nếu tôi đã làm, hãy cho tôi biết. :-P
jmk2142

6
Câu trả lời tuyệt vời để nói điều ít nhất ... tôi đang cố gắng nắm bắt tất cả những điều mà bạn đã đề cập ... điều REST có vẻ hơi khó khăn mặc dù bạn nói đúng, bạn chắc chắn không thể giải thích tôi REST trong câu hỏi này ... Tôi ' sẽ trải qua những điều một lần nữa và chấp nhận nó trong một thời gian ... Thx lần nữa cho câu trả lời chi tiết ...
testndtv

2
Khi có thời gian, tôi sẽ cập nhật câu trả lời của mình bằng danh sách các tài liệu tham khảo tốt có thể giúp bạn trong nhiệm vụ. Tôi không thể cung cấp cho bạn một thanh kiếm gỗ để đối mặt với thế giới nguy hiểm ngoài kia, nhưng tôi có thể cung cấp cho bạn các liên kết tài nguyên của các trang web đã giúp tôi. :-)
jmk2142

5
@testndtv Tôi đã trả lời câu hỏi của bạn chưa? Một dấu √ sẽ được đánh giá cao.
jmk2142

2
Không có nghi ngờ u đã trả lời câu hỏi theo cách hơn mong đợi ... Tôi đã chấp nhận câu trả lời now..Thanks rất nhiều lần nữa cho sự giúp đỡ ..
testndtv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.