一篇包含了React所有基本点的文章

去年,我写了一本关于学习React.js的小书,原来是大约100页。 今年我要挑战自己,把它归纳为一篇文章。

10年的阳新网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整阳新建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联从事“阳新网站设计”,“阳新网站推广”以来,每个客户项目都认真落实执行。

本文不会涵盖什么是React,或者为什么要学习它。 相反,这是面向已经熟悉JavaScript并熟悉DOM API基础知识的人,对React.js的基础知识的介绍。

以下所有代码示例均标示为参考。 它们纯粹是为了提供概念而写的例子。 他们大多数可以写得更好一些。

1:组件是React的一切

React是围绕可重用组件的概念设计的。 您定义小组件,并将它们放在一起形成更大的组件。

所有小或小的组件都可重复使用,甚至跨不同的项目。

一个React组件(以其最简单的形式)是一个简单的JavaScript函数:

 
 
 
  1. // Example 1
  2. // https://jscomplete.com/repl?j=Sy3QAdKHW
  3. function Button (props) {
  4.   // Returns a DOM element here. For example:
  5.   return {props.label};
  6. }
  7. // To render the Button component to the browser
  8. ReactDOM.render(, mountNode) 

用于按钮标签的花括号将在下面介绍。 现在不必要担心他们。 ReactDOM也将在后面解释,但是如果要测试这个例子和接下来的代码示例,render函数就是你需要的。

ReactDOM.render的第二个参数是React将要接管和控制的目标DOM元素。 在jsComplete REPL中,您就可以使用mountNode变量。

关于示例1的注意事项有以下几点:

  • 组件名称以大写字母开头。 这是必需的,因为我们将处理HTML元素和React元素的混合。 小写名称保留给HTML元素。 事实上,请继续尝试将React组件命名为“button”。 ReactDOM将忽略该函数并呈现常规的空HTML按钮。
  • 每个组件都接收一个属性列表,就像HTML元素一样。 在React中,这个列表叫做props。创建功能组件,你可以通过使用任意名称命名props。
  • 在上面的Button组件的返回中,我们写出了奇怪的HTML。 这既不是JavaScript也不是HTML,甚至不是React.js。 但是,它非常受欢迎,成为React应用程序中的默认设置。 它被称为JSX,它是一个JavaScript扩展。 JSX也是妥协! 继续尝试在上面的函数中的任何其他HTML元素,并查看它们是如何支持的(例如,返回一个文本输入元素)。

2: What the flux is JSX?

上面的示例1可以用纯粹的React.js来编写,而不需要JSX,如下所示:

 
 
 
  1. // Example 2 -  React component without JSX
  2. // https://jscomplete.com/repl?j=HyiEwoYB-
  3. function Button (props) {
  4.   return React.createElement(
  5.     "button",
  6.     { type: "submit" },
  7.     props.label
  8.   );
  9. }
  10. // To use Button, you would do something like
  11. ReactDOM.render(
  12.   React.createElement(Button, { label: "Save" }),
  13.   mountNode
  14. ); 

上面的示例1可以用纯粹的React.js来编写,而不需要JSX,如下所示:

createElement函数是React***API中函数。 您需要学习的这个级别中共有7件事情中的1项。 可见ReactApi多么简短。

很像DOM本身有一个document.createElement函数来创建一个由标签名称指定的元素,React的createElement函数是一个更高级别的函数,可以做类似于document.createElement的功能。 但它也可以用于创建一个表示React组件的元素。 当我们使用上面的例2中的Button组件时,我们这里就是创建了一个React组件。

与document.createElement不同,React的createElement可以接受第二个参数之后的动态参数,以表示创建的元素的后代。 所以createElement实际上创建一个树。

这是一个例子:

 
 
 
  1. / Example 3 -  React’s createElement API
  2. // https://jscomplete.com/repl?j=r1GNoiFBb
  3. const InputForm = React.createElement(
  4.   "form",
  5.   { target: "_blank", action: "https://google.com/search" },
  6.   React.createElement("div", null, "Enter input and click Search"),
  7.   React.createElement("input", { name: "q", className: "input" }),
  8.   React.createElement(Button, { label: "Search" })
  9. );
  10. // InputForm uses the Button component, so we need that too:
  11. function Button (props) {
  12.   return React.createElement(
  13.     "button",
  14.     { type: "submit" },
  15.     props.label
  16.   );
  17. }
  18. // Then we can use InputForm directly with .render
  19. ReactDOM.render(InputForm, mountNode); 

