Как разрешить HTML-шаблонам определять компоненты React так же, как Vue? - PullRequest
0 голосов
/ 11 мая 2019

В Vue у вас может быть что-то вроде.

<!-- index.php -->

<div id="app">
    <section>
        <main>
            <h1>Main</h1>
            <some-component></some-component>
        </main>
        <aside>
            <h2>Side</h2>
            <another-component></another-component>
        </aside>
    </section>
</div>

<script>
    Vue.component('some-component', { template: '<div>hello - {{ this.$parent.test }}</div>' });
    Vue.component('another-component', { template: '<div>world - {{ this.$parent.test }}</div>' });

    new Vue({el: '#app', data: () => ({test: 123})});
</script>

, которое будет рендерить все зарегистрированные компоненты, и вы получите что-то вроде

<div id="app">
    <section>
        <main>
            <h1>Main</h1>
            <div>hello - 123</div>
        </main>
        <aside>
            <h2>Side</h2>
            <div>world - 123</div>
        </aside>
    </section>
</div>

Как можноТо же самое можно сделать с помощью React?

Я пробовал глупые вещи, такие как

class App extends Component {
    render() {
        return <div>{this.props.kids}</div>
    }
}


if (document.getElementById('app')) {
    ReactDOM.render(<App kids={document.getElementById('app').innerHTML)} />, document.getElementById('app'));
}

Общая цель - иметь возможность иметь нормальные шаблоны HTML, а затем разбрасывать различные реакции.компоненты повсюду, где это необходимо.

В идеале он должен содержаться в одном компоненте, не похожем на рендер, который может предоставлять глобальные данные, используя контекстный интерфейс API.

Ответы [ 2 ]

0 голосов
/ 11 мая 2019

React не основан на шаблонах, но использует JS или JSX для определения компонентов, поэтому возможности ограничены.

Предпочтительнее

Можно отображать фрагменты HTML с помощью dangerouslySetInnerHTML:

<div dangerouslySetInnerHTML={this.props.kids}/>

Это не позволяет использовать пользовательские компоненты внутри фрагментов, потому что компоненты React не используют селекторы. Может быть возможно проанализировать шаблон с анализатором HTML в иерархии элементов React, а затем заменить пользовательские элементы, такие как <some-component>, на соответствующие компоненты React, как показано в в этом вопросе .

Можно определять и переносить компоненты на лету, но это не рекомендуется при производстве:

<script src="https://unpkg.com/babel-standalone/babel.js"></script>
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script type="text/babel">
  var Foo = () => 'Foo';
</script>
...
<script type="text/babel">
  ReactDOM.render(<Foo/>, document.getElementById('foo'));
</script>

Чтобы использовать контекстный API для нескольких компонентов, они должны отображаться не как корневые компоненты с render, а внутри общего родителя, например, как порталы с createPortal:

...
<script>
  var portals = {};
</script>
...
<script type="text/babel">
  portals['#foo'] = <Foo/>;
</script>
...
<script type="text/babel">
  // runs on page load
  var CommonContext = ...;
  var Root = () => (
    <CommonContext.Provider value={...}>
      {Object.entries(portals).map(({ selector, child }) => (
        ReactDOM.createPortal(child, document.querySelector(selector))
      )}
    </CommonContext.Provider>      
  );

  ReactDOM.render(<Root/>, document.getElementById('root'));
</script>
0 голосов
/ 11 мая 2019

Я не вижу смысла в использовании React, если вы хотите vue / angular-подобные шаблоны, используйте вместо этого vue. React использует javascript xml или jsx, если хотите, которые выглядят как шаблоны, но на самом деле дают вам все преимущества javascript.

Хотя, если вы хотите все в одном компоненте, ничто не мешает вам сделать это.

Теперь, если вы имели в виду, что вам нужен один компонент, который отображает все дочерние элементы, вы не за горами. Вот простой пример из codeburst

const Picture = (props) => {
  return (
    <div>
      <img src={props.src}/>
      {props.children}
    </div>
  )
}


render () {
  return (
    <div className='container'>
      <Picture src={picture.src}>
          //what is placed here is passed as props.children  
      </Picture>
    </div>
  )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...