Подтвердить что ты не робот

React.js: как отделить jsx от JavaScript

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

4b9b3361

Ответ 1

Вот шаблон для разделения шаблона 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: включено предложение в Damon Smith ответить на установку this в функции шаблона для компонента React.

Обновление 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>
  );
};

Ответ 2

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

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

Ответ 3

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

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

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

render: function() {
    return myTemplate;
}

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

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

то в вашей функции рендеринга компонента вам необходимо привязать его к 'this' правильно, а затем вызвать его, например:

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

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

Ответ 4

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

template.js

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

мой-component.js

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

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

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

Ответ 5

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

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

Примечание. Тег script для component.js должен появиться перед тегом script для main.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);