2

我创建了一个基本的反应应用程序

npx create-react-app

我可以在 中创建组件,index.js并且可以将它们渲染到index.html.

但是,这也是我可以渲染它们的唯一页面,例如,我不能在login.html页面或任何其他页面上使用相同的组件,除了index.html

我正在用npm start.

4

3 回答 3

3

通常 React 用于单页应用程序,因此您只需在单个页面中渲染应用程序,然后使用路由(与react-routercommon)来模拟浏览器导航。

但是,您可以在多个页面上呈现它...您只需将激活 JavaScript 复制到其他页面上

只需将其复制到您的login.html(取自默认的 create-react-app 输出):

<noscript>
  You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script type="text/javascript" src="/static/js/bundle.js"></script>
于 2018-05-08T13:04:50.850 回答
1

你为什么需要这个?请记住,React 就其自身的性质而言,自称是一个 SPA(单页应用程序)。这应该足以让你明白单页是(应该是)index.html。

无论如何,您可以通过查看由 create-react-app 创建的默认 index.html 文件以及 manifest.json 文件来完成。

从 manifest.json 开始,你应该有这个 JSON:

{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    }
  ],
  "start_url": "./index.html",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}

或者类似的东西。您可以设置一个“start_url”属性,这是 create-react-app webpack dev-server 默认情况下,当您在运行它的本地地址请求任何路径时为您提供服务的起点(通常为 localhost:3000 )。通过更改此属性,您可以使其服务于您想要的页面,例如 login.html。

现在,查看 index.html 默认代码,您应该有如下内容:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>

如您所见,在页面末尾有一个

<div id="root"></div>

这正是 React 渲染 ReactDOM.render(jsx, ElementID) jsx 的地方。事实上,如果你查看 index.js,ReactDOM 就像:

ReactDOM.render(
    <Something />,
, document.getElementByID('root'));

可以看到 ElementID('root') 是要渲染 jsx() 的 div 元素的 id。如果您创建一个新页面,例如 login.html,复制粘贴 index.html 内容并更改元素 ID,然后您可以选择在那里呈现您的内容,同时更改 ReactDOM.render() 的引用 ElementID。处理这个你应该得到你想要的结果,但如前所述,在我看来你不应该需要这个。

于 2018-05-08T13:17:22.720 回答
0

要使用 以外的文件index.html,您需要在 2 个文件中的四个位置进行更改。