关于以上例子要注意的几点:

  • InputForm不是React组件; 它只是一个React元素。 这就是为什么我们直接在ReactDOM.render调用中使用它,而不是使用
  • 我们可以嵌套React.createElement调用,因为它都是JavaScript。
  • React.createElement的第二个参数可以是null,也可以是一个空对象,当元素不需要attributes和props时。
  • 我们可以将HTML元素与React组件混合使用。 您可以将HTML元素视为内置的React组件。
  • React的API尝试尽可能接近DOM API,因此我们为输入元素使用className而不是类。 私以为,我们都希望React的API将成为DOM API本身的一部分。 因为,你知道的,这有太多的好处了。

上面的代码是您在引入React库时了解的内容。 浏览器不处理任何JSX业务。 然而,我们人类喜欢看HTML并且使用HTML而不是这些createElement调用(想象一下使用document.createElement构建一个网站,我相信你可以的!)。 这就是为什么存在JSX的原因。 我们可以用非常类似于HTML的语法编写它,而不是用React.createElement调用上面的表单:

 
 
 
  1. // Example 4 - JSX (compare with Example 3)
  2. // https://jscomplete.com/repl?j=SJWy3otHW
  3. const InputForm =
  4.   
  5.     
    Enter input and click Search
  6.     
  7.     
  8.   ;
  9. // InputForm "still" uses the Button component, so we need that too.
  10. // Either JSX or normal form would do
  11. function Button (props) {
  12.   // Returns a DOM element here. For example:
  13.   return {props.label};
  14. }
  15. // Then we can use InputForm directly with .render
  16. ReactDOM.render(InputForm, mountNode); 

关于上面的例子注意以下几点

  • 它不是HTML。 例如,我们仍然在使用className而不是类。
  • 我们仍然在考虑将以上HTML作为JavaScript。 看看我在末尾添加了分号。

我们上面写的(例4)是JSX。 然而,我们在浏览器的执行版本是它的编译版本(示例3)。 为了实现这一点,我们需要使用预处理器将JSX版本转换为React.createElement版本。

那就是JSX。 这是一个折中,允许我们以类似于HTML的语法编写我们的React组件,这是一个很好的共识。

上面标题中的“Flux”一词被选为韵脚(...),但它也是Facebook流行的非常受欢迎的应用程序架构的名称。 最着名的实现是Redux。

JSX,顺便说一下,可以自己在其他地方使用。 这不是只有在React中才可以使用的。

3: 您可以在JSX中的任何位置使用JavaScript表达式

在JSX部分中,您可以在一对花括号内使用任何JavaScript表达式。

 
 
 
  1. // Example 5 -  Using JavaScript expressions in JSX
  2. // https://jscomplete.com/repl?j=SkNN3oYSW
  3. const RandomValue = () => 
  4.   
  5.     { Math.floor(Math.random() * 100) }
  6.   
