【React】类组件,JSX语法,JSX原理,传递参数,条件渲染,列表渲染

❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
🙏 个人名言:不可控之事 乐观面对
😍 系列专栏:

React

  • 需要引入三个依赖包,React,React-dom,babel(这个包是因为React使用jsx语法编写,而jsx语法浏览器不识别,所以需要一个包将代码转换为javascript代码)
    在这里插入图片描述
  • 在React18之前,使用的是ReactDOM.render()来渲染页面,React18之后用createRoot之后再.render实现
<!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" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <div id="app"></div>
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script type="text/babel">
      //React18之前,React
      ReactDOM.render(<h2>Hello World</h2>, document.querySelector("#root"));
      //React18之后
      const app = ReactDOM.createRoot(document.querySelector("#app"));
      app.render(<h2>Hello React!</h2>);
    </script>
  </body>
</html>

在这里插入图片描述

小案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      //  编写React代码
      const root = ReactDOM.createRoot(document.getElementById("root"));

      // 将文本定义成变量
      let message = "Hello world!";

      //监听按钮的点击
      function btnClick() {
        message = "Click";
        rootRender();
      }
      rootRender();
      function rootRender() {
        root.render(
          <div>
            <h2>{message}</h2>
            <button onClick={btnClick}>修改文本</button>
          </div>
        );
      }
    </script>
  </body>
</html>

使用组件(类组件)

  • 通过封装成组件,增加代码的内聚性,将**数据,方法,渲染内容(render方法)**三者放在一个组件里面

补充:
1.默认函数this绑定的是window,在严格模式下绑定的是undefined
2.为什么改变this绑定不能用call或者apply
在这里插入图片描述
3.super函数执行步骤
在这里插入图片描述

如何封装一个组件

  • 如何封装一个组件?
    - 封装一个类组件,类组件需要**继承React.Component** ,

数据存放在什么位置、更新数据(setState)

  • 数据分为参与界面更新的数据和不参与界面更新的数据
    参与界面更新的数据要放在当前对象的state中,更新数据的时候有两步,第一是修改message数据值,第二是重新执行render函数,但是this.setState方法就把重新渲染render函数的步骤默认执行的
    在这里插入图片描述

在类中的方法,默认是严格模式,this是undefined。如果是babel转换过的代码,也必然是严格模式,this也是undefined

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      class App extends React.Component {
        //组件数据
        constructor() {
          super();
          this.state = {
            message: "hello world",
            name: "why",
            age: "18",
          };
        }
        //组件方法(实例方法)
        btnClick() {
          this.setState({
            message: "hello react",
          });
        }

        //渲染内容render方法
        render() {
          return (
            <div>
              <h2>{this.state.message}</h2>
              <button onClick={this.btnClick.bind(this)}>修改文本</button>
            </div>
          );
        }
      }

      const root1 = ReactDOM.createRoot(document.getElementById("root"));
      root1.render(<App />);
    </script>
  </body>
</html>

小案例(电影列表展示)

  • JSX大括号里不能写对象,可以写数组
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      const root = ReactDOM.createRoot(document.getElementById("root"));

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            movies: ["星际穿越", "流浪地球", "大话西游", "独行乐曲"],
          };
        }

        render() {
          return (
            <div>
              <h2>电影列表</h2>
              <ul>
                {this.state.movies.map((movie) => (
                  <li>{movie}</li>
                ))}
              </ul>
            </div>
          );
        }
      }

      root.render(<App />);
    </script>
  </body>
</html>

计数器案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      const root = ReactDOM.createRoot(document.querySelector("#root"));

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            message: "hello world",
            counter: 100,
          };
          // this.increment = this.increment.bind(this)
          // this.decrement = this.decrement.bind(this)
        }

        render() {
        //js的解构语法
          const { message, counter } = this.state;
          return (
            <div>
              <h2>当前计数:{counter}</h2>
              <button onClick={this.increment.bind(this)}>+1</button>
              <button onClick={this.decrement.bind(this)}>-1</button>
            </div>
          );
        }

        increment() {
          this.setState({
            counter: this.state.counter + 1,
          });
        }
        decrement() {
          this.setState({
            counter: this.state.counter - 1,
          });
        }
      }
      root.render(<App />);
    </script>
  </body>
