专为 Rails 设计的前端模块化框架

组件化的页面

“道” 提倡以组件为单位拆分页面。

# app/views/todos/show.html.erb

<%= tao_todo_item todo %>
<%= tao_todo_comments todo %>      

组件化的渲染逻辑

“道” 以组件为单位模块化渲染逻辑,每个组件有一个对应的组件类和一个可选的 partial 模版。

组件类会定义组件的 attributes、helper method,以及对应的 view helper。例如,Todos::ItemComponent 对应的 view helper 是 tao_todo_item(todo, options)

# app/components/todos/item_component.rb

class Todos::ItemComponent < ApplicationComponent

  attr_reader :todo

  def initialize view, todo, options = {}
    super view, options
    @todo = todo
  end

  def tags
    /#(.+?)#/.match(todo.content).to_a
  end

  def content_without_tags
    todo.content.gsub(/#(.+?)#/, '')
  end

end      

组件可以有对应的 partial 模版,例如,Todos::ItemComponent 对应的 partial 模版是 app/views/components/todos/_item.html.erb

组件的 partial 模版会接受组件的实例 component 作为 locale variable 传入。

<!-- app/views/components/todos/_item.html.erb -->
<%= content_tag component.tag_name, id: dom_id(component.todo), completed: component.todo.completed do %>
  <%= check_box_tag nil, '1', component.todo.completed, class: 'todo-checkbox' %>
  <div class="tags">
    <% component.tags.each do |tag| %>
      <%= link_to tag, '#', class: 'tag' %>
    <% end %>
  </div>
  <div class="content"><%= component.content_without_tags %></div>
<% end %>      

组件化的交互逻辑

“道” 以组件为单位模块化交互逻辑。

按照 Custom Elements V1 标准,组件被封装成标准的自定义 HTMLElement。

TaoComponent 提供了一套属性声明机制,通过这套机制我们可以方便的操作自定义元素的 HTML 属性。

# app/assets/javascripts/components/todos/item.coffee

class TodoItem extends TaoComponent

  @tag 'tao-todo-item'

  @attribute 'completed', type: 'boolean', default: false

  _connected: ->
    @on 'click', '.todo-checkbox', (e) =>
      @completed = $(e.currentTarget).is(':checked')

  _disconnected: ->
    @off()

TaoComponent.register TodoItem