Javascript 在多页应用中使用 React

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31933359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:25:27  来源:igfitidea点击:

Using React in a multi-page app

javascriptnode.jsreactjs

提问by Jose Carrillo

I have been playing around with React and so far I really like it. I am building an app with NodeJS and would like to use React for some of the interactive components across the application. I do not want to make it single page app.

我一直在玩 React,到目前为止我真的很喜欢它。我正在使用 NodeJS 构建一个应用程序,并希望将 React 用于整个应用程序中的一些交互式组件。我不想让它成为单页应用程序。

I haven't yet found anything on the web that answer the following questions:

我还没有在网上找到任何可以回答以下问题的内容:

How do I break up or bundle my React components across a multi-page app?

如何在多页应用程序中拆分或捆绑我的 React 组件?

Currently all my components are in one file even though I may never load them in some sections of the app.

目前我所有的组件都在一个文件中,即使我可能永远不会在应用程序的某些部分加载它们。

So far I am trying using conditional statements to render components by searching for the ID of the container where React will render. I am not 100% sure of what the best practices are with React. It looks something like this.

到目前为止,我正在尝试使用条件语句通过搜索 React 将呈现的容器的 ID 来呈现组件。我不是 100% 确定 React 的最佳实践是什么。它看起来像这样。

if(document.getElementById('a-compenent-in-page-1')) {
    React.render(
        <AnimalBox url="/api/birds" />,
        document.getElementById('a-compenent-in-page-1')
    );
}

if(document.getElementById('a-compenent-in-page-2')) {
    React.render(
        <AnimalBox url="/api/cats" />,
        document.getElementById('a-compenent-in-page-2')
    );
}

if(document.getElementById('a-compenent-in-page-3')) {
    React.render(
        <AnimalSearchBox url="/api/search/:term" />,
        document.getElementById('a-compenent-in-page-3')
    );
}

I am still reading the documentation and haven't found what I need yet for a multi page app.

我仍在阅读文档,但还没有找到我需要的多页应用程序。

Thanks in advance.

提前致谢。

采纳答案by webdeb

Currently, I am doing something similar.

目前,我正在做类似的事情。

The application is not a full React App, I am using React for dynamic Stuff, like CommentBox, which is autark. And can be included at any Point with special params..

该应用程序不是一个完整的 React 应用程序,我使用 React 来处理动态的东西,比如 CommentBox,它是自给自足的。并且可以包含在具有特殊参数的任何点上..

However, all my sub Apps are loaded and included into a single file all.js, so it can be cached by the browser across pages.

但是,我所有的子应用程序都被加载并包含在一个文件中all.js,因此它可以被浏览器跨页面缓存。

When I need to include an App into the SSR Templates, I just have to include a DIV with the class "__react-root" and a special ID, ( the name of the React App to be rendered )

当我需要在 SSR 模板中包含一个应用程序时,我只需要包含一个带有“__react-root”类的 DIV 和一个特殊的 ID,(要呈现的 React 应用程序的名称)

The logic is really simple:

逻辑其实很简单:

import CommentBox from './apps/CommentBox';
import OtherApp from './apps/OtherApp';

const APPS = {
  CommentBox,
  OtherApp
};

function renderAppInElement(el) {
  var App = APPS[el.id];
  if (!App) return;

  // get props from elements data attribute, like the post_id
  const props = Object.assign({}, el.dataset);

  ReactDOM.render(<App {...props} />, el);
}

document
  .querySelectorAll('.__react-root')
  .forEach(renderAppInElement)


<div>Some Article</div>
<div id="CommentBox" data-post_id="10" class="__react-root"></div>

<script src="/all.js"></script>

Edit

编辑

Since webpack perfectly supports code-splitting & LazyLoading, I thought it make sense to include an example where you don't need to load all your apps in one bundle, but split them up and load on demand.

由于 webpack 完美支持代码拆分和 LazyLoading,我认为包含一个示例是有意义的,您不需要将所有应用程序加载到一个包中,而是将它们拆分并按需加载。

import React from 'react';
import ReactDOM from 'react-dom';

const apps = {
  'One': () => import('./One'),
  'Two': () => import('./Two'),
}

const renderAppInElement = (el) => {
  if (apps[el.id])  {
    apps[el.id]().then((App) => {
      ReactDOM.render(<App {...el.dataset} />, el);
    });
  }
}

回答by Cocomico

You can provide several entry points for the application in the webpack.config.js file:

您可以在 webpack.config.js 文件中为应用程序提供多个入口点:

var config = {
  entry: {
    home: path.resolve(__dirname, './src/main'),
    page1: path.resolve(__dirname, './src/page1'),
    page2: path.resolve(__dirname, './src/page2'),
    vendors: ['react']
  },
 output: {
    path: path.join(__dirname, 'js'),
    filename: '[name].bundle.js',
    chunkFilename: '[id].chunk.js'
  },
}

then you can have in your src folder three different html files with their respective js files (example for page1):

那么你可以在你的 src 文件夹中拥有三个不同的 html 文件以及它们各自的 js 文件(例如 page1):

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
</head>
<body>
  <div id="app"></div>
  <script src="./vendors.js"></script>
  <script src="./page1.bundle.js"></script>
