开源展示型网站网络运营与推广
ember框架
客户端MVC框架吸引了所有关注,我决定是时候真正看一下其中的一个,并为自己确定炒作是否值得了。
我敢肯定,你们中许多人被玩弄这些框架,而看着别人做 的 一样 。 这些简短的涉猎几乎没有告诉您构建有用的东西的感觉。 在本文中,我将探讨构建实际价值的感觉。
选择正确的MVC框架似乎很困难。 仅提供了一些Backbone.js,Angular.js,Ember.js。 我评估过的务实的Rails开发人员认为Ember.js是最Rails友好的框架。 它与Rails很好地集成在一起,从后端切换到前端时非常适合。
为了构建有趣的东西,而不是重新发明轮子,我们将在TodoMVC应用程序之上构建 。 它是官方ember指南中用作示例的同一应用程序。 我们的版本将重点介绍如何通过以下方式构建和扩展它:
- 移至Rails项目
- 使用Rails作为后端存储
- 添加身份验证
- 为经过身份验证的用户添加私人列表
- 添加受保护的列表共享
有很多方面需要介绍,因此需要花费一些时间。 今天,我们将介绍将应用程序移至在Rails项目中运行以及使用Rails进行后端存储的过程。
灰烬中的TodoMVC
TodoMVC应用程序用作比较前端javascript框架的通用示例。 它具有足够的功能来展示框架,同时,任何潜在的开发人员都会立即熟悉它。 让我们简要介绍一下这些功能。
该应用程序在顶部显示一个带有文本字段的待办事项列表。 您可以使用文本字段将新项目添加到列表中。 也可以通过双击单个项目来进行编辑,然后使用悬停时显示的删除图标将其删除。 可以使用输入框的复选框将所有待办事项标记为已完成。
在列表下方,有一个未完成项目的计数器和一个用于显示所有/活动/已完成任务的过滤器。 最后,您可以使用底部的“清除已完成”按钮从列表中删除所有已完成的项目。
本文不会涉及所有细节,因为在官方余烬指南中有一篇非常出色的文章。 在这里,重点是如何将零件组装在一起的高层次概述,从而清楚地说明了将示例移植到Rails项目中的过程。
基本模板是开始熟悉Ember应用程序的地方。 该模板是所有组件组合在一起的地方:您可以从script
标签中概览应用程序的大小以及所处的位置。 以下摘录来自TodoMVC应用程序:
<!doctype html>
<html lang="en" data-framework="emberjs">
<head>
<meta charset="utf-8">
<title>ember.js • TodoMVC</title>
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
</head>
<body>
<script type="text/x-handlebars" data-template-name="todos">
<!--handlebars template content omitted-->
</script>
<!--library files-->
<script src="bower_components/todomvc-common/base.js"></script>
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/handlebars/handlebars.js"></script>
<script src="bower_components/ember/ember.js"></script>
<script src="bower_components/ember-data/ember-data.js"></script>
<script src="bower_components/ember-localstorage-adapter/localstorage_adapter.js"></script>
<!--application files-->
<script src="js/app.js"></script>
<script src="js/router.js"></script>
<script src="js/models/todo.js"></script>
<script src="js/controllers/todos_controller.js"></script>
<script src="js/controllers/todo_controller.js"></script>
<script src="js/views/edit_todo_view.js"></script>
<script src="js/views/todos_view.js"></script>
<script src="js/helpers/pluralize.js"></script>
</body>
</html>
在大多数情况下,它看起来像是带有许多JavaScript的标准HTML5文档。 单个非标准部分是x-handlebars模板。 此处省略了代码,但在官方的余烬指南中进行了讨论。 像这样将其包含在HTML中对于小型应用程序来说是很好的选择,但在迁移到Rails的过程中,我们将其提取出来。
javascript的导入有两个方面:第一部分是导入运行Ember应用程序所需的库文件,而第二部分是Ember应用程序本身。 指南中将对这两种方法进行更详细的讨论,因此请参考以获取更多信息。
设置滑轨
Rails对托管Ember应用程序提供了良好的支持。 您需要做的就是在Gemfile中包含ember-rails gem并生成安装文件。
gem 'ember-rails'
gem 'ember-data-source', '>= 1.0.0.beta7'
rails g ember:bootstrap
生成器在app / assets / javascripts下创建一个ember文件夹结构。 当前版本并不完美,需要一些小的调整才能完成设置。
首先,删除原始的app / assets / javascripts / application.js 。 然后,将以下两行添加到app / assets / javascripts / application.js.coffee的最顶部,以在加载Ember之前加载jQuery。
#= require jquery
#= require jquery_ujs
要打开根页面,请将以下内容添加到config / routes.rb中
Rails.application.routes.draw do
root to: 'application#index'
end
另外,添加一个空的app / views / application / index.html.erb 。 这是使用默认ApplicationController
无需任何其他代码即可呈现index
操作的良好起点。 启动Rails应用程序( rails s
),然后将浏览器指向http:// localhost:3000 ,以确保所有内容均已连接。
将TodoMVC移入Rails

