• React 使用JSX或者TSX渲染页面


    02 Rendering with JSX

    Your first JSX content

    In this section, we’ll implement the obligatory " Hello, World " JSX application. At this point, we’re just dipping our toes in the water; more in-depth examples will follow. We’ll also discuss what makes this syntax work well for declarative UI structures.

    在本节中,我们将实现必需的“Hello, World”JSX应用程序。在这一点上,我们只是把脚趾伸进水里;后面会有更深入的例子。我们还将讨论是什么使这种语法能够很好地用于声明性UI结构。

    Hello JSX

    先创建一个基于ts的vite项目:

    npm create vite
    

    修改src/main.tsx:

    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App.tsx";
    
    ReactDOM.createRoot(document.getElementById("root")!).render(
      
        
      
    );
    

    Without further ado, here’s your first JSX application:

    话不多说,下面是您的第一个JSX应用程序: src/App.tsx

    function App() {
      return (
        

    Hello, JSX

    ); } export default App;

    Let’s walk through what’s happening here. The render() function takes JSX as an argument and renders it to the DOM node passed toReactDOM.createRoot() .The actual JSX content in this example renders a paragraph with some bold text inside. There’s nothing fancy going on here, so we could have just inserted this markup into the DOM directly as a plain string. However, the aim of this example is to show the basic steps involved in getting JSX rendered onto the page. Now, let’s talk a little bit about the declarative UI structure.

    让我们来看看这里发生了什么。render()函数接受JSX作为参数,并将其呈现给传递给reactdom . createroot()的DOM节点。本例中的实际JSX内容呈现一个段落,其中包含一些粗体文本。这里没有什么特别的事情,所以我们可以直接将这个标记作为一个普通字符串插入DOM。但是,本示例的目的是展示将JSX呈现到页面上所涉及的基本步骤。现在,让我们讨论一下声明性UI结构。

    Declarative UI structures

    Before we move forward with more in-depth code examples, let’s take a moment to reflect on our " Hello, World " example. The JSX content was short and simple. It was also declarative because it described what to render, not how to render it. Specifically, by looking at the JSX, you can see that this component will render a paragraph and some bold text within it. If this were done imperatively, there would probably be some more steps involved, and they would probably need to be performed in a specific order.

    在继续讨论更深入的代码示例之前,让我们花点时间回顾一下“Hello, World”示例。JSX的内容简短而简单。它也是声明性的,因为它描述了要呈现什么,而不是如何呈现。具体来说,通过查看JSX,您可以看到该组件将在其中呈现一个段落和一些粗体文本。如果这是命令式的,则可能会涉及到更多的步骤,并且可能需要以特定的顺序执行。

    I find it helpful to think of declarative as structured and imperative as ordered. It’s much easier to get things right with a proper structure than to perform steps in a specific order.

    我发现将陈述性看作是结构化的,命令式看作是有序的很有帮助。与按特定顺序执行步骤相比,用适当的结构把事情做好要容易得多。

    The example we just implemented should give you a feel for what declarative React is all about. As we move forward in this chapter and throughout the book, the JSX markup will grow more elaborate. However, it’s always going to describe what is in the UI.The render() function tells React to take your JSX markup and transform it into JavaScript statements that update the UI in the most efficient way possible. This is how React enables you to declare the structure of your UI without having to think about carrying out ordered steps to update elements on the screen; an approach that often leads to bugs. Out of the box, React supports the standard HTML tags that you would find on any HTML page. Unlike static HTML, React has unique conventions that should be followed when using HTML tags.…

    我们刚刚实现的例子应该会让你对声明式React有一个大致的了解。随着本章和本书的深入,JSX标记将变得更加复杂。不过,它总是会描述UI中的内容。render()函数告诉React获取您的JSX标记并将其转换为JavaScript语句,以最有效的方式更新UI。这就是React如何让你声明UI的结构,而不必考虑执行有序的步骤来更新屏幕上的元素;一种经常导致bug的方法。React开箱即用,支持在任何HTML页面上都能找到的标准HTML标记。与静态HTML不同,React在使用HTML标签…时应该遵循独特的约定

    Rendering HTML

    At the end of the day, the job of a React component is to render HTML into the DOM browser. This is why JSX has support for HTML tags out of the box. In this section, we’ll look at some code that renders a few of the available HTML tags. Then, we’ll cover some of the conventions that are typically followed in React projects when HTML tags are used.

    归根结底,React组件的工作是将HTML呈现到DOM浏览器中。这就是JSX支持HTML标记的原因。在本节中,我们将看一些呈现一些可用HTML标记的代码。然后,我们将介绍在React项目中使用HTML标记时通常遵循的一些约定。

    Built-in HTML tags

    When we render JSX, element tags reference React components. Since it would be tedious to have to create components for HTML elements, React comes with HTML components. We can render any HTML tag in our JSX, and the output will be just as we’d expect. Now, let’s try rendering some of these tags:

    当我们渲染JSX时,元素标签引用React组件。因为为HTML元素创建组件会很繁琐,所以React自带了HTML组件。我们可以在JSX中呈现任何HTML标记,输出将与我们所期望的一样。现在,让我们尝试渲染其中的一些标签:

    function App() {
      return (
        

    标题标签

    段落标签

    • 列表标签
    • 列表标签
    • 列表标签
    ); } export default App;

    Don’t worry about the formatting of the rendered output for this example. We’re making sure that we can render arbitrary HTML tags, and they render as expected, without any special definitions and imports.

    对于本例,不要担心呈现输出的格式。我们要确保可以呈现任意HTML标记,并且它们可以按照预期呈现,而不需要任何特殊的定义和导入。

    HTML elements rendered using JSX closely follow regular HTML element syntax with a few subtle differences regarding case-sensitivity and attributes.

    使用JSX呈现的HTML元素非常遵循常规HTML元素语法,只是在区分大小写和属性方面有一些细微的区别。

    HTML tag conventions

    When you render HTML tags in JSX markup, the expectation is that you’ll use lowercase for the tag name. In fact, capitalizing the name of an HTML tag will fail. Tag names are case-sensitive and non-HTML elements are capitalized. This way, it’s easy to scan the markup and spot the built-in HTML elements versus everything else.You can also pass HTML elements any of their standard properties. When you pass them something unexpected, a warning about the unknown property is logged. Here’s an example that illustrates these ideas:

    在JSX标记中呈现HTML标记时,期望使用小写的标记名。事实上,将HTML标记的名称大写将会失败。标签名称区分大小写,非html元素大写。这样,就很容易扫描标记并找出内置的HTML元素和其他元素。您还可以将HTML元素的任何标准属性传递给它们。当您向它们传递一些意外的内容时,将记录有关未知属性的警告。这里有一个例子可以说明这些想法:

    function App() {
      return (
        
    ); } export default App;

    When you run this example, it will fail to compile because React doesn’t knowabout the ; }

    This component uses the exact same pattern as MySection ; it takes the{props.children} value and surrounds it with markup. React handles the details for you. In this example, the button text is a child of MyButton , which is, in turn, a child of MySection . However, the button text is transparently passed through MySection . In other words, we didn’t have to write any code in MySection to make sure that MyButton got its text. Pretty cool, right?

    这个组件使用与MySection完全相同的模式;它使用{props。Children}值,并用标记包围它。React会为你处理这些细节。在这个例子中,按钮文本是MyButton的子元素,而MyButton又是MySection的子元素。但是,按钮文本是透明地通过MySection传递的。换句话说,我们不需要在MySection中编写任何代码来确保MyButton获得它的文本。很酷,对吧?

    We can further organize our components by placing them within a namespace.

    我们可以通过将组件放置在名称空间中来进一步组织组件。

    Namespaced components

    The custom elements that you’ve created so far have used simple names. A namespace provides an organizational unit for your components so that related components can share the same namespace prefix. Instead of writing in your JSX markup, you would write . This makes it clear that MyComponent is part of MyNamespace .Typically, MyNamespace would also be a component. The idea of namespacing is to have a namespace component render its child components using the namespace syntax. Let’s take a look at an example:

    到目前为止,您创建的自定义元素都使用了简单的名称。名称空间为组件提供了一个组织单元,以便相关组件可以共享相同的名称空间前缀。而不是写’在你的JSX标记中,你应该写。这清楚地表明MyComponent是MyNamespace的一部分。通常,MyNamespace也是一个组件。名称空间的思想是让名称空间组件使用名称空间语法呈现其子组件。让我们来看一个例子:

    新增 src/MyComponent2.tsx

    function MyComponent(props) {
      return 
    {props.children}
    ; } function First() { return

    第一个组件...

    ; } function Second() { return

    第二个组件...

    ; } MyComponent.First = First; MyComponent.Second = Second; function MyComponent2() { return ( ); } export default MyComponent2;

    This markup renders a element with two children. Instead of writing , we write , and the same with . We want to explicitly show that First and Second belong to MyComponent within the markup.Now, let’s take a look at the MyComponent module:

    这个标记呈现了一个带有两个子元素的元素。我们不写,而是写也一样。我们想要显式地显示First和Second属于标记中的MyComponent。现在,让我们来看看MyComponent模块:

    function MyComponent(props) {
      return 
    {props.children}
    ; } function First() { return

    第一个组件...

    ; } function Second() { return

    第二个组件...

    ; } MyComponent.First = First; MyComponent.Second = Second;

    This module declares MyComponent as well as the other components that fall under this namespace ( First and Second ). It assigns the components to the namespace component ( MyComponent ) as function object properties. There are a number of things that you could change in this module. For example, you don’t have to directly export First and Second since they’re accessible through MyComponent . You also don’t need to define everything in the same module; you could import First and Second and assign them as function object properties. Using namespaces is completely optional, and, if you use them, you should use them consistently.You now know how to build your own React components that introduce new JSX tags in your markup. The components that we’ve looked at so far in this chapter have been static. That is, once we rendered them, they were never updated. JavaScript expressions are the dynamic pieces of JSX and are what cause React to update components.

    这个模块声明了MyComponent以及这个命名空间下的其他组件(First和Second)。它将组件作为函数对象属性分配给命名空间组件(MyComponent)。在这个模块中,您可以更改许多内容。例如,你不必直接导出First和Second,因为它们可以通过MyComponent访问。你也不需要在同一个模块中定义所有的东西;您可以导入First和Second,并将它们指定为函数对象属性。使用名称空间是完全可选的,如果要使用它们,应该始终如一地使用它们。现在您知道了如何构建自己的React组件,在标记中引入新的JSX标记。到目前为止,我们在本章中看到的组件都是静态的。也就是说,一旦我们渲染了它们,它们就永远不会更新。JavaScript表达式是JSX的动态部分,是React更新组件的原因。

    Using JavaScript expressions

    As you saw in the preceding section, JSX has a special syntax that allows you to embed JavaScript expressions. Any time React renders JSX content, expressions in the markup are evaluated. This is the dynamic aspect of JSX, and in this section, you’ll learn how to use expressions to set property values and element text content. You’ll also learn how to map collections of data to JSX elements.

    正如您在上一节看到的,JSX有一种特殊的语法,允许您嵌入JavaScript表达式。每当React呈现JSX内容时,都会计算标记中的表达式。这是JSX的动态方面,在本节中,您将学习如何使用表达式来设置属性值和元素文本内容。您还将学习如何将数据集合映射到JSX元素。

    Dynamic property values and text

    Some HTML property or text values are static, meaning that they don’t change as JSX markup is re-rendered. Other values, the values of properties or text, are based on data that is found elsewhere in the application. Remember, React is just the view layer. Let’s look at an example so that you can get a feel for what the JavaScript expression syntax looks like in JSX markup:

    一些HTML属性或文本值是静态的,这意味着它们在重新呈现JSX标记时不会改变。其他值(属性值或文本值)基于在应用程序中其他地方找到的数据。记住,React只是视图层。让我们来看一个例子,这样你就可以感受到JavaScript表达式在JSX标记中的语法是什么样的:

    新增 src/MyComponent3.tsx:

    function MyComponent3() {
      const enabled = false;
      const text = "一个按钮";
      const placeholder = "请输入账号";
      const size = 50;
    
      return (
        
    ); } export default MyComponent3;

    Anything that is a valid JavaScript expression, including nested JSX, can go in between the curly braces: {} . For properties and text, this is often a variable name or object property. Notice, in this example, that the !enabled expression computes a Boolean value.

    任何有效的JavaScript表达式,包括嵌套的JSX,都可以放在花括号{}之间。对于属性和文本,这通常是一个变量名或对象属性。注意,在本例中,启用的表达式计算一个布尔值。

    Primitive JavaScript values are straightforward to use in JSX syntax. But what if you have an object or array that you need to transform into JSX elements?

    原始JavaScript值在JSX语法中使用很简单。但是,如果需要将对象或数组转换为JSX元素,该怎么办呢?

    Handling events

    In React, you can easily pass events to components to handle user interactions such as button clicks, form submissions, and mouse movements. This allows you to create interactive and responsive user interfaces. React provides a convenient way to attach event handlers directly to components using a syntax similar to how you would use the addEventListener and removeEventListener methods in traditional JavaScript.To illustrate this, let’s consider an example where we want to handle a button click event in a React component:

    在React中,您可以轻松地将事件传递给组件来处理用户交互,例如按钮单击、表单提交和鼠标移动。这允许您创建交互式和响应式用户界面。React提供了一种方便的方式来直接将事件处理程序附加到组件上,使用类似于传统JavaScript中使用addEventListener和removeEventListener方法的语法。为了说明这一点,让我们考虑一个例子,我们想要处理一个React组件中的按钮点击事件:

    新增:src/MyComponent4.tsx

    function MyComponent4() {
      const text = "点我试试";
      const onButtonClick = () => {
        alert("试试就试试");
      };
      return (
        
    ); } export default MyComponent4;

    In this example, we define a function called handleClick that will be called when the button is clicked. We then attach this function as an event handler to the onClick property of the