岸边的风:个人主页
个人专栏 :《 VUE 》 《 javaScript 》
⛺️ 生活的理想,就是为了理想的生活 !
目录
Component
JSX
Multiple components
props: passing data to components
Some notes
我们现在将开始入门的可能是本课程最重要的主题,即React-库。让我们从制作一个简单的React应用开始,同时了解React的核心概念。
到目前为止,最简单的方法是使用一个叫做create-react-app的工具来开始。如果随Node一起安装的npm工具的版本号是5.3以上,那么在你的机器上安装create-react-app是可行的(但不是必须的)。
让我们创建一个名为part1的应用,并进入其目录。
npx create-react-app part1
cd part1
该应用的运行方式如下
npm start
默认情况下,该应用在本地主机的3000端口运行,地址为http://localhost:3000。
默认浏览器应该自动启动。立即打开浏览器的控制台。同时打开一个文本编辑器,这样你就可以在屏幕上同时查看代码和网页。
应用的代码位于src文件夹中。让我们简化默认代码,使文件index.js的内容如下所示:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render( )
copy
而文件App.js看起来是这样的:
const App = () => (
Hello world
)
export default App
copy
文件App.css, App.test.js, index.css, logo.svg, setupTests.js 和 reportWebVitals.js 可以删除,因为它们现在在我们的应用中并不需要。
如果你最后出现了以下错误
可能由于某种原因使用了比当前18版本更早的React版本。
修复方法是修改index.js,如下所示
import ReactDOM from "react-dom"
import App from "./App"
ReactDOM.render( , document.getElementById("root"))
copy
你很可能需要为你的其他项目做相同的事情。
关于版本差异的更多信息,请参见这里。
文件App.js现在定义了一个名为App的React组件。在文件index.js的最后一行的命令:
ReactDOM.createRoot(document.getElementById('root')).render( )
copy
将其内容渲染到div-元素中,该元素在文件public/index.html中定义,其id值为'root'。
默认情况下,文件public/index.html不包含任何我们在浏览器中可见的HTML标记。你可以尝试在该文件中添加一些HTML。当使用React时,所有需要渲染的内容通常被定义为React组件。
让我们仔细看一下定义组件的代码。
const App = () => (
Hello world
)
copy
正如你可能猜到的,这个组件将被渲染成一个div-标签,它包裹着一个p-标签,其中包含了文本Hello world。
从技术角度来说,该组件被定义为一个JavaScript函数。下面是一个函数(它不接收任何参数):
() => (
Hello world
)
copy
然后这个函数被分配给一个常量变量App。
const App = ...
copy
有几种方法可以在JavaScript中定义函数。这里我们将使用箭头函数,它在较新的JavaScript版本中被描述为ECMAScript 6,也称为ES6。
因为函数只由一个表达式组成,所以我们使用了一个简写,表示这一段代码。
const App = () => {
return (
Hello world
)
}
copy
换句话说,该函数返回表达式的值。
定义该组件的函数可以包含任何种类的JavaScript代码。把你的组件修改成如下样子,观察控制台中发生了什么。
const App = () => {
console.log('Hello from component')
return (
Hello world
)
}
copy
也可以在一个组件内渲染动态内容。
修改组件如下。
const App = () => {
const now = new Date()
const a = 10
const b = 20
return (
Hello world, it is {now.toString()}
{a} plus {b} is {a + b}
)
}
copy
大括号内的任何JavaScript代码都会被计算,计算的结果会被嵌入到组件产生的HTML中的定义位置。
看起来React组件返回的是HTML标记。然而,事实并非如此。React组件的布局大多是用JSX编写的。虽然JSX如下所示:HTML,但我们实际上是在处理一种写JavaScript的方式。底层上,由React组件返回的JSX被编译成JavaScript。
编译后,我们的应用如下所示:
const App = () => {
const now = new Date()
const a = 10
const b = 20
return React.createElement(
'div',
null,
React.createElement(
'p', null, 'Hello world, it is ', now.toString()
),
React.createElement(
'p', null, a, ' plus ', b, ' is ', a + b
)
)
}
copy
编译是由Babel处理的。用create-react-app创建的项目被配置为自动编译。我们将在本课程的第7章节中学习更多关于这个主题的内容。
也可以把React写成 "纯JavaScript "而不使用JSX。不过,理智的人不会这么做的。
实际上,JSX很像HTML,区别在于使用JSX,你可以通过在大括号内编写适当的JavaScript来轻松嵌入动态内容。JSX的理念与许多模板语言非常相似,例如与Java Spring一起使用的Thymeleaf,它被用在服务器上。
JSX是"XML-like"语言,这意味着每个标签都需要被关闭。例如,换行是一个空元素,在HTML中可以写成如下。
copy
但在编写JSX时,标签需要被关闭。
copy
让我们修改文件App.js如下(注:在这些示例中,底部的export 部分被省略,现在和将来都是如此。但它仍然是代码正常工作所必须的)。
const Hello = () => { return ( Hello world
)}
const App = () => {
return (
Greetings
)
}
我们定义了一个新的组件Hello,并在组件App中使用它。当然,一个组件可以被多次使用。
const App = () => {
return (
Greetings
)
}
copy
用React编写组件是很容易的,通过组合组件,即使是比较复杂的应用也可以保持相当的可维护性。事实上,React的一个核心理念是由许多专门的可重复使用的组件组成应用。
另一个强制的惯例是在应用的组件树的顶端有一个叫做App的根组件。然而,正如我们将在第6章中了解到的,有些情况下,组件App并不完全是根,而是被包裹在一个适当的实用组件中。
可以使用所谓的props向组件传递数据。
让我们对组件Hello做如下修改
const Hello = (props) => { return (
Hello {props.name}
)
}
现在定义组件的函数有一个参数props。作为一个参数,该参数接收一个对象,该对象有对应于组件用户定义的所有 "props "的字段。
这些prop的定义如下。
const App = () => {
return (
Greetings
)
}
copy
可以有任意数量的prop,它们的值可以是 "硬编码 "的字符串或JavaScript表达式的结果。如果prop的值是用JavaScript实现的,它必须用大括号来包裹。
让我们修改代码,让组件Hello使用两个props。
const Hello = (props) => {
return (
Hello {props.name}, you are {props.age} years old
)
}
const App = () => {
const name = 'Peter' const age = 10
return (
Greetings
)
}
copy
组件App发送的props是变量的值、表达式的计算结果和一个常规字符串。
React已经能生成相当清晰的错误信息。尽管如此,至少在开始的时候,你应该以非常小的步骤前进,并确保每一个改变都能如愿以偿。
控制台应始终打开。如果浏览器报告错误,不建议继续写更多的代码,寄希望有奇迹出现。相反,你应该试着理解错误的原因,比如说,回到之前的工作状态。
请记住,在React中,在你的代码中写console.log()命令(打印到控制台)是可行的,也是值得的。
还要记住,React组件名称必须大写。如果你尝试用以下方式定义一个组件
const footer = () => {
return (
greeting app created by mluukkai
)
}
并像这样使用它
const App = () => {
return (
Greetings
)
}
页面不会显示在Footer组件中定义的内容,相反React只会创建一个空的footer元素,即内置的HTML元素,而不是同名的自定义React元素。如果你把组件名称的第一个字母改为大写字母,那么React就会创建一个定义在Footer组件中的div元素,并在页面上渲染。
注意,React组件的内容(通常)需要包含一个根元素。例如,如果我们试图定义组件App而不使用最外层的div元素。
const App = () => {
return (
Greetings
)
}
结果是返回一个错误信息。
使用根元素并不是唯一可行的选择。一个组件的array也是一个有效的解决方案。
const App = () => {
return [
Greetings
,
,
]
}
然而,定义应用的根元素时,不是一个特别明智的做法,它使代码看起来有点难看。
由于根元素被强制规定了,我们在DOM树中有 "额外的 "div-elements。这可以通过使用fragments来避免,即用一个空元素来包装组件要返回的元素。
const App = () => {
const name = 'Peter'
const age = 10
return (
<>
Greetings
>
)
}
现在编译成功了,由React生成的DOM也不再包含额外的div元素。