使用React.js组件作为Backbone.js视图
发布在使用React.js开发web应用2015年8月7日view:22069MVVMReact
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

enter image description here

使用React.js组件作为Backbone.js视图

作为目前最为流行的MVC框架之一,Backbone体积小,上手简单的特性受到了很多前端工程师的青睐。但是和其他框架例如Ember.js或者Angular.js相比,Backbone还是略显简陋了一些。总的来说,Backbone只是为你的代码提供了一个简单的框架。其中包括模型(Model),集合(Collection),以及视图(View)三个主要模块,其中的视图不仅承担了展示数据的任务,同时还需要负责用户和应用之间的交互(例如对UI中的事件如click做出相应)。可以说,在Backbone中,MVC三分部分中的V和C都由View来负责处理。

View虽然承担着如此重要的任务,但是在Backbone的三个主要模块中,它确是最少被设计的一部分。和Ember.js的组件和AngularJS的指令相比,它缺少很多将数据和视图层相关联的钩子函数,也因此在编写应用时非常容易在View的部分编写出凌乱的代码。

于是,在编写Backbone应用,尤其是大型应用时,我们希望借助一些辅助工具或者库对Backbone的视图层进行一些优化。而最近非常火热的React.js就是一个非常不错的选择。

React.js简介

React.js是一个来自Facebook的开源JS库,它的初衷是用于创建”独立的视图组件”。根本上来说,它和AngularJS的指令或者Polymer的web组件很相似。一个React组件本质上来说就是一个拥有自己作用域的DOM元素。它不能够直接和你的应用中的其他部分进行交互,无论是JavaScript代码还是DOM。

React中最独特的一个部分是它使用了JSX,它能够将同代码一起编写的HTML转化成可解析的JavaScript代码。下面就是一个关于React组件中使用JSX的一个例子,下面的代码将会渲染成一个链接:

/** @jsx React.DOM */
var component = React.createClass({
render: function() {
    return <a href="http://venmo.com">Venmo</a>
}
});

它将会被转化成为下面的代码:

/** @jsx React.DOM */
var component = React.createClass({
render: function() {
    return React.DOM.a( {href:"http://venmo.com"}, "Venmo")
}
}); 

将JSX整合到你的工作流中非常的容易,你只需要使用下面这些工具:

  • require-jsx:一个用于加载JSX文件的RequireJS插件
  • reactify: 一个用于转换JSX文件的Browserify工具
  • grunt-react:通过Grunt来编译JSX工具

当然,JSX只是一个选择之一 – 如果你喜欢使用React.DOM领域特定语言(DSL)的话也可以,尽管我在此还是强烈推荐使用JSX。

在本文中我们不会介绍React的基本用法,因为React文档中已经有非常优秀的教程

从一个Backbone的视图中渲染一个组件

现在我们来创建一个非常基本的组件:一个在点击时会触发一个事件的链接。我们现在想做的事情是将这个组件作为一个Backbone视图的一个部分,而不是直接来使用这个组件。这个组件创建起来非常容易:

    var MyWidget = React.createClass({
  handleClick: function() {
    alert('Hello!');
  },
  render: function() {
    return (
      <a href="#" onClick={this.handleClick}>Do something!</a>
    );
  }
    });

这个例子和前面的例子几乎没有什么区别,除了在其中我们添加了一个handleClick处理函数用来处理链接点击事件。现在,我们需要做的事情是添加一个Backbone视图来渲染这个组件:

    var MyView = Backbone.View.extend({
  el: 'body',
  template: '<div class="widget-container"></div>',
  render: function() {
    this.$el.html(this.template);
    React.renderComponent(new MyWidget(), this.$('.widget-container').get(0));
    return this;
  }
    });

    new MyView().render();

组件到Backbone的通信

当然,为了真正利用好React组件,我们需要在有变化发生时在React和Backbone之间进行通信。假设我们想要在链接被点击时展示一些文本。不止如此,我们想要组件的DOM元素之外展示这些文本。

尽管React的文档在解释如何在不同组件通信已经非常完善,一个子React组件如何同一个Backbone视图之间进行通信却并未在文档中提及。然而,在此有一种非常那个简单的方式:我们可以通过一个事件的属性绑定一个事件处理器。

下面的这个例子就实践了这个模式,以jSX的方式:

function anEventHandler() { ... }
React.RenderComponent(<MyComponent customHandler={anEventHandler} />,this.$('body').get(0));

我们可以在Backbone视图中做同样的事情,但是在这里我们不使用JSX,而是使用React这个类:

    var MyView = Backbone.View.extend({
  el: 'body',
  template: '<div class="widget-container"></div>' +
            '<div class="outside-container"></div>',
  render: function() {
    this.$el.html(this.template);

    React.renderComponent(new MyWidget({
      handleClick: this.clickHandler.bind(this)
    }), this.$('.widget-container').get(0));

    return this;
  },
  clickHandler: function() {
    this.$(".outside-container").html("The link was clicked!");
  }
    });

在这个组件中,我们为onClick绑定一个新的事件处理器:

    var MyWidget = React.createClass({
  render: function() {
    return (
      <a href="#" onClick={this.props.handleClick}>Do something!</a>
    );
  }
    });

再次申明,这个是一个非常普通的例子,但是通过这个例子我们不难将这种方式运用到现实的例子中。

