重学React之基础知识

简介: 重学React之基础知识

React开发依赖,三个库的理解


开发React必须依赖三个库:


  • react:包含react所必须的核心代码


  • react-dom:react渲染在不同平台所需要的核心代码


  • babel:将jsx转换成React代码的工具 这三个库是各司其职的,目的就是让每一个库只单纯做自己的事情:


  • 在React的0.14版本之前是没有react-dom这个概念的,所有功能都包含在react里。


  • 为什么要进行拆分呢?原因就是react-native。


  • react包中包含了react和react-native所共同拥有的核心代码。


  • react-dom针对web和native所完成的事情不同:


  • web端:react-dom会将jsx最终渲染成真实的DOM,显示在浏览器中。


  • native端:react-dom会将jsx最终渲染成原生的控件(比如Android中的Button,iOS中的UIButton)。 babel是什么呢? 前端使用非常广泛的编辑器、转移器。


  • 比如当下很多浏览器并不支持ES6的语法,但是确实ES6的语法非常的简洁和方便,我们开发时希望使用它。


  • 那么编写源码时我们就可以使用ES6来编写,之后通过Babel工具,将ES6转成大多数浏览器都支持的ES5的语法。 React和Babel的关系:


  • 默认情况下开发React其实可以不使用babel。但是前提是我们自己使用 React.createElement 来编写源代码,它编写的代码非常的繁琐和可读性差。


  • 那么我们就可以直接编写jsx(JavaScript XML)的语法,并且让babel帮助我们转换成React.createElement。 所以,我们在编写React代码时,这三个依赖都是必不可少的。


那么,如何添加这三个依赖:


  • 直接CDN引入


react依赖: <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
 react-dom依赖:<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
 babel依赖:<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>


如果需要加载指定版本的 reactreact-dom,可以把 17 替换成所需加载的版本号。这里有一个crossorigin的属性,这个属性的目的是为了拿到跨域脚本的错误信息。


  • 通过React的脚手架。


npm install create-react-app -g


npx create-react-app my-app
    cd my-app
    npm start


JSX语法


JSX是什么?


  • JSX是一种JavaScript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起就是一段XML语法。


  • 它用于描述我们的UI界面,并且其完成可以和JavaScript融合在一起使用。


  • 它不同于Vue中的模块语法,你不需要专门学习模块语法中的一些指令(比如v-for、v-if、v-else、v-bind)。


JSX的书写规范


  • JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个div原生。


  • 为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写。


  • JSX中的标签可以是单标签,也可以是双标签。注意:如果是单标签,必须以/>结尾。


JSX嵌入变量


  • 当变量是Number、String、Array类型时,可以直接显示。


  • 当变量是null、undefined、Boolean类型时,内容为空。


  • 如果希望可以显示null、undefined、Boolean,那么需要转成字符串;


  • 转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;


  • 对象类型不能作为子元素。


JSX嵌入表达式


  • 运算表达式


  • 三元运算符


  • 执行一个函数


JSX中class属性的绑定


可以发挥自己的想象,react中className的绑定是很灵活的。


  • 字符串拼接绑定


this.state={
      isFlag: true
    }
    <p className={"aa bb "+(this.state.isFlag? "active":"")}>pppp</p>


  • 数组绑定


this.state={
      isFlag: true,
      classs: ["a","b","c"]
    }
    <p className={this.state.classs.join(" ")}>oooo</p>


JSX中style属性的绑定


  • 通过键值对绑定即可。


this.state={
      isFlag: true,
      styles: {
        color: "red",
        fontSize: "30px"
      }
    }
    <p style={{...this.state.styles,marginTop: this.state.isFlag? "200px":""}}>oooo</p>


React事件绑定


React 事件的命名采用小驼峰式(camelCase),而不是纯小写。我们需要通过{}传入一个事件处理函数,这个函数会在事件发生时被执行。


类组件中事件中的this绑定


  • 在调用方法的时候利用bind绑定this


return (
      <div>
        {/*这里的this表示的是render环境下的this,所以就是app*/}
        <button onClick={this.handleClick.bind(this)}>请点我一下!</button>
      </div>
    )


  • 使用 ES6 class fields 语法,就是给类定义属性,让该属性等于一个箭头函数


btnClick = () => {
    console.log(this);
    console.log(this.state.message);
 }


  • 事件监听时传入箭头函数(推荐): 在使用方法时,用一个箭头函数将其包裹,返回该函数


