Реагировать.js: как отделить jsx от JavaScript


есть ли способ переместить jsx из функции рендеринга компонента в отдельный файл? Если да, то как я могу ссылаться на jsx в функции render?

5 52

5 ответов:

вот шаблон для разделения шаблона jsx, который использует модули CommonJS в NodeJS, Browserify или Webpack. В NodeJS я нашел модуль node-jsx полезным, чтобы избежать необходимости компилировать JSX.

// index.js
require('node-jsx').install({extension: '.jsx'});
var React = require('react'),
    Component = require('./your-component');


// your-component.jsx
var YourComponent,
    React = require('react'),
    template = require('./templates/your-component.jsx');

module.exports = YourComponent = React.createClass({
  render: function() {
    return template.call(this);
  }
});


// templates/your-component.jsx
/** @jsx React.DOM */
var React = require('react');

module.exports = function() {

  return (
    <div>
      Your template content.
    </div>
  );

};

обновление 2015-1-30: включено предложение в ответ Деймона Смита установить this в функции шаблона для компонента реакции.

обновление 12/2016: текущая передовая практика заключается в использовании .расширение js и использование инструмента сборки, такого как Babel для вывода окончательный JavaScript из вашего источника. Взгляните на create-react-app если вы только начали. Кроме того, последние рекомендации React рекомендуют разделение между компонентами, которые управляют состоянием (обычно называемыми "компонентами контейнера"), и компонентами, которые являются презентационными. Эти презентационные компоненты теперь могут быть записаны как функции, поэтому они не далеки от функции шаблона, используемой в предыдущем примере. Вот как я бы рекомендовал развязать большую часть презентационный код JSX теперь. Эти примеры все еще используют ES5 React.createClass() синтаксис.

// index.js
var React = require('react'),
    ReactDOM = require('react-dom'),
    YourComponent = require('./your-component');

ReactDOM.render(
  React.createElement(YourComponent, {}, null),
  document.getElementById('root')
);

// your-component.js
var React = require('react'),
    YourComponentTemplate = require('./templates/your-component');

var YourComponentContainer = React.createClass({
  getInitialState: function() {
    return {
      color: 'green'
    };
  },

  toggleColor: function() {
    this.setState({
      color: this.state.color === 'green' ? 'blue' : 'green'
    });
  },

  render: function() {
    var componentProps = {
      color: this.state.color,
      onClick: this.toggleColor
    };
    return <YourComponentTemplate {...componentProps} />;
  }
});

module.exports = YourComponentContainer;

// templates/your-component.js
var React = require('react');

module.exports = function YourComponentTemplate(props) {
  return (
    <div style={{color: props.color}} onClick={props.onClick}>
      Your template content.
    </div>
  );
};

можно использовать react-templates. Это дает вам именно такое разделение между разметкой и самим компонентом и многое другое.

Я нашел его очень полезным для моих нужд (крупномасштабное веб-приложение).

одна проблема с перемещением шаблонов в отдельный файл заключается в том, что если вы используете обработчики, такие как:

var myTemplate = (
    <form onSubmit={this.handleSubmit}></form>
);

и затем в вашем компоненте вы используете:

render: function() {
    return myTemplate;
}

сгенерированный код шаблона вызовет это.handleSubmit (), так что "это" будет неправильно, и обработчики не будут работать. Что вам нужно сделать, это поместить их в функцию, например:

var myTemplate = function() {
    return (
        <form onSubmit={this.handleSubmit}></form>
    );
};

затем в функции рендеринга вашего компонента вам нужно правильно привязать его к "этому", а затем вызвать его, например это:

render: function() {
    return myTemplate.bind(this)();
},

теперь вы можете поместить это определение шаблона в любом месте, в отдельном файле или как вы хотите структурировать и ссылаться на свой собственный код. (сил тебе! Не слушайте эти сумасшедшие предписывающие рамки! :))

Я только что разделил JSX на анонимные функциональные файлы

шаблон.js

export default (component) => {
return <h1>Hello {component.props.name}</h1>
}

мой компонент.js

import React, {Component} from 'react';
import template from './template';

export default MyComponent extends Component {
   render() {
     return template(this);
   }
}

в шаблоне вы можете получить доступ к реквизитам или состояние или функции с помощью component переменной.

если вы не используете какую-либо модульную систему, т. е. полагаетесь на script только теги, просто выставьте свой компонент JSX в глобальной переменной и используйте его, когда вам нужно:

// component.js
var Component = React.createClass({ /* your component */ });
// main.js
React.renderComponent(Component({}), domNode);

Примечание:script тег компонент.js должен предстать перед script тег главная.js.

если вы используете Commonjs-подобную модульную систему, такую как Browserify, просто экспортируйте свое определение компонента и требуйте его, когда вам это нужно.

// component.js
var React = require("react");
module.exports = React.createClass({ /* your component */ });
// main.js
var Component = require("component.js");
React.renderComponent(Component({}), domNode);