1. 首页
  2. IT教程

React—最简洁的技术学习(一)

React—最简洁的技术学习(一)

大家好,又见面了,我是你们的朋友全栈君。

摘要(本人感受)

此文章是本人在学习React过程中总结起来的一些小经验,因自己在网络上找到的React的教程很多都是一上来就是构建复杂的React环境,Webpack,ES2015等技术的使用,让其简洁的React变得复杂化。本文只为分享简洁的学习过程,让大家理解React,当然其中的不足之处,还望大家指出,谢谢。

React特点

1、虚拟DOM: React也是以数据驱动的,每次数据变化React都会扫码整个虚拟DOM树,自动计算与上次虚拟DOM的差异变化,然后针对需要变化的部分进行实际的浏览器DOM更新。

2、组件化: React可以从功能角度横向划分,将UI分解成不同组件,各组件都独立封装,整个UI是由一个个小组件构成的一个大组件,每个组件只关系自身的逻辑,彼此独立。

3、单项数据流:React设计者认为数据双向绑定虽然便捷,但在复杂场景下副作用也是很明显,所以React更倾向于单向的数据流动-从父节点传递到子节点。

理解了React的特点之后,开始学习React的基本组件。

一、 Hello World开始


刚开始学习React,暂时不考虑工程化的问题,React的运行环境十分简单,只需要在HTML文件中引入2个js(react.js 和 react-dom.js)文件即可开始工作。

react.js:实现React核心逻辑,但是与具体的渲染引擎无关,从而可以跨平台公用。如果需要迁移到React Native,这部分逻辑是不需要改变的。

react-dom.js:包含了具体的DOM渲染更新逻辑,以及服务端渲染的逻辑,这部分就是与浏览器相关了。

作为程序员,学习的第一步就是 Hello World的开始。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="./react.js"></script>
    <script src="./react-dom.js"></script>
  </head>
  <body>
      <div id="container"></div>
      <script>
            //创建Hello组件
            var HelloComponent =React.createClass({
                render:function(){
                    return React.createElement('h1',null,'Hello world');
                }
            });
            
            ReactDOM.render(
                React.createElement(HelloComponent,null),
                document.getElementById('container')
            )
      </script>
  </body>
</html>

在上面这段代码中 React.createClass的作用是注册一个组件类HelloComponent,这个组件类只包含了一个render函数,这个函数通过调用React.createElement实现了以下HTML的内容:

这是React在创建组件时使用的基本语法,在后面我们学习了JSX的语法后,这种写法就不适用了,所以目前先记住这种使用。

二、初识JSX语法


JSX也就是JavaScript XML,它是使用XML标记来创建虚拟DOM和声明组件,在上节介绍中,我们发些在书写方面有些麻烦,影响开发效率问题,比如会出现JavaScript代码与标签混写一起、缺乏一些模板的支持,但是使用JSX,则可以有效的解决这些问题。

加入JSX语法支持

如果我们在代码书写中需要使用JSX的语法,可以使用Babel来进行转换,个人是直接引入Babel的核心文件browser.min.js。如果需要使用,可以去网上提供的静态资源库引用www.bootcdn.cn/ ,可以自行搜索下载哦。

使用JSX语法书写Hello World

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
  </head>
  <body>
      <div id="container"></div>
      
      <script type="text/babel">
       var HelloComponent =React.createClass({
            render:function(){
                return <h1>Hello World</h1>
            }
        });
        ReactDOM.render(
            <HelloComponent />,
            document.getElementById('container')
        )
      </script>
      
  </body>
</html>

通过这种写法可以发现JSX的好处:

  • 可以使用熟悉的语法来仿照HTML来定义虚拟DOM;
  • 与JavaScript之间等价转换,程序代码更加直观;
  • JSX还可以防注入攻击。React DOM 在渲染之前默认会过滤所有传入的值。它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。

Vue中可以使用{
{ }}表达式的写法,React中我们只需要一个{ }表达式即可支持。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
  </head>
  <body>
      <div id="container"></div>
      
          <script type="text/babel">
           var HelloComponent =React.createClass({
                render:function(){
                    //三元表达式
                    return <h1>Hello {
   
   true?'World2':''}</h1>
                }
            });
            ReactDOM.render(
                <HelloComponent />,
                document.getElementById('container')
            )
          </script>
      
  </body>