</html>

JSX语法

  • 正常我们如果这样写JS代码的话,浏览器是会报错的,但是我们如果在babel中这样写,babel就会自动帮我们转换,转成了React.createElement()这种形式,浏览器就会识别这种函数

在这里插入图片描述

  • 其实就是将html的代码写在了js上面,然后通过render函数进行渲染,它用于描述我们的UI界面,完成可以和js融合在一起使用

为什么React选择了JSX

  • 因为渲染逻辑本质上与其他UI逻辑存在耦合,比如UI需要绑定事件,UI需要展示数据状态,在某些状态发生改变时,有需要改变UI,所以React将html,css都放在了JS中,将它们组合在了一起,这个地方就是组件(类组件或者函数组件)

书写规范

  • 1.jsx的结构中(return括号里)只能由一个根元素
    在这里插入图片描述

  • 2.JSX结构样式通常惠包裹一个(),为了方便我们阅读,将整个JSX当作一个整体,实现换行

  • 3.注释:在这里插入图片描述

JSX插入的内容

  • Number,String,Array类型是可以直接插入的,并且可以直接显示

  • 如果是undefined,null,boolean类型在界面上显示为空
    在这里插入图片描述

  • Object类型写在jsx大括号中不显示
    在这里插入图片描述

  • 可以插入表达式,例如firstName + " " + lastName

  • 可以插入三元运算符

  • 可以执行一个函数(这个注意和只传入函数的指针区别,传入函数指针不加小括号,需要bind绑定this,而传入执行函数直接在传入的函数后面加小括号,就直接执行函数了,跟this绑定是无关的)

JSX绑定基本属性

在这里插入图片描述

JSX绑定class属性

  • 如果是静态类,写成className
  • 如果是动态加载Class,有两种方式,一种是模板字符串,一种是数组
    在这里插入图片描述

动态绑定样式

  • 如果动态绑定样式,在JSX中写一个对象,注意只有在JSX作为子元素插入内容的时候不能写成对象,但是作为属性是可以写成对象的并且JS不支持“-”,所以需要写成驼峰式
    在这里插入图片描述

JSX本质及原理

List item
因为jsx的语法浏览器是不识别的,这段代码是经过babel转换的,每当遇到一个标签,都会转换成React.createElement(“div”,{classNamexxxx},[]),之后就会形成一个树结构的元素,每个元素都是一个对象,这个树结构就是虚拟DOM,实际上JSX就是React.createElement(component,props,…children)的函数的语法糖,通过React.createElement最终创建出来一个ReactElement对象,React利用这个对象组成了一个javascript对象树,这个对象树就是虚拟DOM

vue中的话,专门有代码用来解析templete,解析完templete之后就会生成一个render函数,render函数中调用了大量的h函数,调用完h函数,生成了大量的一个一个的对象,对象和对象之间产生联系,最终生成了一个虚拟DOM

createElement传递的参数

在这里插入图片描述

React事件绑定

this问题:如果函数方法中用到了this,那么这个this就是undefined,因为this.btn1Click是传入了函数的指针
this底层是这样的原理:一些列操作之后,click变量就相当于是obj.foo指向的指针,然后调用click()函数之后,这个是this的默认指向,因为babel中默认是严格模式,所以this的指向就是undifined了
在这里插入图片描述
实际开发中这样的this指向的就是undefined
在这里插入图片描述

bind方式绑定

在这里插入图片描述

ES6的 class fields方式绑定

  • 就相当于把函数赋值给变量
    在这里插入图片描述

直接传入箭头函数

在这里插入图片描述
那为什么不直接写this.btn3Click()呢?因为如果直接写的话,就直接调用btn3Click了,而不是传入函数指针了