例如,在Venmo中,我们使用React重新编写了”链接到Facebook”的按钮。实际的Facebook API调用发生在组件中,但是包含组件的Backbone视图将许多处理器绑定到了组件的事件中。这些事件本质上来说就是组件的”公共API”。React可以在事件处理器中传递参数,因此当一个用户和Facebook进行连接时,Backbone视图可以获取到用户的Facebook ID并将它绑定到用户模型中。

Backbone到组件的通信

既然现在我们已经了解到了组件到Backbone的视图如何通信,下一步要做的事情就是学会如何从一个Backbone的模型更新组件的状态 – 举个例子,我们想要编写一个视图,这个视图可以依据一个模型的字段变化进行响应。

首先,我们来创建一个Model类:

    var ExampleModel = Backbone.Model.extend({
  defaults: {
    name: 'Backbone.View'
  }
    });

然后创建一个简单的React组件来展示name字段:

    var DisplayView = React.createClass({
  render: function() {
    return (
      <p>
        {this.props.model.get('name')}
      </p>
    );
  }
    });

然而,这个组件本身并不会针对模型字段的变化做出响应。因此,我们需要为模型的change事件添加一个监听器来告诉组件应该重新渲染:

    var DisplayView = React.createClass({
  componentDidMount: function() {
    this.props.model.on('change', function() {
      this.forceUpdate();
    }.bind(this));
  },

  render: function() {
    // ...
  }
    });

接着,我们添加另一个组件,这个组件将会真正的改变name字段:

var ToggleView = React.createClass({
  handleClick: function() {
    this.props.model.set('name', 'React');
  },
  render: function() {
    return (
      <button onClick={this.handleClick}>
        model.set('name', 'React');
      </button>
    );
  }
    });

最终,我们创建一个模型,同时使用JSX来渲染所有的组件:

var model = new ExampleModel();

React.renderComponent((
<div>
    <DisplayView model={model} />
    <ToggleView model={model} />
</div>
), document.body);

总结

Backbone+React实在是一个非常不错的组合,虽然现在React还不是很成熟,但是它依然非常值得期待。它使得我们可以轻松的分享和重用组件。如果你还没有使用过React,现在不妨去试一试。


本文参考自Using React components as Backbone Views,原文地址http://www.thomasboyt.com/2013/12/17/using-reactjs-as-a-backbone-view.html

评论
发表评论
2年前
添加了一枚【评注】:这个位置不错
2年前

http://light.hs.net 基于backbone实现MVC

3年前
添加了一枚【评注】:错别字。哈哈
3年前
赞了此文章!
3年前
赞了此文章!
3年前
添加了一枚【评注】:test
3年前
添加了一枚【评注】:test
3年前
添加了一枚【评注】:哈哈,这也能评论
3年前
添加了一枚【评注】:为什么不能删除,都看不见代码了???????????
3年前
添加了一枚【评注】:不能取消……
3年前
添加了一枚【评注】:我擦
3年前
添加了一枚【评注】:我擦
3年前
添加了一枚【评注】:尼玛啊 ,我有密集恐惧症~~
3年前

新的思维方式 很赞

3年前
添加了一枚【评注】:太过分了
3年前
添加了一枚【评注】:素质低下的垃圾为何这么多?
3年前

我完全看不清了

3年前
添加了一枚【评注】:b
3年前
添加了一枚【评注】:a
3年前
添加了一枚【评注】:e
3年前
添加了一枚【评注】:ni mei a ...
3年前

丧心病狂的评注

3年前
添加了一枚【评注】:覆盖
3年前
添加了一枚【评注】:盖住
3年前
添加了一枚【评注】:盖住
3年前
添加了一枚【评注】:盖住
3年前
添加了一枚【评注】:得到
3年前
添加了一枚【评注】:我去
3年前
添加了一枚【评注】:都盖住吧
3年前
添加了一枚【评注】:都盖住吧
3年前
添加了一枚【评注】:这么晚都还不睡
3年前
添加了一枚【评注】:这代码盖的。。
3年前
添加了一枚【评注】:还让不让人看了
3年前
添加了一枚【评注】:还让不让人看了
3年前
添加了一枚【评注】:还让不让人看了
3年前
添加了一枚【评注】:还让不让人看了
3年前
添加了一枚【评注】:还让不让人看了
3年前
添加了一枚【评注】:测试
3年前
添加了一枚【评注】:覆盖代码测试
3年前
添加了一枚【评注】:覆盖代码测试
3年前
添加了一枚【评注】:万一把代码全都覆盖掉了怎么办?
3年前
添加了一枚【评注】:?
3年前
添加了一枚【评注】:444444444444
3年前
添加了一枚【评注】:333333333
3年前
添加了一枚【评注】:22222
3年前
添加了一枚【评注】:1111111111111111
3年前
添加了一枚【评注】:试试会不会起鸡皮疙瘩
3年前
赞了此文章!
3年前
赞了此文章!
3年前
添加了一枚【评注】:起鸡皮疙瘩
WRITTEN BY
张小俊128
Intern in Baidu mobile search department。认真工作,努力钻研,期待未来更多可能。
TA的新浪微博
PUBLISHED IN
使用React.js开发web应用

介绍React.js库使用的基础知识

我的收藏