;
  • // To use it:
  • ReactDOM.render(, mountNode); 
  • 任何JavaScript表达式都可以放在那些花括号内。 这相当于JavaScript模板文字中的$ {}插值语法。

    这是JSX中唯一的约束:只有表达式。 所以,你不能使用常规的if语句,但是三元表达式是可以的。

    JavaScript变量也是表达式,所以当组件接收到props列表(RandomValue组件没有,props是可选的)时,可以在花括号内使用这些props。 我们在上面的Button组件中这样做了(示例1)。

    JavaScript对象也是表达式。 有时候,我们在一个花括号里面使用一个JavaScript对象,这使得它看起来像双花括号,但它实际上只是一个大括号内的一个对象。 一个用例是将CSS样式对象传递给React中的style属性:

     
     
     
    1. // Example 6 - An object passed to the special React style prop
    2. // https://jscomplete.com/repl?j=S1Kw2sFHb
    3. const ErrorDisplay = ({message}) =>
    4.   
    5.     {message}
    6.   
    ;
  • // Use it:
  • ReactDOM.render(
  •   
  •     message="These aren't the droids you're looking for" 
  •   />,
  •   mountNode
  • ); 
  • 请注意,我如何仅解析props参数中的message的。 这是JavaScript。 还要注意上面的style属性是一个特殊的属性(再次,它不是HTML,它更接近于DOM API)。 我们使用一个对象作为style属性的值。 该对象定义了样式,就像我们使用JavaScript一样(因为确实就是)。

    甚至可以在JSX中使用React元素,因为这也是一个表达式。 记住,一个React元素就是一个函数调用:

     
     
     
    1. const MaybeError = ({errorMessage}) =>
    2.   
    3.     {errorMessage && }
    4.   
    ;
  •   
  • // The MaybeError component uses the ErrorDisplay component:
  • const ErrorDisplay = ({message}) =>
  •   
  •     {message}
  •   ;
  • // Now we can use the MaybeError component:
  • ReactDOM.render(
  •   
  •     errorMessage={Math.random() > 0.5 ? 'Not good' : ''}
  •   />,
  •   mountNode
  • ); 
  • 上面的MaybeError组件将只显示ErrorDisplay组件,如果有一个errorMessage字符串传递给它和一个空的div。 React将{true},{false},{undefined}和{null}视为没有呈现任何内容的有效元素子元素。

    您还可以使用JSX内的集合上的所有JavaScript方法(map,reduce,filter,concat等)。 再次声明原因是因为它们返回的是表达式:

     
     
     
    1. // Example 8 - Using an array map inside {}
    2. // https://jscomplete.com/repl?j=SJ29aiYH-
    3. const Doubler = ({value=[1, 2, 3]}) =>
    4.   
    5.     {value.map(e => e * 2)}
    6.   ;
    7. // Use it
    8. ReactDOM.render(, mountNode); 

    请注意,我是如何给valueprops默认值的,因为它全是Javascript。 还要注意,我在div中输出了一个数组表达式,这在React中是可行的。 它将把每一个双倍的值放在一个文本节点中。

    4: 您可以使用JavaScript类编写React组件

    简单的功能组件非常适合简单的需求,但有时我们需要更多的功能。 React支持通过JavaScript类语法创建组件。 这是使用类语法编写的Button组件(在示例1中):

     
     
     
    1. // Example 9 - Creating components using JavaScript classes
    2. // https://jscomplete.com/repl?j=ryjk0iKHb
    3. class Button extends React.Component {
    4.   render() {
    5.     return ;
    6.   }
    7. }
    8. // Use it (same syntax)
    9. ReactDOM.render(, mountNode); 

    类语法很简单。 定义一个扩展了React.Component基类的类(需要学习的另一个***的React API)。 该类定义一个唯一实例函数render(),该render函数返回虚拟DOM对象。 每次我们使用上面的基于Button类的组件(例如,通过执行;

  •   }
  • }
  • // Use it
  • ReactDOM.render(, mountNode); 
  • 我们还可以定义类属性函数,并在我们想使用的地方使用,包括返回的JSX输出内:

     
     
     
    1. // Example 11 — Using class properties
    2. // https://jscomplete.com/repl?j=H1YDCoFSb
    3. class Button extends React.Component {
    4.   clickCounter = 0;
    5. handleClick = () => {
    6.     console.log(`Clicked: ${++this.clickCounter}`);
    7.   };
    8.   
    9.   render() {
    10.     return (
    11.       
    12.         {this.props.label}
    13.       
    14.     );
    15.   }
    16. }
    17. // Use it
    18. ReactDOM.render(, mountNode); 

    关于例子11有几点需要注意

     
     
     
    1. // Wrong:
    2. onClick={this.handleClick()}
    3. // Right:
    4. onClick={this.handleClick} 

    5: React的事件中,两个最重要的区别

    在React元素中处理事件时,与DOM API的方式有两个非常重要的区别:

    使用自己的对象将DOM事件对象包装起来,以优化事件处理的性能。 但是在事件处理程序中,我们仍然可以访问DOM事件对象上可用的所有方法。 React将包装的事件对象传递给每个句柄调用。 例如,为了防止表单从默认提交操作中,您可以执行以下操作:

     
     
     
    1. // Example 12 - Working with wrapped events
    2. // https://jscomplete.com/repl?j=HkIhRoKBb
    3. class Form extends React.Component {
    4.   handleSubmit = (event) => {
    5.     event.preventDefault();
    6.     console.log('Form submitted');
    7.   };
    8.   
    9.   render() {
    10.     return (
    11.       
    12.         Submit
    13.       
    14.     );
    15.   }
    16. }
    17. // Use it
    18. ReactDOM.render(, mountNode); 

    6: 每一个React组件都有故事

    以下仅适用于类组件(扩展为React.Component的组件)。 函数组件有一个略有不同的故事。

    1. 首先,我们为React定义一个模板,以从组件创建元素。
    2. 然后,我们指示React在某处使用它。 例如,在另一个组件的render调用中,或者使用ReactDOM.render。
    3. 然后,React实例化一个元素,并给出一组我们可以使用this.props访问的props。 那些props正是我们在上面的步骤2中传递的。
    4. 由于它都是JavaScript,所以构造方法将被调用(如果已经定义的话)。 这是我们要说的***个:组件生命周期方法。
    5. 然后React计算render方法(虚拟DOM节点)的输出。
    6. 由于这是React渲染元素的***次,React将与浏览器进行通信(代表我们使用DOM API)来显示元素。 这个过程通常被称为挂载。
    7. 然后,React调用另一个生命周期方法,称为componentDidMount。 我们可以使用这种方法做一些事情,例如,在DOM上做一些我们现在知道在浏览器中支持处理的东西。 在此生命周期方法之前,我们处理的DOM全部是虚拟的。
    8. 一些组件故事在这里结束。 出于各种原因,其他组件可以从浏览器DOM中解除挂载。 在后一种情况发生之前,React调用另一个生命周期方法componentWillUnmount。
    9. 任何已挂载元件的状态可能会改变。 该元素的父代可能会重新呈现。 在任一种情况下,安装的元件可能会接收不同的props。 这里的魔法发生了,我们现在开始需要React了! 在此之前,我们完全不需要做任何事情
    10. 这个组件的故事继续下去,但在之前,我们需要了解我所说的这个状态。

    7: React组件有一个私有状态

    以下也仅适用于类组件。 有没有人提到有些人把只做展现的组件叫做哑巴?

    状态类字段是任何React类组件中的特殊字段。 React监视每个组件状态以进行更改。 但是对于React要有效地执行这些操作,我们必须通过另一个需要学习的React API函数来更改state字段,this.setState:

     
     
     
    1. // Example 13 -  the setState API
    2. // https://jscomplete.com/repl?j=H1fek2KH-
    3. class CounterButton extends React.Component {
    4.   state = {
    5.     clickCounter: 0,
    6.     currentTimestamp: new Date(),
    7.   };
    8.   
    9.   handleClick = () => {
    10.     this.setState((prevState) => {
    11.      return { clickCounter: prevState.clickCounter + 1 };
    12.     });
    13.   };
    14.   
    15.   componentDidMount() {
    16.    setInterval(() => {
    17.      this.setState({ currentTimestamp: new Date() })
    18.     }, 1000);
    19.   }
    20.   
    21.   render() {
    22.     return (
    23.       
    24.         Click
    25.         

      Clicked: {this.state.clickCounter}

    26.         

      Time: {this.state.currentTimestamp.toLocaleString()}

    27.       
    28.     );
    29.   }
    30. }
    31. // Use it
    32. ReactDOM.render(, mountNode); 

    这是了解state最重要的例子。 它将完善您对React交互方式的基础知识。 在这个例子之后,还有一些你需要学习的小事情,但是从这一点来看,它主要是你和你的JavaScript技能。

    我们来看一下实例13,从类字段开始。 它有两个。 特殊状态字段被初始化为一个对象,该对象包含起始值为0的clickCounter,以及起始值为new Date()的currentTimestamp。

    第二个类字段是一个handleClick函数,我们传递给render方法中的button元素的onClick事件。 handleClick方法使用setState修改此组件实例状态。 注意到这一点。

    我们在componentDidMount生命周期方法内部启动的间隔定时器中修改状态。 它每秒钟打勾并执行调用this.setState。

    在render方法中,我们使用了正常读取语法对state两个属性的读取。 没有特殊的API。

    现在,请注意,我们使用两种不同的方式更新了状态:

    1. 传递返回一个对象的函数。 我们handleClick函数中实现了这部分内容。
    2. 通过传递一个常规对象。 我们在间隔回调中实现了。

    这两种方式都是可以接受的,但是当您同时读取和写入状态时,***个是***的(我们这样做)。 在间隔回调之内,我们只写给状态,而不是读取它。 当两难时,始终使用***个函数参数语法。 它更加安全,因为setState实际上是一个异步方法。

    我们如何更新状态? 我们返回一个包含我们要更新的值的对象。 注意在两次调用setState中,我们只是从state字段传递一个属性,而不是两者。 这是完全可以的,因为setState实际上将您传递的内容(函数参数的返回值)与现有状态合并。 因此,在调用setState时不指定属性意味着我们不希望更改该属性(而不是删除它)。

    8:React是可以响应的

    React从它对状态变化做出响应的事实(虽然不是反应性的,而是按计划进行)而得名。 有一个笑话,反应应该被命名为Schedule!

    然而,当任何组件的状态被更新时,我们用肉眼看到的是React对该更新做出反应,并自动反映浏览器DOM中的更新(如果需要)。

    将render函数输入视为两者

    1. 从父元素得到props
    2. 可以随时更新的内部私有状态

    当渲染功能的输入变化时,其输出可能会改变。

    React保留了渲染历史的记录,当它看到一个渲染与前一个渲染不同时,它将计算它们之间的差异,并将其有效地转换为在DOM中执行的实际DOM操作。

    9: React是你的代理

    您可以将React视为我们聘请的与浏览器通信的代理。 以上面的当前时间戳显示为例。 我们不是手动去浏览器并调用DOM API操作来每秒查找和更新p#timestamp元素,而是在组件状态上更改了一个属性,而React代表我们与浏览器进行通信。 我相信这是真正受欢迎的真正原因。 我们讨厌浏览器(和所说的DOM语言的很多方言),React自愿为我们做所有的谈话,免费!

    10: 每个React组件都有一个故事(第2部分)

    现在我们知道一个组件的状态,以及当这个状态改变了一些魔法的时候,让我们来学习关于该过程的***几个概念。

    1. 组件可能需要在其状态更新时重新呈现,或者当其父级决定更改传递给组件的props时,该组件可能需要重新呈现
    2. 如果后者发生,React会调用另一个生命周期方法componentWillReceiveProps。
    3. 如果状态对象或传入props被更改,则React有一个重要的决定。 组件应该在DOM中更新吗? 这就是为什么它在这里调用另一个重要的生命周期方法,shouldComponentUpdate。 这个方法是一个实际的问题,所以如果你需要自己定制或优化渲染过程,你必须通过返回true或false来回答这个问题。
    4. 如果没有指定customComponentUpdate,React默认是一个非常聪明的事情,在大多数情况下实际上足够好。
    5. 首先,React在此时调用另一个生命周期方法componentWillUpdate。 然后React将计算新的渲染输出并将其与***渲染的输出进行比较。
    6. 如果渲染的输出完全一样,React什么都不做。
    7. 如果存在差异,则React会将这些差异映射到浏览器内。
    8. 无论如何,由于更新过程无论如何(即使输出完全相同),React会调用最终的生命周期方法componentDidUpdate。

    生命周期方法实际上是舱口。 如果你没有做任何事情,你可以创建没有他们的完整的应用程序。 他们可以用来非常方便地分析应用程序中发生的情况,并进一步优化了React更新的性能。

    网页标题:一篇包含了React所有基本点的文章
    URL网址:http://www.shufengxianlan.com/qtweb/news42/305092.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    微信小程序知识

    同城分类信息