事件绑定案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .active{
        color:red;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">
      const root = ReactDOM.createRoot(document.querySelector("#root"));

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            movies:["1","2","3"],
            currentIndex:0
          };
        }

        itemClick(index){
          this.setState({
            currentIndex : index
          })
        }

        render() {
          const {movies,currentIndex} = this.state
          return (
            <div>
              <ul>
                 {
                  movies.map((item,index) =>{
                    return (
                      <li 
                      className={currentIndex === index ?'active':''}
                      key={item}
                      onClick={(event)=>this.itemClick(index)}
                      >
                        {item}
                      </li>
                    )           
                  })
                 }
              </ul>     
            </div>
          );
        }
      }
      root.render(<App />);
    </script>
  </body>
</html>

事件参数传递

<!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" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
    <script type="text/babel">
      class App extends React.Component {
        constructor() {
          super();
          this.state = {
            message: "Hello, world!",
          };
        }
        btnClick(event, name, age) {
          console.log("btnClick", event, name, age);
        }
        render() {
          return (
            <div>
              <button
              /**箭头函数第一个括号里面只传event,其他的参数写在方法的括号里面**/
                onClick={(event) => {
                  this.btnClick(event, "kobe", 19);
                }}
              >
                按钮
              </button>
            </div>
          );
        }
      }
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App />);
    </script>
  </body>
</html>

条件渲染

  • 一共有二种方式,React中的条件渲染跟Vue中的****v-if相同
    vue中的v-show的效果相当于display:block和none的切换
  • 第一种直接使用if,else进行赋值
    在这里插入图片描述
  • 第二种方式是使用三元运算符
{/*方式二:三元运算符*/}
<div>{isReady ? <button>开始战斗!</button>:<h3>开始准备</h3>}</div>

条件渲染案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .active{
        color:red;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
           message:"hello world",
           isShow:true
          };
        }

        changeShow(){
          this.setState({isShow : !this.state.isShow})
        }

        render() {
          const {message,isShow} = this.state
          let showElement = null
          if(isShow){
              showElement = <h2>{message}</h2>
          }
          return (
            <div>
              <button onClick={()=>{this.changeShow()}}>切换</button>
              {showElement}
            </div>
          );
        }
      }
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App />);
    </script>
  </body>
</html>

条件渲染v-show的效果和v-if的效果案例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .active{
        color:red;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
           message:"hello world",
           isShow:true
          };
        }

        changeShow(){
          this.setState({isShow : !this.state.isShow})
        }

        render() {
          const {message,isShow} = this.state
          let showElement = null
          if(isShow){
              showElement = <h2>{message}</h2>
          }
          return (
            <div>
              {/*v-show的效果*/}
              {/*style后面的第一个大括号是jsx的语法,第二个大括号是如果里面是个对象,就再加一个大括号*/}
              <h2 style={{display : isShow? 'block' : 'none'}}>哈哈哈哈哈</h2>
              
              {showElement}
              <button onClick={()=>{this.changeShow()}}>切换</button>
            </div>
          );
        }
      }
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App />);
    </script>
  </body>
</html>

列表渲染

  • 展示列表最多的方式就是使用高阶函数map,需要绑定key
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
    </style>
  </head>
  <body>
    <div id="root"></div>
    <!-- 添加依赖  -->
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

    <script type="text/babel">

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            message: "学生列表数据",
            students: [
              { id: 111, name: "why", score: 199 },
              { id: 112, name: "kobe", score: 98 },
              { id: 113, name: "james", score: 199 },
              { id: 114, name: "curry", score: 188 },
            ],
          };
        }

        render() {
          const {message , students} = this.state
          const filterStudents = students.filter((item) =>{
            return item.score > 100
          })
          const sliceStudents = filterStudents.slice(0,2)
          return (
            <div>
              <h2>{message}</h2>
              <div>
                {
                  sliceStudents.map((item)=>{
                    return (
                      <div key={item.id}>
                        <h2>学号: {item.id}</h2>
                        <h3>姓名: {item.name}</h3>
                        <h1>分数: {item.score}</h1>
                      </div>
                    )
                  })
                }
              </div>
            </div>
          );
        }
      }
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App />);
    </script>
  </body>
</html>

————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李小浦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值