免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
是时候将TodoMVC应用程序复制到我们的Rails应用程序中了。 如果要跳到最后,结果代码在github上 。
首先将前面讨论过的车把模板复制到app / views / application / index.html.haml 。 通过删除turbolinks
引用并在body
标签内的yield
之后移动javascript_include_tag
编辑app / views / layouts / application.html.erb文件。 对于可选功劳,我们可以从Gemfile中删除涡轮链接,因为我们不会使用它们。
通过复制以下文件并将其转换为CoffeeScript,完成迁移。
js / routes.js => app / assets / javascripts / routes.js.coffee
TadaEmber.Router.map ->
@resource 'todos', path: '/', ->
@route 'active'
@route 'completed'
TadaEmber.TodosRoute = Ember.Route.extend
model: -> @store.find('todo')
TadaEmber.TodosIndexRoute = Ember.Route.extend
setupController: -> @controllerFor('todos').set('filteredTodos', this.modelFor('todos'))
TadaEmber.TodosActiveRoute = Ember.Route.extend
setupController: ->
todos = @store.filter 'todo', (todo) ->
!todo.get('isCompleted')
@controllerFor('todos').set('filteredTodos', todos)
TadaEmber.TodosCompletedRoute = Ember.Route.extend
setupController: ->
todos = @store.filter 'todo', (todo) ->
todo.get('isCompleted')
@controllerFor('todos').set('filteredTodos', todos)
js / models / todo.js => app / assets / javascripts / models / todo.js
TadaEmber.Todo = DS.Model.extend
title: DS.attr('string')
isCompleted: DS.attr('boolean')
js / controllers / todos controller.js => app / assets / javascripts / controllers / todos controller.js.cofee
TadaEmber.TodosController = Ember.ArrayController.extend
actions:
createTodo: ->
title = @get('newTitle').trim()
return if !title
todo = @store.createRecord 'todo',
title: title
isCompleted: false
todo.save()
@set('newTitle', '')
clearCompleted: ->
completed = @get('completed')
completed.invoke('deleteRecord')
completed.invoke('save')
remaining: Ember.computed.filterBy('content', 'isCompleted', false)
completed: Ember.computed.filterBy('content', 'isCompleted', true)
allAreDone: ((key, value) ->
if value != undefined
@setEach('isCompleted', value)
return value;
else
length = @get('length')
completedLength = @get('completed.length')
return length > 0 && length == completedLength
).property('length', 'completed.length')
js / controllers / todo controller.js => app / assets / javascripts / controllers / todo controller.js.coffee
TadaEmber.TodoController = Ember.ObjectController.extend
isEditing: false
bufferedTitle: Ember.computed.oneWay('title')
actions:
editTodo: -> @set('isEditing', true)
doneEditing: ->
bufferedTitle = @get('bufferedTitle').trim()
if Ember.isEmpty(bufferedTitle)
Ember.run.debounce(@, 'removeTodo', 0)
else
todo = @get('model')
todo.set('title', bufferedTitle)
todo.save()
@set('bufferedTitle', bufferedTitle)
@set('isEditing', false)
cancelEditing: ->
@set('bufferedTitle', @get('title'))
@set('isEditing', false)
removeTodo: -> @removeTodo()
removeTodo: ->
todo = @get('model')
todo.deleteRecord()
todo.save()
saveWhenCompleted: (->
@get('model').save()
).observes('isCompleted')
js / views / edit todo view.js => app / assets / javascripts / views / edit todo view.js.coffee
TadaEmber.EditTodoView = Ember.TextField.extend
focusOnInsert: (->
@.$().val(@.$().val())
@.$().focus
).on('disInsertElement')
Ember.Handlebars.helper('edit-todo', TadaEmber.EditTodoView)
js / views / todos view.js => app / assets / javascripts / views / todos view.js.coffee
TadaEmber.TodosView = Ember.View.extend
focusInput: (-> @.$('#new-todo').focus() ).on('disInsertElement')
js / helpers / pluralize.js => app / assets / javascripts / helpers / pluralize.js
Ember.Handlebars.helper 'pluralize', (singular, count) ->
inflector = Ember.Inflector.inflector;
count == 1 ? singular : inflector.pluralize(singular)
app / assets / javascripts / store.js.coffee
TadaEmber.Store = DS.Store.extend()
# Override the default adapter with the `DS.ActiveModelAdapter` which
# is built to work nicely with the ActiveModel::Serializers gem.
#adapter: '_ams'
TadaEmber.ApplicationAdapter = DS.LSAdapter.extend
namespace: 'tada-emberjs'
快完成了 将Bower组件/ ember-localstorage-adapter / localstorage adapter.js复制到app / assets / javascript / localstorage adapter.js并将以下行添加到app / assets / javascript / tadaember.js.coffee的顶部
#= require ./localstorage_adapter
通过将app / views / application / index.html.erb中的script
标签的内容复制到app / javascripts / templates / todos.hbs中来完成转换 。 最后,将css和图像从原始代码复制到我们的资产目录将添加一些样式。
在后端添加Rails
该列表将其数据保存在当前正在运行该应用程序的浏览器的localstorage
中。 在其他浏览器中打开该应用程序将导致该应用程序重置为干净状态,而无需执行任何操作。 我们将使用Rails应用程序作为存储提供程序来对此进行补救。
首先,生成模型并迁移
rails g model Todo title is_completed:boolean
rake db:migrate
添加一个控制器,该控制器将充当Ember应用程序的API。 不要忘记将资源调用添加到路由器。
app / controllers / todos_controller.rb
class TodosController < ApplicationController
respond_to :json
def index
respond_with Todo.all
end
def show
respond_with Todo.find(params[:id])
end
def create
respond_with Todo.create(todo_params)
end
def update
respond_with Todo.update(params[:id], todo_params)
end
def destroy
respond_with Todo.destroy(params[:id])
end
private
# Never trust parameters from the scary internet, only allow the white list through.
def todo_params
params.require(:todo).permit(:title, :is_completed)
end
end
config / routes.rb
Rails.application.routes.draw do
resources :todos
root to: 'application#index'
end
最后,为Rails添加序列化器以正确序列化模型。 Ember希望每个模型都有一个字符串ID。 ActiveModelAdapter
将处理从JSON来的snakecase is_completed
与Ember应用程序中使用的camelcase isCompleted
之间的转换。
app / serializers / todo_serializer.rb
class TodoSerializer < ActiveModel::Serializer
# fix for ember-data deserializer not being able to handle non-string ids
def id
object.id.to_s
end
attributes :id, :title, :is_completed
end
要卸下辅助轮并使用新的Rails后端,请更新Ember商店以使用ember-rails gem提供的activemodel商店。 (有关详情,请参阅此 。)
TadaEmber.Store = DS.Store.extend
# Override the default adapter with the `DS.ActiveModelAdapter` which
# is built to work nicely with the ActiveModel::Serializers gem.
adapter: '-active-model'
最终产品可在github上找到
结论
我们已经成功地将TodoMVC应用程序从独立应用程序迁移到了在Rails中运行。 我们还从本地存储转移到了将数据存储在Rails中。 在以后的文章中,我们将解决添加身份验证以及通过url共享列表的功能。
翻译自: https://www.sitepoint.com/ember-todomvc-rails/
ember框架