最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - structure of a Backbone and React single page app - Stack Overflow

programmeradmin7浏览0评论

I've been using backbone.js for most of my frontend JavaScript projects so far, but after hearing about Facebook's react.js I got interested and started poking around.

I'm wondering whether or not I'm supposed to use the Backbone.View class anymore or replace every "view" with a react "ponent" - even the "base-view" that's layouting the page ...

I found some posts in the interwebs that still used Backbone.Views - others I stumbled upon only created React-classes.

  • .html
  • /
  • .html

Maybe someone can point me in the right direction ... what to use when and how to best implement multiple "pages/states" in single page app and not just the usual (I can stand it anymore) TODO example.

Here some code that I came up with:

Backbone init stuff:

require(
  [
    "jsx!app/view/base",
    "react",
    "app/router",
    "backbone"
  ],
  function (BaseView, React, Router, Backbone) {
    "use strict";

    var router = new Router();
    var base = new BaseView({router: router});

    React.renderComponent(base, document.getElementById("page"));

    router.on("route", function(action) {
      base.setProps({path: action});
    });

    Backbone.history.start({pushState: true});
  }
);

app/router:

define(function(require) {

  "use strict";

  var Backbone = require("backbone");

  /**
   *
   */
  var Router = Backbone.Router.extend({
    routes: {
      "": "home",
      "test": "test",
      "*error": "404"
    }
  }); // end Router


  return Router;
});

app/view/base.jsx:

define(function(require) {

  "use strict";

  var React = require("react");

  var mixins = require("app/utils/mixins");

  var Header = require("jsx!app/view/header");
  var ContentHome = require("jsx!app/view/content_home");
  var ContentTest = require("jsx!app/view/content_test");
  var ContentLogin = require("jsx!app/view/content_login");

  /**
   *
   */
  var BaseView = React.createClass({

    render: function() {
      var content;

      switch (this.props.path) {
        case "home":
          content = <ContentHome />
          break;
        case "test":
          content = <ContentTest />
          break;
        case "login":
          content = <ContentLogin />
          break;

        case "404":
        default:
          content = "Error, page not found";
          break;
      } 

      return (
        <div id="base" onClick={this.onClick}>
          <Header />
          {content}
        </div>
      );
    },

    onClick: function(event) {
      if (event.target.tagName.toLowerCase() === "a" &&
          event.target.className === "main") {
        event.preventDefault();
        this.props.router.navigate(event.target.pathname, {trigger: true});
      }
    }

  }); // end BaseView

  return BaseView;
});

But I'm not pletely pleased with this setup. Any input is wele.

I've been using backbone.js for most of my frontend JavaScript projects so far, but after hearing about Facebook's react.js I got interested and started poking around.

I'm wondering whether or not I'm supposed to use the Backbone.View class anymore or replace every "view" with a react "ponent" - even the "base-view" that's layouting the page ...

I found some posts in the interwebs that still used Backbone.Views - others I stumbled upon only created React-classes.

  • http://www.thomasboyt./2013/12/17/using-reactjs-as-a-backbone-view.html
  • https://usepropeller./blog/posts/from-backbone-to-react/
  • http://blog.mayflower.de/3937-Backbone-React.html
  • https://medium./react-tutorials

Maybe someone can point me in the right direction ... what to use when and how to best implement multiple "pages/states" in single page app and not just the usual (I can stand it anymore) TODO example.

Here some code that I came up with:

Backbone init stuff:

require(
  [
    "jsx!app/view/base",
    "react",
    "app/router",
    "backbone"
  ],
  function (BaseView, React, Router, Backbone) {
    "use strict";

    var router = new Router();
    var base = new BaseView({router: router});

    React.renderComponent(base, document.getElementById("page"));

    router.on("route", function(action) {
      base.setProps({path: action});
    });

    Backbone.history.start({pushState: true});
  }
);

app/router:

define(function(require) {

  "use strict";

  var Backbone = require("backbone");

  /**
   *
   */
  var Router = Backbone.Router.extend({
    routes: {
      "": "home",
      "test": "test",
      "*error": "404"
    }
  }); // end Router


  return Router;
});