</html>

需要注意的是表达式中不支持if…else这样的语句,但是支持三元运算符和二元运算符。

三、进阶JSX语法


上一节中了解到基本的JSX语法,这节深入了解一下,这边会给大家提醒一些小坑,帮助大家更好的节约学习时间。

JSX数组遍历 学习过vue的小伙伴们一定知道,在vue中通过v-for的方式去遍历出数组中的内容,而在React中用JSX语法中用表达式的方式去进行数组的遍历。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello World</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
  </head>
  <body>
      <div id="container"></div>
      <script type="text/babel">
      
        let names = ['React','Vue','Angular'];
        
        var NameComponent = React.createClass({
            render:function(){
                //  此处有坑哦
                return <div>
                        {
                            names.map(function(name){
                                return <div key={name}>Hello,{name}!</div>
                            })
                        }
                    </div>
            }
        });

        ReactDOM.render(
            <NameComponent />,
            document.getElementById('container')
        )
      </script>
  </body>
</html>

在我们注重格式化书写的时候,可能会在render函数中的return后进行断开书写,这样显得格式化更好些:

如果这样书写,你将会看到:

控制台报错了,一脸懵!!!

在React中,render函数中的return后必须接上返回内容,否则会认为无值返回,控制台会报错提示。在其他的return中若没接上返回内容,虽然不会报错,但是会以无值形式返回,导致渲染不出后面的数据。

在此你可以在return后面加上一个(),这样你就可以进行格式化书写了:

我们发现在数组遍历中我们都需要加上遍历的key,无论是vue或者是React中都需要使用key,如果没有key虽然会出来效果,但是控制台会报错。key的作用是生成虚拟DOM时,需要使用key来进行标记,DOM更新时进行比较。

    {
        names.map(function(name){
            return <div key={name}>Hello,{name}!</div>
        })
    }

如果无key的添加:

数组中的JSX

JSX允许在模板中插入JavaScript变量,如果这个变量是一个数组,就会展开这个数组的所有成员。

let arr=[
    <h1 key="1">我是React!</h1>,
    <h2 key="2">我是Vue!</h2>
];
ReactDOM.render(
    <div>{arr}</div>, 
    document.getElementById('container') 
)

四、Props和State的学习


React组件可以把它看作带有props属性集合和state状态集合并且构造出一个虚拟DOM结构的对象。

Props

props是组件中固有属性的集合,其数据由外部传入,一般在整个组件的生命周期中都是只读的。属性的初始值通常由React.createElement函数或者JSX中标签的属性值进行传递,并合并到组件实例对象的this.props中。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Props</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
    <style>
    </style>
  </head>
  <body>
      <div id="container"></div>
      <script type="text/babel">
        
        let HelloBox = React.createClass({
            render:function(){
                return (<div>{
   
   'Hello '+this.props.name}</div>)
            }
        })

        ReactDOM.render(
            <HelloBox name='React' />,
            document.getElementById('container')
        )

      </script>
  </body>
</html>

this.props后面携带的值需要与组件传递的属性值保持一致。

State

组件总是需要和用户互动的。React的一大创新,就是将界面组件看成一个状态机,用户界面拥有不同状态并根据状态进行渲染输出,用户界面和数据始终保持一致。开发者的主要工作就是定义state,并根据不同的state渲染对应的用户界面。

举个实例让大家感受一下:

这个例子包含一个input框和一个button,通过点击button来改变input的disable状态。
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Props和State</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.mim.js"></script>
    <style>
        input:disabled{
            border: 1px solid red;
        }
        button{
            cursor: pointer
        }
    </style>
  </head>
  <body>
      <div id="container"></div>
      <script type="text/babel">

        var TextBoxComponent = React.createClass({
            
            //初始化原始数据 ,与Vue中的data类似
            getInitialState:function(){
                return {
                    enable:true
                }
            },

            render:function(){
                return(
                    <p>
                        //通过this.state去获取enable的初始化值
                        <input type="text" disabled={this.state.enable} /> 
                        <button>改变状态</button>
                    </p>

                )
            }
        })

        ReactDOM.render(
            <TextBoxComponent />,
            document.getElementById('container')
        )

      </script>
  </body>
</html>

