Backbone.Js and Rails

1. Backbone.Js là gì?

Nói một cách đơn giản, Backbone Js là một framework của Javascript. Hay nó chính là một Javascript phía client. Giúp chúng ta tổ chức viết Javascrip một cách có cấu trúc rõ ràng, cụ thể hơn.

2. Tại sao chúng ta nên sử dụng Backbone.Js?

Sử dụng backbone.js giúp chúng ta có thể tạo ra các ứng dụng Javascript một cách dễ dàng hơn, nhanh hơn. Cấu trúc của Backbone.js giống mô hình MVC, giúp chúng ta quản lý tốt hơn. Khi sử dụng Backbone.js chúng ta dễ dàng bảo trì hơn, do code JS được viết bới backbone.js rất rõ ràng và dễ hiểu.

3. Các thành phần cơ bản của Backbone.Js

Router

Bộ định tuyền router sử dụng chính routes của Rails để xác định sẽ khởi tạo và sử dụng các View nào của Backbone.Js

View

Là nơi lắng nghe các sự kiện, và quyết định các hành động phản ứng lại với các sự kiện mà ngời dùng tương tác.

Model

Dùng để lưu giữ các dữ liệu tương tác

Collection

Như là một tập có thứ tự của Model. Nó như là một tập con của Model, giúp chúng ta lấy dữ liệu dạng Json từ các request URL.

4. Cài đặt và sử dụng Backbone.Js với Rails.

a) Cài đặt

Add “ gem 'rails-backbone' “ to Gemfile

Install:

    bundle install
    rails g backbone:install // Tạo các thư mục cho router, view, model, template (các file mã html sử dụng cho view, lấy dữ liệu từ server trả về)
    rails g scaffold Post title:string content:string
    rake db:migrate
    rails g backbone:scaffold Post title:string content:string (VD: muốn tạo tự động các file router, model, view, colection... với bảng Post)

(Không muốn sử dụng backbone:scaffold ta có thể tạo riêng các file trong backbone như sau:

    rails g backbone:model name_model - Tạo model với backbone có tên là name_model
    rails g backbone:router name_router - Tạo router với backbone có tên là name_router).

b) Cách sử dụng Backbone.Js với Rails.

Ví dụ ta sử dụng Backbone.Js với trang Index (VD: Ứng dụng Framgia_member để hiển thị tên và mã của các thành viên trong công ty)

<script>
  $(function(){
    router = new FramgiaMember.Routers.AppRouter({controller:"<%= params[:controller] %>",action:"<%= params[:action] %>"});
  });
</script>

Khởi tạo Router với tham số là controller và action. Khi đó Router sẽ dụng các tham số này để cài đặt View

FramgiaMember.Routers.AppRouter = Backbone.Router.extend({
  initialize: function(options) {
    this.controller = options.controller;
    this.action = options.action;
    this.setview();
    },

  setview: function(){
    switch(this.controller){
      case "framgia_members":
        this.setViewMember(); break;
    }
  },

  setViewMember: function(){
    switch(this.action){
      case "index":
        new FramgiaMember.Views.FramgiaMember.Index; break;
    }
  }
});

Như trên ta thấy, với controller là "framgia_members" và action "index" thì ta sẽ khởi tạo và sử dụng view "FramgiaMember.Views.FramgiaMember.Index" Nội dung file FramgiaMember.Views.FramgiaMember.Index :

FramgiaMember.Views.FramgiaMember ||(FramgiaMember.Views.FramgiaMember= {});

FramgiaMember.Views.FramgiaMember.Index = Backbone.View.extend({
  template: JST["backbone/templates/framgia_member/member"],
  el: "#main",
  initialize: function(){
    this.member = new FramgiaMember.Models.Member;
    this.collection = new FramgiaMember.Collections.MemberCollection;
  },

  events: {
    "click #show_all": "show_all",
    "click #show_one": "show_one",
  },

  show_all: function(){
    this.collection.setUrl("");
    this.render();
  },

  show_one: function(){
    this.collection.setUrl($("#id").val());
    this.render();
  },

  render: function(){
    var that = this
    this.collection.fetch().done(function(){
        var new_view = that.template({data:that.collection.toJSON()});
        console.log(that.collection.toJSON());
        $("tbody").append(new_view);
    });
  }
});

Như trên ta có: event{} là nơi ta định nghĩa event cho các đối tượng nào và hành động tương ứng trong các hàm. Sau đó ta mới viết hàm ở dưới, điều này giúp ta có cái nhìn khái quát hơn, quản lý tốt hơn với các event trong view.

Sử dụng collection để lấy dữ liệu trả về dạng json trong backbone.js: Dòng code:

template: JST["backbone/templates/framgia_member/member"]
để khai báo file trong template để ta sử dụng trong hàm render:
  render: function(){
    var that = this
    this.collection.fetch().done(function(){
        var new_view = that.template({data:that.collection.toJSON()});
        $("tbody").append(new_view);
    });
  }

Khi sử dụng fetch() với collection thì backbone sẽ lấy dữ liệu từ server thông qua url được cài đặt trong collection đó:

 FramgiaMember.Collections.MemberCollection = Backbone.Collection.extend({

  setUrl: function(id){
    if (id == ""){
      this.url = '/framgia_members.json'
    } else{
      this.url = '/framgia_members/' + id + ".json";
    }
  }
});

như trên ta có, khi id truyền vào là rỗng thì ta sẽ request tới index_path,nếu truyền vào id thì ta request tới framgia_member_path(id), khi đó trong view sẽ có file "index.json.jbuilder" và "show.json.jbuilder" để quyết định sẽ trả về dữ liệu nào. Nó giúp chúng ta tránh được sự dư thừa thông tin khi trả về cả đối tượng. VD: File jndex.json.jbuilder chỉ trả về full_name, code và id.

json.array!(@framgia_members) do |framgia_member|
  json.full_name framgia_member.full_name
  json.code framgia_member.code
  json.id framgia_member.id
end

Dòng lệnh that.template({data:that.collection.toJSON()}); truyền dữ liệu vào file templates với tên là data. Khi đó file template sẽ sử dụng biến data để lấy dữ liệu và dùng cho hiển thị. File "member.jst.efs" (File template được khai báo từ trước: template: JST["backbone/templates/framgia_member/member"])

<% _.each(data, function(member){ %>
<tr class="<%= member.id %>">
<td><%= member.full_name %></td>
<td><%= member.code %></td>

<td><a href="/framgia_members/<%= member.id %>">Show</td>
<td><a href="/framgia_members/<%= member.id %>/edit">Edit</td>
<td><a href="/framgia_members/<%= member.id %>/destroy" class="destroy">Destroy</a></td>
<td class="delete_this"><button>Delete</button></td>
</tr>

Tài liệu tham khảo tại:


All Rights Reserved