目录
创建React应用:
使用 npm
创建 React Web 应用的命令如下:
- 首先,您需要安装 Node.js 和 npm。如果您还没有安装 Node.js 和 npm,请先安装它们。
- 打开命令行工具,并进入您想要创建 React Web 应用的目录。
- 在命令行中运行以下命令,使用
create-react-app
工具创建 React Web 应用:npx create-react-app my-app
在上面的命令中,`my-app` 是您要创建的应用程序的名称。您可以将其替换为您自己的应用程序名称。
create-react-app
工具将会自动创建一个新的 React Web 应用,并安装所需的依赖包。创建完成后,您可以进入新创建的应用程序目录:cd my-app
- 在应用程序目录中,您可以使用以下命令启动开发服务器:
npm start
运行上述命令后,开发服务器将会启动,并在浏览器中打开应用程序。您可以在开发服务器启动后,通过访问 `http://localhost:3000` 来访问应用程序。
现在,您已经成功地创建了一个新的 React Web 应用,并启动了开发服务器。您可以开始编写您的应用程序代码,并使用 `npm start` 命令来预览您的应用程序。
React web应用的目录文件结构
在使用命令创建react web应用后,看到的目录和文件结构是这样的:
React Web 应用的目录文件结构可以根据具体需求进行调整,但通常包含以下文件和目录:
src
: 存放应用程序的源代码。components
: 存放应用程序的组件。pages
: 存放应用程序的页面组件。assets
: 存放应用程序所需的静态资源,例如图片、字体等。styles
: 存放应用程序的样式文件,例如 CSS、Sass、Less 等。utils
: 存放应用程序的工具函数和帮助函数。services
: 存放应用程序的服务,例如 API 请求等。constants
: 存放应用程序的常量,例如枚举值、配置项等。App.js
: 应用程序的主组件。index.js
: 应用程序的入口文件。
public
: 存放应用程序所需的静态文件,例如 HTML、favicon.ico 等。node_modules
: 存放应用程序的依赖包。package.json
: 应用程序的配置文件,包括依赖包、启动脚本等信息。README.md
: 应用程序的说明文档。通常情况下,React Web 应用的目录结构遵循单一职责原则和分层架构原则,将不同类型的文件放置在对应的目录中,以便于代码的组织和维护。例如,组件应该放置在components
目录中,页面组件应该放置在pages
目录中,静态资源应该放置在assets
目录中等等。除了上述目录和文件之外,您还可以根据具体需求添加其他的目录和文件。例如,如果您的应用程序需要国际化支持,您可以添加一个
locales
目录,用于存放不同语言的翻译文件。如果您的应用程序需要使用 Redux 来管理状态,您可以添加一个redux
目录,用于存放 Redux 相关的文件。
React 中的组件如何传入参数
React的页面通过组件实现页面部件的灵活组合。组件的动态数据通过组件初始化时的参数设定。例如,假设您的 About 组件接收两个参数 `company_info` 和 `address`,您可以在 App 组件(src/App.jsx 文件)中引入 About 组件(src/About.jsx文件),并将这两个参数传递给 About 组件。下面是一个示例代码:
App组件代码文件src/App.jsx:
import React from 'react'; import About from './About'; function App() { const companyInfo = { name: 'ABC Company', industry: 'Technology' }; const address = { street: '123 Main St', city: 'San Francisco', state: 'CA', zip: '94111' }; return ( <div> <About company_info={companyInfo} address={address} /> </div> ); } export default App;
在上面的代码中,我们首先引入 About 组件,并定义了 `companyInfo` 和 `address` 两个参数的值。然后,我们在 App 组件中使用 About 组件,并将这两个参数传递给 About 组件,其中 `company_info` 对应 `companyInfo` 参数,`address` 对应 `address` 参数。
关于 About 组件的定义,您需要在 About.js 文件中编写代码。在 About.js 文件中,您可以通过 `props` 对象来获取传递给 About 组件的参数,例如:
About组件代码文件src/About.jsx:
import React from 'react'; function About(props) { const companyInfo = props.company_info; const address = props.address; return ( <div> <h2>About Us</h2> <p>Company Name: {companyInfo.name}</p> <p>Industry: {companyInfo.industry}</p> <p>Address: {address.street}, {address.city}, {address.state} {address.zip}</p> </div> ); } export default About
在上面的代码中,我们首先通过 `props` 对象获取了传递给 About 组件的 `company_info` 和 `address` 参数。然后,我们在组件中使用这些参数来渲染 UI。例如,我们使用 `companyInfo.name` 来显示公司名称,使用 `address.street`、`address.city`、`address.state` 和 `address.zip` 来显示地址信息。
React 中的页面跳转(路由)的实现原理:
React 中的路由通常使用第三方库来实现,最流行的路由库是 react-router
。使用 react-router
可以帮助您在 React 应用程序中实现路由功能,使得用户能够在不同的 URL 之间切换,同时保持单页应用程序(SPA)的优势。
下面是一个使用 react-router
实现路由功能的示例:
-
首先,您需要安装
react-router-dom
包。您可以使用 npm 或 yarn 安装该包:npm install react-router-dom # 或者 yarn add react-router-dom
-
在您的 React 应用程序中,您需要导入
BrowserRouter
和Route
组件,以便实现路由功能。例如:import { BrowserRouter, Route } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> </BrowserRouter> ); }
在上面的代码中,我们使用
BrowserRouter
组件创建了一个路由器,并在其中定义了三个路由规则。其中,exact
属性表示该路由规则只匹配精确的 URL,而不是 URL 的子路径。例如,exact path="/"
只匹配根路径,而不匹配任何子路径。component
属性指定了该路由规则所对应的组件。 -
在您的组件中,您可以使用
Link
组件来创建一个链接,以便用户能够点击该链接并切换到对应的 URL。import { Link } from 'react-router-dom'; function Navbar() { return ( <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/contact">Contact</Link> </li> </ul> </nav> ); }
在上面的代码中,我们使用 `Link` 组件创建了三个链接,分别对应于不同的 URL。用户可以点击这些链接来切换到对应的 URL。
以上是一个基本的使用 `react–router` 实现路由功能的示例。在实际应用中,您还可以使用 `Switch` 组件、`Redirect` 组件、嵌套路由等功能来实现更复杂的路由需求。
React 应用的状态管理逻辑:
在 React 中,变量状态是通过组件的状态(State)来管理的。组件的状态是一个可以被改变的 JavaScript 对象,它包含了组件的数据,并且可以在组件的生命周期中被修改。
组件的状态可以通过 this.state
属性来访问,以及通过 this.setState()
方法来更新。当 this.setState()
方法被调用时,React 会自动重新渲染组件,并根据新的状态更新组件的 DOM。
下面是一个示例:
import React from 'react'; class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } handleClick() { this.setState({ count: this.state.count + 1 }); } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.handleClick()}> Click me </button> </div> ); } }
在上面的代码中,Example
组件的状态包含了一个名为 count
的变量。当用户点击按钮时,handleClick()
方法会被调用,使用 this.setState()
方法来更新 count
变量的值。在组件的 render()
方法中,this.state.count
被用来显示用户点击按钮的次数。
需要注意的是,状态只能通过 this.setState()
方法来更新。直接修改 this.state
属性的值是不会触发组件的重新渲染的。而且,由于 this.setState()
方法是异步的,所以不能直接依赖于 this.state
的值来更新状态,而应该使用回调函数来确保更新的正确性。例如:
// 不能保证更新的正确性 this.setState({ count: this.state.count + 1 }); // 应该使用回调函数确保更新的正确性 this.setState(prevState => ({ count: prevState.count + 1 }
如何回调函数来确保更新的正确性?
React 中的 setState
方法是一个异步方法,因此在对状态进行更新时,不能直接依赖于 this.state
的值来进行计算,因为此时 this.state
的值可能还没有更新。为了确保更新的正确性,可以使用 setState
方法的回调函数来进行计算。回调函数会在状态更新完成后被调用,因此可以确保更新的正确性。
下面是一个使用react回调函数 管理react状态值 的示例代码:
this.setState( { count: this.state.count + 1 }, () => { // 在回调函数中进行计算 console.log(`The count is now ${this.state.count}`); } );
在上面的代码中,setState
方法的第二个参数是一个回调函数,在状态更新完成后会被调用。在回调函数中,可以使用更新后的状态值来进行计算。例如,上面的示例中,在回调函数中使用 this.state.count
来输出更新后的计数值。
使用回调函数的好处是可以确保状态更新完成后再进行计算,避免了状态更新的不确定性,使得代码更加稳定和可靠。
React应用打包发布:
package.json 配置文件中的辅助脚本作用说明:
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" },
在之前 创建 应用的时候,package.json 文件里有以上类似内容。
在 React 项目的 package.json
文件中,"scripts"
属性是一个包含了各种命令的对象,可以通过 npm run
命令来执行这些命令。下面是 "scripts"
对象中常见的几个命令及其作用:
"start": "react-scripts start"
:开始开发模式并启动开发服务器。在开发模式下,React 会自动重新编译代码,并在浏览器中实时更新显示结果。"build": "react-scripts build"
:构建生产环境的代码。在构建过程中,React 会对代码进行压缩和优化,以提高性能和加载速度。"test": "react-scripts test"
:运行测试。React 提供了测试工具和测试框架,可以在开发和构建过程中进行自动化测试,确保代码的质量和稳定性。"eject": "react-scripts eject"
:将项目从 React 脚手架中“弹出”,以获得更多的配置自由度。执行该命令会将 React 脚手架的配置文件复制到项目中,并将其解除封装,以便进行更多的自定义配置。
除了常见的这些命令外,您还可以根据自己的需求添加和修改 "scripts"
对象中的命令,以便更好地管理和使用 React 项目。
如何打包发布React 应用:
运行 命令编译 代码得到 适用于生产环境的代码文件(生成在 build/ 目录下):
npm run build
运行 npm run build
命令会生成用于生产环境的代码,也就是发布版本的代码。与开发环境不同,生产环境的代码经过了优化和压缩,以提高性能和加载速度。这些优化包括删除注释、去除空格、混淆代码等操作。
通过运行 npm run build
命令,React 会使用 Webpack 工具将源代码编译成生产环境的代码,并将编译后的代码输出到 build 文件夹中。这些编译后的代码是可以直接部署到服务器上的,以便用户访问和使用。
需要注意的是,在开发阶段,我们可以使用 npm start
命令来启动开发服务器,以便进行开发和调试。npm start
命令会生成用于开发环境的代码,也就是调试版本的代码。该版本的代码通常会包含开发工具和调试信息,以便进行调试和错误定位。但是,这种代码并不适合直接部署到生产环境中,因为它没有经过优化和压缩,加载速度会比较慢,同时也存在安全风险。
进阶(原理、版本差异、使用React做移动APP开发):
React工作原理
目前我们的项目多个组件App和Message,如图components/目录下的 *.jsx 文件名的都是不同组件,下图包括About、App、Contact、Frame、Home、Link 组件。
当应用启动时,React会根据组件相应地建立Javascript数据结构,叫虚拟DOM。虚拟DOM与在浏览器显示的实际DOM是不同的,它是组件树在内存中的表示,每一个节点表示一个组件及其属性。当组件的状态或者说数据变化时,相应的虚拟DOM节点也作相应的更新反映新的状态,然后虚拟DOM再比较当前版本与之前的版本,以决定是否需要更新实际的DOM。
从技术上讲,更新DOM不是由React完成的,而是由它的同伴React DOM完成的。我们查看package.json,发现目前依赖的就是两个库:React和React DOM。
... "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, ...
我们来看看它们是如何一起工作的。
React代码目录结构中,src/index.jsx 会将组件绑定于 public/index.html 的root元素位置,src/index.jsx是我们的应用的入口点。查看index.jsx发现,ReactDOM负责渲染我们整个组件树,根组件 App 包含在另一个叫React.StrictMode的组件里,这个组件不用于显示,而是用于发现一些问题。
... ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( <React.StrictMode> <App /> </React.StrictMode>, )
React 版本和语法差异:
一些使用React旧版本的代码 src/index.js 文件写法:
import ReactDOM from 'react-dom' ReactDom.render(<App />, document.getElementById('root'))
则 npm start 时会有告警信息:
ReactDOM.render is no longer supported in React 18. Use createRoot instead.
修改为如下新版本代码:
import {createRoot} from 'react-dom/client'; createRoot(document.getElementById('root')).render(<App />);
再结合最新版本React项目my-app 配置文件 package.json 内容:
{ "name": "my-app", "version": "0.1.0", "private": true, "dependencies": { "@mui/styles": "^5.13.2", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^5.3.4", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
其中react和react dom组件的版本都是18,
"react": "^18.2.0",
"react-dom": "^18.2.0",
且由于使用了 ReactDOM.createRoot() 这个代码,在 npm run build 打包发布的时候,不会再有告警信息。
移动APP中使用React开发页面
在手机App中,渲染画面使用的是另一个库:React Native。React没有跟具体平台绑定,它对平台是透明的,React创建的应用可以在Web、手机或桌面上使用。
React Native 和 Expo 让你可以使用 React 构建 Android、iOS 等应用程序。它们的样式和体验都和原生应用程序一样,因为它们的用户界面是真正的原生用户界面。你的 React 组件由平台提供的真实 Android 或 iOS 视图来渲染。
react 开发web应用跟 React Native 开发移动应用的本质区别是什么?
React 和 React Native 都是由 Facebook 开发的用于构建用户界面的 JavaScript 库。它们的本质区别在于,React 用于构建 Web 应用程序,而 React Native 用于构建原生移动应用程序。
具体来说,React 通过虚拟 DOM 来管理 UI,使用 HTML 和 CSS 来定义用户界面。而 React Native 则使用类似 HTML 和 CSS 的 JSX 语法来定义 UI,但是它最终会被转换为原生组件,例如 iOS 中的 UIView 和 Android 中的 View。
由于 React Native 使用原生组件来构建用户界面,因此它可以直接调用操作系统的 API,实现更高效的渲染和更好的性能。同时,React Native 支持使用 JavaScript 来编写业务逻辑和控制流程,使得开发人员可以使用相同的技术栈来构建 iOS 和 Android 应用程序,减少了开发成本和维护难度。
相比之下,React 更适合构建 Web 应用程序,它可以在浏览器中直接渲染用户界面。React 支持使用 React Router 来管理路由,使用 Redux 管理状态,使用 CSS-in-JS 等技术来实现更灵活和可复用的组件。
总之,React 和 React Native 都是用于构建用户界面的 JavaScript 库,但它们的本质区别在于目标平台不同,React 用于构建 Web 应用程序,而 React Native 用于构建原生移动应用程序。