目前暂时还不能点击button去改变disable的状态,在React单向数据流的条件下,我们无法向Vue那样直接去操作改变disable的状态,需要去借助setState函数去处理。

setState函数

通知React组件数据发生变化的方法是调用成员函数setState(data,callback)。这个函数会合并data到this.state,并重新渲染组件。渲染完成后,调用可选的callback回调。(大部分情况下不需要调用回调,因为React会负责把界面更新到最新状态)

因此我们给button加上我们的点击事件,通过setState去改变disable的值。

在上面的代码中我们需要注意几点:

  • getInitialState函数必须有返回值,可以是null,false,一个对象。
  • 访问state数据的方法是”this.state.属性名”。
  • 变量用{ }包裹,不需要再加双引号。

props与state的区别

props不能被其所在的组件修改,从父组件传递进来的属性不会在组件内部更改;

state只能在所在组件内部更改,或在外部调用setState函数对状态进行间接修改。

五、React生命周期


一个组件完整的生命周期包含实例化阶段、活动阶段、销毁阶段三个阶段。每个阶段又由相应的方法管理。

这些过程中涉及三个主要的动作术语:

  • mounting: 表示正在挂载虚拟DOM到真实DOM;
  • updating: 表示正在被重新渲染;
  • unmounting:表示正在将虚拟DOM移除真实DOM。

在每个动作术语中提供了一些函数供我们使用:

  • componentWillMount():表示将要或正挂载过程中;
  • componentDidMount():表示已经挂载完成了;
  • componentWillUpdate(object nextProps, object nextState):表示将要或正在重新渲染;
  • componentDidUpdate(object prevProps, object prevState):表示重新渲染完成了;
  • componentWillUnmount():表示虚拟DOM卸载了。

通过一个简单的实例,来看React组件的生命周期。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>生命周期</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
    <style>
    </style>
  </head>
  <body>
      <div id="container"></div>
      <script type="text/babel">

      var AddCount = React.createClass({
      
          //数据初始化
          getInitialState:function() {
              console.log('1-getInitialState')
              return {
                  count:1
              }
          },
          
          componentWillMount() {
              console.log('2-componentWillMount')
          },

          componentDidMount(){
              console.log('3-componentDidMount')
          },

          componentWillUpdate(){
              console.log('4-componentWillUpddate')
          },
          
          componentDidUpdate(){
              console.log('5-componentDidUpdate')
          },

          handleClick:function(event){
              this.setState({
                  count:this.state.count+1
              })
          },
          
          render:function(){
              return(
                  <p>
                    {this.state.count} <br/>
                    <button onClick={this.handleClick}>点击加一</button>
                  </p>
              )
          }
      })


      ReactDOM.render(
          <AddCount />,
          document.getElementById('container')
      )
      </script>
  </body>
</html>

点击之后:

六、获取真实DOM节点


React中的DOM也是虚拟DOM(virtual DOM),这点跟Vue非常类似。只有当它插入文档以后,才会变成真实的DOM。React也是在虚拟DOM发生变化时,进行比对后,只渲染变化的部分,它是React极高性能的主要原因之一。

但是有时候我们需要从组件中获取真实的DOM节点,来进行业务逻辑的编写,React为我们提供了ref属性。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>ref</title>
    <script src="./common/react.js"></script>
    <script src="./common/react-dom.js"></script>
    <script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.mim.js"></script>
    <style>
    </style>
  </head>
  <body>
      <div id="container"></div>
      <script type="text/babel">
        var MyComponent = React.createClass({

            handleClick:function(event){
                //通过this.refs去获取,这点和Vue相似
                this.refs.myTitleInput.focus();
            },

            render:function() {
                return(
                    <div>
                        <input type="text" ref="myTitleInput" /> <br/>
                        <input type="button" value="Focus on input" onClick={this.handleClick} />
                    </div>
                )
            }
        })

        ReactDOM.render(
            <MyComponent/>,
            document.getElementById('container')
        )
      </script>
  </body>
</html>

通过这些知识点的学习,可以初步的了解到React的基本知识。下一章将分享React的表单应用。如果有不对的地方还希望大家留言指出,谢谢!

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/107016.html原文链接:https://javaforall.cn

原创文章,作者:夜风博客,如若转载,请注明出处:https://www.homedt.net/269595.html