</body>
</html>

JavaScript file:

JavaScript 文件:

import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import ComponentA from './components/ReactComponentA'
ReactDom.render(<div>
                  <App title='page1' />
                  <ReactComponentA/>
                 </div>, document.getElementById('app'))

Different React components can be then loaded for each single page.

然后可以为每个页面加载不同的 React 组件。

回答by Scott

I'm building an application from the ground up and am learning as I go, but I think what you are looking for is React-Router. React-Router maps your components to specific URLs. For example:

我正在从头开始构建一个应用程序,并且正在学习,但我认为您正在寻找的是React-Router。React-Router 将您的组件映射到特定的 URL。例如:

render((
    <Router>
        <Route path="/" component={App}>
            <Route path="api/animals" component={Animals}>
               <Route path="birds" component={Birds}/>
               <Route path="cats" component={Cats}/>
            </Route>
        </Route>
        <Route path="api/search:term" component={AnimalSearchBox}>
    </Router>
), document.body)

In the search case, 'term' is accessible as a property in the AnimalSearchBox:

在搜索案例中,'term' 可以作为 AnimalSearchBox 中的一个属性访问:

componentDidMount() {
    // from the path `/api/search/:term`
    const term = this.props.params.term
}

Try it out. Thistutorial is the one that put me over the top in terms of my understanding of this and other related topics.

试试看。 就我对这个主题和其他相关主题的理解而言,教程使我处于领先地位。



Original answer follows:

原答案如下:

I found my way here looking for the same answer. See if thispost inspires you. If your application is anything like mine, it will have areas that change very little and varies only in the main body. You could create a widget whose responsibility it is to render a different widget based upon the state of the application. Using a flux architecture, you could dispatch a navigation action that changes the state your body widget switches upon, effectively updating the body of the page only.

我在这里找到了寻找相同答案的方法。看看这篇文章是否对你有所启发。如果您的应用程序与我的应用程序类似,那么它的区域变化很小,并且仅在主体部分有所不同。您可以创建一个小部件,其职责是根据应用程序的状态呈现不同的小部件。使用 Flux 架构,您可以调度一个导航操作来更改您的正文小部件切换的状态,从而仅有效地更新页面的正文。

That's the approach I'm attempting now.

这就是我现在正在尝试的方法。

回答by jennas

Are you using a CMS? They tend to like changing urls which could break your application.

您使用的是 CMS 吗?他们往往喜欢更改可能会破坏您的应用程序的 url。

Another way is using something like React Habitat.

另一种方法是使用React Habitat 之类的东西。

With it, you can register components and they automatically get exposed to the dom.

有了它,你可以注册组件,它们会自动暴露给 dom。

Example

例子

Register component(s):

注册组件:

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

Then they are availiable in your dom like this:

然后它们在您的 dom 中可用,如下所示:

<div data-component="AnimalBox"></div>

<div data-component="AnimalSearchBox"></div>

The above will be automatically replaced with your react components.

以上将自动替换为您的反应组件。

You can then automatically pass properties (or props) to your components too:

然后,您也可以自动将属性(或道具)传递给您的组件:

<div data-component="AnimalBox" data-prop-size="small"></div>

This will expose sizeas a prop to your component. There are additional optionsfor passing other types such as json, array's, ints, floats etc.

这将size作为一个道具暴露给你的组件。还有其他选项可以传递其他类型,例如 json、数组、整数、浮点数等。

回答by Przemek Nowicki

I know it's been a while since this question was asked but hopefully this helps someone.

我知道这个问题已经有一段时间了,但希望这对某人有所帮助。

As @Cocomico mentioned you could provide several entry points for the application in the webpack.config.js file. If you are looking for a simple Webpack setup (based on the idea of multiple entry points) that allows you to add React components to static pages you may consider using this: https://github.com/przemek-nowicki/multi-page-app-with-react

正如@Cocomico 提到的,您可以在 webpack.config.js 文件中为应用程序提供多个入口点。如果您正在寻找一个简单的 Webpack 设置(基于多个入口点的想法),允许您将 React 组件添加到静态页面,您可以考虑使用这个:https: //github.com/przemek-nowicki/multi-page -app-with-react

回答by Agu Dondo

I suggest you take a look at InertiaJS: https://inertiajs.com/

我建议你看看 InertiaJS:https://inertiajs.com/

With Inertia you build apps just like you've always done with your server-side web framework of choice. You use your framework's existing functionality for routing, controllers, middleware, authentication, authorization, data fetching, and more.

The only thing that's different is your view layer. Instead of using server-side rendering (eg. Blade or ERB templates), the views are JavaScript page components. This allows you to build your entire front-end using React, Vue or Svelte.

使用 Inertia,您可以像使用您选择的服务器端 Web 框架一样构建应用程序。您将框架的现有功能用于路由、控制器、中间件、身份验证、授权、数据获取等。

唯一不同的是您的视图层。视图不是使用服务器端渲染(例如 Blade 或 ERB 模板),而是 JavaScript 页面组件。这允许您使用 React、Vue 或 Svelte 构建整个前端。