app/view/base.jsx:

define(function(require) {

  "use strict";

  var React = require("react");

  var mixins = require("app/utils/mixins");

  var Header = require("jsx!app/view/header");
  var ContentHome = require("jsx!app/view/content_home");
  var ContentTest = require("jsx!app/view/content_test");
  var ContentLogin = require("jsx!app/view/content_login");

  /**
   *
   */
  var BaseView = React.createClass({

    render: function() {
      var content;

      switch (this.props.path) {
        case "home":
          content = <ContentHome />
          break;
        case "test":
          content = <ContentTest />
          break;
        case "login":
          content = <ContentLogin />
          break;

        case "404":
        default:
          content = "Error, page not found";
          break;
      } 

      return (
        <div id="base" onClick={this.onClick}>
          <Header />
          {content}
        </div>
      );
    },

    onClick: function(event) {
      if (event.target.tagName.toLowerCase() === "a" &&
          event.target.className === "main") {
        event.preventDefault();
        this.props.router.navigate(event.target.pathname, {trigger: true});
      }
    }

  }); // end BaseView

  return BaseView;
});

But I'm not pletely pleased with this setup. Any input is wele.

Share Improve this question edited Feb 27, 2014 at 11:04 Philipp Kyeck asked Feb 26, 2014 at 20:55 Philipp KyeckPhilipp Kyeck 18.9k19 gold badges88 silver badges125 bronze badges 2
  • I wrote a similar answer here: stackoverflow./a/22063571/960178. Tell me if that helps? – chenglou Commented Feb 27, 2014 at 9:06
  • thanks for the link - your answer looks pretty much like my approach. – Philipp Kyeck Commented Feb 27, 2014 at 10:26
Add a ment  | 

2 Answers 2

Reset to default 2

Don't hold a reference to a ponent like you are. If needed use refs or better yet, just render the ponent in the callback. React will check if it needs to update the DOM.

require(
  [
    "jsx!app/view/base",
    "react",
    "backbone"
  ],
  function (BaseView, React, Backbone) {
    "use strict";

    var router = Backbone.Router.extend({
      routes: {
        "": "home",
        "test": "test",
        "login": "login",
        "*error": "404"
      }
    }).on('route', function(action) {
      React.renderComponent(
        <BaseView router={router} path={action} />,
        document.getElementById("page")
      );
    });

    Backbone.history.start({pushState: true});
  }
);

Edit: Since the logic in BaseView is very coupeld to the logic in Router, it makes most sense to keep them in the same file.

var BaseView = React.createClass({
  render: function() {
    return (
      <div id="base" onClick={this.onClick}>
        <Header />
        {this.props.children}
      </div>
    );
  },

  onClick: function(event) {
    if (event.target.tagName.toLowerCase() !== "a") return;
    if (event.target.className !== "main") return;

    event.preventDefault();
    this.props.router.navigate(event.target.pathname, {trigger: true});
  }
});

app/router:

var router = Backbone.Router.extend({
  routes: {
    "": "home",
    "test": "test",
    "login": "login",
    "*error": "404"
  }
}).on('route', function(action) {
  var pathMapping = {
    "home": ContentHome,
    "test": ContentTest,
    "login": ContentLogin
  };
  var Content = pathMapping[action] || Content404;

  React.renderComponent(
    <BaseView router={router}>
      <Content />
    </BaseView>,
    document.getElementById("page")
  );
});

Backbone.history.start({pushState: true});
  var BaseView = React.createClass({
    pathToComponent: function(){
        var paths = {
             'home': ContentHome,
             'login': ContentLogin
        };
        return paths[path] || Content404
    },
    render: function() {
      var ContentComponent = this.pathToComponent(this.props.path);
      return (
        <div id="base" onClick={this.onClick}>
          <Header />
          <ContentComponent />
        </div>
      );
    },

  }); // end BaseView

  return BaseView;
});
发布评论

评论列表(0)

  1. 暂无评论