这些文件是project_directory\public\manifest.jsonproject_directory\node_modules\react-scripts\config\paths.js

  1. project_directory\public\manifest.json
  • 变更前
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}

  • 改变后
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "./yourNewHtmlFile.html",  // change only this line
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}
  1. project_directory\node_modules\react-scripts\config\paths.js
  • 变更前

      // @remove-on-eject-begin
      /**
       * Copyright (c) 2015-present, Facebook, Inc.
       *
       * This source code is licensed under the MIT license found in the
       * LICENSE file in the root directory of this source tree.
       */
      // @remove-on-eject-end
      'use strict';
    
      const path = require('path');
      const fs = require('fs');
      const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
    
      // Make sure any symlinks in the project folder are resolved:
      // https://github.com/facebook/create-react-app/issues/637
      const appDirectory = fs.realpathSync(process.cwd());
      const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
    
      // We use `PUBLIC_URL` environment variable or "homepage" field to infer
      // "public path" at which the app is served.
      // webpack needs to know it to put the right <script> hrefs into HTML even in
      // single-page apps that may serve index.html for nested URLs like /todos/42.
      // We can't use a relative path in HTML because we don't want to load something
      // like /todos/42/static/js/bundle.7289d.js. We have to know the root.
      const publicUrlOrPath = getPublicUrlOrPath(
      process.env.NODE_ENV === 'development',
      require(resolveApp('package.json')).homepage,
      process.env.PUBLIC_URL
      );
    
      const buildPath = process.env.BUILD_PATH || 'build';
    
      const moduleFileExtensions = [
      'web.mjs',
      'mjs',
      'web.js',
      'js',
      'web.ts',
      'ts',
      'web.tsx',
      'tsx',
      'json',
      'web.jsx',
      'jsx',
      ];
    
      // Resolve file paths in the same order as webpack
      const resolveModule = (resolveFn, filePath) => {
      const extension = moduleFileExtensions.find(extension =>
        fs.existsSync(resolveFn(`${filePath}.${extension}`))
      );
    
      if (extension) {
        return resolveFn(`${filePath}.${extension}`);
      }
    
      return resolveFn(`${filePath}.js`);
      };
    
      // config after eject: we're in ./config/
      module.exports = {
      dotenv: resolveApp('.env'),
      appPath: resolveApp('.'),
      appBuild: resolveApp(buildPath),
      appPublic: resolveApp('public'),
      appHtml: resolveApp('public/index.html'), 
      appIndexJs: resolveModule(resolveApp, 'src/index'),
      appPackageJson: resolveApp('package.json'),
      appSrc: resolveApp('src'),
      appTsConfig: resolveApp('tsconfig.json'),
      appJsConfig: resolveApp('jsconfig.json'),
      yarnLockFile: resolveApp('yarn.lock'),
      testsSetup: resolveModule(resolveApp, 'src/setupTests'),
      proxySetup: resolveApp('src/setupProxy.js'),
      appNodeModules: resolveApp('node_modules'),
      swSrc: resolveModule(resolveApp, 'src/service-worker'),
      publicUrlOrPath,
      };
    
      // @remove-on-eject-begin
      const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath);
    
      // config before eject: we're in ./node_modules/react-scripts/config/
      module.exports = {
      dotenv: resolveApp('.env'),
      appPath: resolveApp('.'),
      appBuild: resolveApp(buildPath),
      appPublic: resolveApp('public'),
      appHtml: resolveApp('public/index.html'),
      appIndexJs: resolveModule(resolveApp, 'src/index'),
      appPackageJson: resolveApp('package.json'),
      appSrc: resolveApp('src'),
      appTsConfig: resolveApp('tsconfig.json'),
      appJsConfig: resolveApp('jsconfig.json'),
      yarnLockFile: resolveApp('yarn.lock'),
      testsSetup: resolveModule(resolveApp, 'src/setupTests'),
      proxySetup: resolveApp('src/setupProxy.js'),
      appNodeModules: resolveApp('node_modules'),
      swSrc: resolveModule(resolveApp, 'src/service-worker'),
      publicUrlOrPath,
      // These properties only exist before ejecting:
      ownPath: resolveOwn('.'),
      ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3
      appTypeDeclarations: resolveApp('src/react-app-env.d.ts'),
      ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'),
      };
    
      const ownPackageJson = require('../package.json');
      const reactScriptsPath = resolveApp(`node_modules/${ownPackageJson.name}`);
      const reactScriptsLinked =
      fs.existsSync(reactScriptsPath) &&
      fs.lstatSync(reactScriptsPath).isSymbolicLink();
    
      // config before publish: we're in ./packages/react-scripts/config/
      if (
      !reactScriptsLinked &&
      __dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1
      ) {
      const templatePath = '../cra-template/template';
      module.exports = {
        dotenv: resolveOwn(`${templatePath}/.env`),
        appPath: resolveApp('.'),
        appBuild: resolveOwn(path.join('../..', buildPath)),
        appPublic: resolveOwn(`${templatePath}/public`),
        appHtml: resolveOwn(`${templatePath}/public/index.html`),
        appIndexJs: resolveModule(resolveOwn, `${templatePath}/src/index`),
        appPackageJson: resolveOwn('package.json'),
        appSrc: resolveOwn(`${templatePath}/src`),
        appTsConfig: resolveOwn(`${templatePath}/tsconfig.json`),
        appJsConfig: resolveOwn(`${templatePath}/jsconfig.json`),
        yarnLockFile: resolveOwn(`${templatePath}/yarn.lock`),
        testsSetup: resolveModule(resolveOwn, `${templatePath}/src/setupTests`),
        proxySetup: resolveOwn(`${templatePath}/src/setupProxy.js`),
        appNodeModules: resolveOwn('node_modules'),
        swSrc: resolveModule(resolveOwn, `${templatePath}/src/service-worker`),
        publicUrlOrPath,
        // These properties only exist before ejecting:
        ownPath: resolveOwn('.'),
        ownNodeModules: resolveOwn('node_modules'),
        appTypeDeclarations: resolveOwn(`${templatePath}/src/react-app-env.d.ts`),
        ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'),
      };
      }
      // @remove-on-eject-end
    
      module.exports.moduleFileExtensions = moduleFileExtensions;
    
  • 改变后

      // @remove-on-eject-begin
      /**
       * Copyright (c) 2015-present, Facebook, Inc.
       *
       * This source code is licensed under the MIT license found in the
       * LICENSE file in the root directory of this source tree.
       */
      // @remove-on-eject-end
      'use strict';
    
      const path = require('path');
      const fs = require('fs');
      const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
    
      // Make sure any symlinks in the project folder are resolved:
      // https://github.com/facebook/create-react-app/issues/637
      const appDirectory = fs.realpathSync(process.cwd());
      const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
    
      // We use `PUBLIC_URL` environment variable or "homepage" field to infer
      // "public path" at which the app is served.
      // webpack needs to know it to put the right <script> hrefs into HTML even in
      // single-page apps that may serve index.html for nested URLs like /todos/42.
      // We can't use a relative path in HTML because we don't want to load something
      // like /todos/42/static/js/bundle.7289d.js. We have to know the root.
      const publicUrlOrPath = getPublicUrlOrPath(
      process.env.NODE_ENV === 'development',
      require(resolveApp('package.json')).homepage,
      process.env.PUBLIC_URL
      );
    
      const buildPath = process.env.BUILD_PATH || 'build';
    
      const moduleFileExtensions = [
      'web.mjs',
      'mjs',
      'web.js',
      'js',
      'web.ts',
      'ts',
      'web.tsx',
      'tsx',
      'json',
      'web.jsx',
      'jsx',
      ];
    
      // Resolve file paths in the same order as webpack
      const resolveModule = (resolveFn, filePath) => {
      const extension = moduleFileExtensions.find(extension =>
        fs.existsSync(resolveFn(`${filePath}.${extension}`))
      );
    
      if (extension) {
        return resolveFn(`${filePath}.${extension}`);
      }
    
      return resolveFn(`${filePath}.js`);
      };
    
      // config after eject: we're in ./config/
      module.exports = {
      dotenv: resolveApp('.env'),
      appPath: resolveApp('.'),
      appBuild: resolveApp(buildPath),
      appPublic: resolveApp('public'),
      appHtml: resolveApp('public/yourNewHtmlFile.html'),  // change this line
      appIndexJs: resolveModule(resolveApp, 'src/index'),
      appPackageJson: resolveApp('package.json'),
      appSrc: resolveApp('src'),
      appTsConfig: resolveApp('tsconfig.json'),
      appJsConfig: resolveApp('jsconfig.json'),
      yarnLockFile: resolveApp('yarn.lock'),
      testsSetup: resolveModule(resolveApp, 'src/setupTests'),
      proxySetup: resolveApp('src/setupProxy.js'),
      appNodeModules: resolveApp('node_modules'),
      swSrc: resolveModule(resolveApp, 'src/service-worker'),
      publicUrlOrPath,
      };
    
      // @remove-on-eject-begin
      const resolveOwn = relativePath => path.resolve(__dirname, '..', relativePath);
    
      // config before eject: we're in ./node_modules/react-scripts/config/
      module.exports = {
      dotenv: resolveApp('.env'),
      appPath: resolveApp('.'),
      appBuild: resolveApp(buildPath),
      appPublic: resolveApp('public'),
      appHtml: resolveApp('public/yourNewHtmlFile.html'),  // change this line
      appIndexJs: resolveModule(resolveApp, 'src/index'),
      appPackageJson: resolveApp('package.json'),
      appSrc: resolveApp('src'),
      appTsConfig: resolveApp('tsconfig.json'),
      appJsConfig: resolveApp('jsconfig.json'),
      yarnLockFile: resolveApp('yarn.lock'),
      testsSetup: resolveModule(resolveApp, 'src/setupTests'),
      proxySetup: resolveApp('src/setupProxy.js'),
      appNodeModules: resolveApp('node_modules'),
      swSrc: resolveModule(resolveApp, 'src/service-worker'),
      publicUrlOrPath,
      // These properties only exist before ejecting:
      ownPath: resolveOwn('.'),
      ownNodeModules: resolveOwn('node_modules'), // This is empty on npm 3
      appTypeDeclarations: resolveApp('src/react-app-env.d.ts'),
      ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'),
      };
    
      const ownPackageJson = require('../package.json');
      const reactScriptsPath = resolveApp(`node_modules/${ownPackageJson.name}`);
      const reactScriptsLinked =
      fs.existsSync(reactScriptsPath) &&
      fs.lstatSync(reactScriptsPath).isSymbolicLink();
    
      // config before publish: we're in ./packages/react-scripts/config/
      if (
      !reactScriptsLinked &&
      __dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1
      ) {
      const templatePath = '../cra-template/template';
      module.exports = {
        dotenv: resolveOwn(`${templatePath}/.env`),
        appPath: resolveApp('.'),
        appBuild: resolveOwn(path.join('../..', buildPath)),
        appPublic: resolveOwn(`${templatePath}/public`),
        appHtml: resolveOwn(`${templatePath}/public/yourNewHtmlFile.html`),  // change this line
        appIndexJs: resolveModule(resolveOwn, `${templatePath}/src/index`),
        appPackageJson: resolveOwn('package.json'),
        appSrc: resolveOwn(`${templatePath}/src`),
        appTsConfig: resolveOwn(`${templatePath}/tsconfig.json`),
        appJsConfig: resolveOwn(`${templatePath}/jsconfig.json`),
        yarnLockFile: resolveOwn(`${templatePath}/yarn.lock`),
        testsSetup: resolveModule(resolveOwn, `${templatePath}/src/setupTests`),
        proxySetup: resolveOwn(`${templatePath}/src/setupProxy.js`),
        appNodeModules: resolveOwn('node_modules'),
        swSrc: resolveModule(resolveOwn, `${templatePath}/src/service-worker`),
        publicUrlOrPath,
        // These properties only exist before ejecting:
        ownPath: resolveOwn('.'),
        ownNodeModules: resolveOwn('node_modules'),
        appTypeDeclarations: resolveOwn(`${templatePath}/src/react-app-env.d.ts`),
        ownTypeDeclarations: resolveOwn('lib/react-app.d.ts'),
      };
      }
      // @remove-on-eject-end
    
      module.exports.moduleFileExtensions = moduleFileExtensions;
    

就是这样

于 2021-08-22T05:51:41.360 回答