javascripthfpp2012发表于*编辑于

1. 介绍

现如今react那么流行,除了我们可以在前端用npm来使用react之外,比如用webpack + react + redux,其实在rails中也使用react。在rails中集成react跟在纯前端使用react还是有差异的,现在我们就来讲讲两种使用react的方法。

2. react-rails

react-rails是一个gem,它允许你用传统的方法,比如纯js,或jsx的语法格式来写react,文件的组织也是按照rails的作法来,都放在app/assets/javascripts下,默认情况下没有使用任何类似browserifywebpack的情况下,它都是写完后一起被打包,通过asset pipeline来编译的。

使用官方的readme文档就可以安装和使用它。

下面来说说它的优点和缺点。

优点之一,就是它简单,无论是安装或配置使用都相对简单,它还可以用服务器来渲染,也能轻易的传递rails的变量到组件中。也就是说它能够轻易地利用rails。

比如:

class TodoController < ApplicationController
  def index
    @todos = Todo.all
    render component: 'TodoList', props: { todos: @todos }, tag: 'span', class: 'todo'
  end
end

优点之二是也可以用es6或coffee语法来写。

它的缺点之一,是如果大量使用react的情况下还是感觉有点苍白和不足,如果局布使用还是可以的,就是某些页面太复杂,需要用上react的情况。

最致命的缺点是,它的包管理机制的不足。

什么叫包管理机制的不足。如果你有开发过react应该,你也稍微了解过react是有很多插件,它有一个很大的生态圈,很多人贡献了react的插件,这些插件让我们减少了不少开发成本,比如react-router,或者react-bootstrap

如果在前端开发react,我们可以会使用browserifywebpack来管理这些插件。

但是默认情况下,在react-rails或rails中,你是要下载一个js文件,然后放在javascripts目录下,要用的话,就在application.js文件里require一下。

那么问题来了,你会发现好多的react插件,你下载不到这种js文件,它们本身就是npm包。没有这种编译好的文件。

这个时候,你除非自己去编译出来,再放到javascripts目录下,或者使用browserifywebpack来管理,它们都有rails的gem包。

比如下面这个应用就是react-rails结合browserify的一个demo。

react-rails-redux-sample

幸运的是比较出名的库,比如[react-router]和[react-bootstrap]它们是有打包好的js文件的。

<script src="https://unpkg.com/react-router/umd/ReactRouter.min.js"></script>

要使用这个插件,可以通过window.ReactRouter来调用。

详情可查看这两个插件的主页。

还有一个地方能下载打包后的js文件。

unpkg

如果想要了解如何打包这种js文件,可以看下面这个链接。

umd

下面有一篇博客是演示如何在rails中使用这个gem的,不过它的语法是用coffeescript写的,我感觉很别扭,我把它改成了js来写。

reactjs-a-guide-for-rails-developers

改写成之后的源码在下面:

accounts-react

3. react_on_rails

react_on_rails也是一个gem,它能解决react-rails那个包管理的问题,它默认情况下是用webpack来管理npm包的。除此之外,它默认情况下还集成了redux,并提供了一些helper方法,无论是在view中或controller中使用都很方便。

它还提供了capistrano的脚本代码来方便地让你部署代码的时候来管理npm包。

不得不说,它使用起来比react-rails还是复杂一些的。

你可以生成一个HelloWorld的example来开始使用它。

rails generate react_on_rails:install

它的一个缺点就是你必须按照它的规则来写一些组件,语法也是它规定好的,特别是入口文件那里,比如要先注册一个组件

// client/app/bundles/Spd/startup/clientRegistration.jsx
import ReactOnRails from 'react-on-rails'
import Routers from './RoutersClient'

// This is how react_on_rails can see the HelloWorldApp in the browser.
ReactOnRails.register({ Routers })

然后Routers的内容是这样的:

// client/app/bundles/Spd/startup/RoutersClient.jsx
import React from 'react'
import Spd from '../containers/Spd'
import { render } from 'react-dom'
import { Router, Route, Link, hashHistory, IndexRoute } from 'react-router'
import RegionalDesign from '../components/RegionalDesign'

export default (props) => (
  <Router handler={Spd} history={hashHistory}>
    <Route path="/" component={Spd}>
      <Route path="/regional_design/:id" component={RegionalDesign} />
    </Route>
  </Router>
)

最后在view层使用它。

<%= react_component("Routers",
                     props: {},
                     prerender: false) %>

这在某种程度上很限制。但熟悉的话,还是无关紧要的。毕竟影响的东西并不多,其他的组件还是按照正常的规则写就好了。

4. 总结

如果只是在rails中少量使用react的话,我还是建议前面的两种方法,如果特别重前端,大量使用react,或者要让前端开发人员参与进来的话,我还是推荐使用正常的react开发,比如用react的脚手架生成一个项目来进行开发,这样比较方便点。

相关资源