return (
  <div>
    {/*这里的箭头函数中的this表示的是render环境下的this,所以就是app*/}
    <button onClick={() => { this.handleClick() }}>请点我一下!</button>
  </div>
 )


  • 直接在构造函数中利用bind显示的绑定this


constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this)
  }


函数参数的传递


在执行事件函数时,有可能我们需要获取一些参数信息:比如event对象、其他参数。


  • 如果只需要event对象 如果函数不需要传递参数,但是需要事件对象。则直接写(箭头函数绑定this的方法除外),由于我们传入的事件函数是系统内部调用的。所以会传入一个事件对象,我们就可以拿到。


  • 如果只需要我们自己的参数 如果需要传参,但是不需要事件对象,则直接传递参数,没有事件对象什么事。


  • 如果事件对象event和自定义参数都需要 获取的时候事件对象都是最后一个参数(通过bind绑定的this),而通过箭头函数绑定this,则在什么位置传入,他就在什么位置获取。


<button onClick={(e) => {this.handleClick(e,"pp")}}>anniu</button> // 传入的位置就是event
    <button onClick={this.handleClick.bind(this,"pp")}>anniu</button> // 系统自己传入,会自动作为最后一个参数。


条件渲染


React 中的条件渲染和 JavaScript 中的一样,使用 JavaScript 运算符 if 或者条件运算符去创建元素来表现当前的状态,然后让 React 根据它们来更新 UI。


  • 通过三目运算符


{
      this.state.isFlag? <div>正确</div>:<div>错误</div>
    }


  • 通过逻辑与


{
      this.state.isFlag&&<div>正确</div>
    }


  • 通过if语句


实现vue中v-show的效果。我们知道v-show只是控制了display属性,来实现元素的显示或者隐藏。


this.state = {
        isFlag: true
    }
    <div style={{display: this.state.isFlag ? "block" : "none" }}> 元素的显示或者隐藏 </div>


列表渲染


所有的列表渲染操作之后都需要去调用map来做渲染。


  • 通过数组filter方法过滤后,需要调用map,来做渲染映射。


this.state = {
      list: [
        "zh","llm","zhvllm"
      ]
    }
    {
      this.state.list.filter(item => item[0]==='z').map(item => {
        return <div>{item}</div>
      })
    }


  • 通过数组slice方法截取后,需要调用map, 来做渲染映射。


this.state = {
      list: [
        "zh","llm","zhvllm"
      ]
    }
    {
      this.state.list.slice(0, 2).map(item => {
        return <div>{item}</div>
      })
    }


列表渲染绑定key


let message = null
    if(this.state.isFlag) {
        message = <div>"true"</div>
    }else {
        message = <div>"false"</div>
    }


JSX的本质


实际上,jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。所有的jsx最终都会被转换成React.createElement的函数调用。


createElement需要传递三个参数:


  • type: 当前ReactElement的类型。


  • 如果是标签元素,那么就使用字符串表示 “div”。


  • 如果是组件元素,那么就直接使用组件的名称。


  • config


  • 所有jsx中的属性都在config中以对象的属性和值的形式存储。


  • children


  • 存放在标签中的内容,以children数组的方式进行存储。 我们可以通过这个网站:babel,来查看jsx是如何转化为React.createElement。


虚拟DOM


React.createElement 最终创建出来一个 ReactElement对象。


这个ReactElement对象是什么作用呢?


React利用ReactElement对象组成了一个JavaScript的对象树。它即是虚拟DOM (Virtual DOM)。


<script type="text/babel">
    class ElHow extends React.Component {
      constructor(props) {
        super(props)
        this.state={
        }
      }
      render () {
        const elementObject=React.createElement("div",null, /*#__PURE__*/React.createElement("div",null, /*#__PURE__*/React.createElement("p",null,"\u6587\u672C")), /*#__PURE__*/React.createElement("div",null, /*#__PURE__*/React.createElement("input",{
          type: "text"
        })));
        console.log(elementObject)
        return elementObject
      }
    }
    ReactDOM.render(<ElHow />,document.getElementById('root'))
  </script>


网络异常,图片无法展示
|


为什么要采用虚拟DOM,而不是直接修改真实的DOM呢?


  • 很难跟踪状态发生的改变:原有的开发模式,我们很难跟踪到状态发生的改变,不方便针对我们应用程序进行调试。


  • 操作真实DOM性能较低:传统的开发模式会进行频繁的DOM操作,而这一的做法性能非常的低。


一个购物车小案例


  • 注意要维持state数据的不可变性。


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
  <title>Document</title>
  <style>
    table {
      border-collapse: collapse
    }
  </style>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    class ElHow extends React.Component {
      constructor(props) {
        super(props)
        this.state={
          list: [{
            name: "nodejs",
            id: 1,
            date: "2006-9",
            price: 85,
            num: 1,
          },{
            name: "react",
            id: 2,
            date: "2006-2",
            num: 1,
            price: 59
          },{
            name: "vue",
            id: 3,
            date: "2008-10",
            num: 1,
            price: 39
          },{
            name: "javascript",
            id: 4,
            date: "2006-3",
            price: 128,
            num: 1
          }]
        }
      }
      handleDown=(index) => {
        // console.log(index)
        this.setState({
          list: this.state.list.map((item,indey) => {
            if(index==indey&&item.num>1) {
              return {
                ...item,
                num: item.num-1
              }
            }
            return item
          })
        })
      }
      handleUp=(index) => {
        this.setState({
          list: this.state.list.map((item,indey) => {
            if(index==indey) {
              return {
                ...item,
                num: item.num+1
              }
            }
            return item
          })
        })
      }
      handleRemove=(index) => {
        this.setState({
          list: this.state.list.filter((item,indey) => index!=indey)
        })
      }
      render () {
        let total=0;
        this.state.list.forEach(item => {
          total+=(item.num*item.price)
        })
        return (
          <div>
            {
              !this.state.list.length? <div>购物车为空~</div>:
                (
                  <div>
                    <table border="1">
                      <thead>
                        <tr>
                          <th>编号</th>
                          <th>书籍名称</th>
                          <th>出版日期</th>
                          <th>价格</th>
                          <th>购买数量</th>
                          <th>操作</th>
                        </tr>
                      </thead>
                      <tbody>
                        {
                          this.state.list.map((item,index) => {
                            return (
                              <tr key={item.id}>
                                <td>{item.id}</td>
                                <td>《{item.name}》</td>
                                <td>{item.date}</td>
                                <td>¥{item.price}</td>
                                <td>
                                  <button
                                    disabled={item.num===1}
                                    onClick={(e) => {this.handleDown(index)}}
                                  >-</button>
                                  {item.num}
                                  <button
                                    onClick={(e) => {this.handleUp(index)}}
                                  >+</button>
                                </td>
                                <td>
                                  <button
                                    onClick={(e) => {this.handleRemove(index)}}
                                  >移除</button></td>
                              </tr>
                            )
                          })
                        }
                      </tbody>
                    </table>
                    <div>总价钱:¥{total}</div>
                  </div>
                )
            }
          </div>
        )
      }
    }
    ReactDOM.render(<ElHow />,document.getElementById('root'))
  </script>
</body>
</html>


相关文章
|
4天前
|
XML JavaScript 前端开发
VUE基础知识:Vue.js和React的主要区别是什么?
VUE基础知识:Vue.js和React的主要区别是什么?
547 0
|
前端开发 JavaScript API
React 基础知识——Ref和API | 学习笔记
快速学习 React 基础知识——Ref 和 API
87 0
|
前端开发 开发者 容器
React基础知识——Mixin 和 表单 | 学习笔记
快速学习 React 基础知识—— Mixin 和 表单
74 0
|
前端开发 开发者 容器
React 基础知识——属性状态 | 学习笔记
快速学习 React 基础知识——属性状态
58 0
|
前端开发 JavaScript 开发者
React 基础知识——事件和组合 | 学习笔记
快速学习 React 基础知识——事件和组合
80 0
React 基础知识——事件和组合 | 学习笔记
|
XML 前端开发 JavaScript
React 基础知识 —— JSX | 学习笔记
快速学习 React 基础知识 —— JSX
93 0
React 基础知识 —— JSX | 学习笔记
|
前端开发 JavaScript 数据管理
React基础知识
React基础知识
87 0
React基础知识
|
前端开发 JavaScript 测试技术
|
JavaScript 前端开发
学习React之前要掌握的JS基础知识
学习React之前要掌握的JS基础知识
144 0
学习React之前要掌握的JS基础知识
|
前端开发 JavaScript API
React入门与基础知识
观看阿里云react入门视频的笔记
7771 0