JSX详解&&React的事件绑定&&事件参数的传递

Posted 小小白学计算机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSX详解&&React的事件绑定&&事件参数的传递相关的知识,希望对你有一定的参考价值。

一、认识JSX


这段element变量的声明右侧赋值的标签语法是什么呢?

  • 它不是一段字符串(因为没有使用引号包裹),它看起来是一段html原生,但是我们能在js中直接给一个变量赋值html吗?
  • 其实是不可以的,如果我们讲 type=“text/babel” 去除掉,那么就会出现语法错误;
  • 它到底是什么呢?其实它是一段jsx的语法;

JSX是什么?

  • JSX是一种javascript的语法扩展(eXtension),也在很多地方称之为JavaScript XML,因为看起就是一段XML语法;
  • 它用于描述我们的UI界面,并且其完成可以和JavaScript融合在一起使用;
  • 它不同于Vue中的模块语法,你不需要专门学习模块语法中的一些指令(比如v-for、v-if、v-else、v-bind);

为什么React选择了JSX?

React认为渲染逻辑本质上与其他UI逻辑存在内在耦合

  • 比如UI需要绑定事件(button、a原生等等);
  • 比如UI中需要展示数据状态,在某些状态发生改变时,又需要改变UI; n 他们之间是密不可分,所以React没有讲标记分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件
    (Component);
  • 我们只需要知道,JSX其实是嵌入到JavaScript中的一种结构语法;

JSX的书写规范:

  • JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个div原生(或者使用后面我们学习的Fragment);
  • 为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写;
  • JSX中的标签可以是单标签,也可以是双标签;
    注意:如果是单标签,必须以/>结尾;

二、JSX的使用

jsx中的注释

JSX嵌入变量

  • 情况一:当变量是Number、String、Array类型时,可以直接显示

  • 情况二:当变量是null、undefined、Boolean类型时,内容为空; 如果希望可以显示null、undefined、Boolean,那么需要转成字符串; 转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;

  • 情况三:对象类型不能作为子元素(not valid as a React child)

<!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="app"></div>

  <script src="../react/react.development.js"></script>
  <script src="../react/react-dom.development.js"></script>
  <script src="../react/babel.min.js"></script>

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          // 1.在{}中可以正常显示显示的内容
          name: "why", // String
          age: 18, // Number
          names: ["abc", "cba", "nba"], // Array

          // 2.在{}中不能显示(忽略)
          test1: null, // null
          test2: undefined, // undefined
          test3: true, // Boolean
          flag: true,
          // 3.对象不能作为jsx的子类
        //   friend: {
        //     name: "kobe",
        //     age: 40
        //   }
        }
      }
      render() {
        return (
          <div>
            <h2>{this.state.name}</h2>
            <h2>{this.state.age}</h2>
            <h2>{this.state.names}</h2>

            <h2>{this.state.test1 + ""}</h2>
            <h2>{this.state.test2 + ""}</h2>
            <h2>{this.state.test3.toString()}</h2>

            <h2>{this.state.flag ? "你好啊": null}</h2>

            <h2>{this.state.friend}</h2>
          </div>
        )
      }
    }
    ReactDOM.render(<App/>, document.getElementById("app"));
  </script>

</body>
</html>

JSX嵌入表达式

  • 运算表达式
  • 三元运算符
  • 执行一个函数

jsx绑定属性

  • 比如元素都会有title属性
  • 比如img元素会有src属性
  • 比如a元素会有href属性
  • 比如元素可能需要绑定class
  • 比如原生使用内联样式style
<!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="app"></div>

  <div style="color: red; font-size: 30px;"></div>

  <script src="../react/react.development.js"></script>
  <script src="../react/react-dom.development.js"></script>
  <script src="../react/babel.min.js"></script>

  <script type="text/babel">
    function getSizeImage(imgUrl, size) {
      return imgUrl + `?param=${size}x${size}`
    }

    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          title: "标题",
          imgUrl: "http://p2.music.126.net/L8IDEWMk_6vyT0asSkPgXw==/109951163990535633.jpg",
          link: "http://www.baidu.com",
          active: true
        }
      }
      render() {
        const { title, imgUrl, link, active } = this.state;
        return (
          <div>
            {/* 1.绑定普通属性 */}
            <h2 title={title}>我是标题</h2>
            <img src={getSizeImage(imgUrl, 140)} alt=""/>
            <a href={link} target="_blank">百度一下</a>

            {/* 2.绑定class */}
            <div className="box title">我是div元素</div>
            <div className={"box title " + (active ? "active": "")}>我也是div元素</div>
            <label htmlFor=""></label>

            {/* 3.绑定style */}
            <div style={{color: "red", fontSize: "50px"}}>我是div,绑定style属性</div>
          </div>
        )
      }
    }
    ReactDOM.render(<App />, document.getElementById("app"));
  </script>
</body>

</html>

三、React事件绑定

如果原生DOM原生有一个监听事件,我们可以如何操作呢?
方式一:获取DOM原生,添加监听事件;

方式二:在HTML原生中,直接绑定onclick;

在React中是如何操作呢?
我们来实现一下React中的事件监听,这里主要有两点不同:

  1. React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
    例如原生中的onclick="btnClick",在React中需要写成onClick={btnClick}
  2. 我们需要通过{}传入一个事件处理函数,这个函数会在事件发生时被执行;

在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this,如果我们这里直接打印this,也会发现它是一个undefined。

为什么是undefined呢?
原因是btnClick函数并不是我们主动调用的,而且当button按钮被点击时,React内部调用了btnClick函数,而它内部调用时,并不知道要如何绑定正确的this;

如何解决this的问题呢?
方案一:bind给btnClick显式绑定this

方案二:定义函数时使用箭头函数,使用 ES6 class fields 语法

方案三:事件监听时传入箭头函数(推荐)

四、事件参数传递

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

情况一:获取event对象

  • 很多时候我们需要拿到event对象来做一些事情(比如阻止默认行为)
  • 假如我们用不到this,那么直接传入函数就可以获取到event对象;



情况二:获取更多参数

  • 有更多参数时,我们最好的方式就是传入一个箭头函数,主动执行的事件函数,并且传入相关的其他参数;

<!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="app"></div>
    <button id="btn">原生</button>

    <script src="../react/react.development.js"></script>
    <script src="../react/react-dom.development.js"></script>
    <script src="../react/babel.min.js"></script>
    <script type="text/babel">
        document.getElementById('btn')
        .addEventListener('click', function (event) {
            console.log(event);
        })
        class App extends React.Component {
            constructor(props) {
                super(props)
                this.state = {
                    movies: ['流浪地球', '温暖的抱抱', '盗梦空间']
                }
                this.btnClick = this.btnClick.bind(this)
            }
            render() {
                return (
                    <div>
                        <button onClick={this.btnClick}>按钮</button>
                        <ul>
                            {
                                this.state.movies.map((item, index, arr) => {
                                    return (
                                        <li className="item"
                                            onClick={(event) => {this.liClick(item, index, event)}} key={index}>
                                            {item}
                                        </li>
                                    )
                                })
                            }
                        </ul>
                    </div>
                )
            }
            btnClick(event) {
                console.log(event);
                console.log('按钮发生点击', this);
            }
            liClick(item, index, event) {
                console.log('li发生了点击', item, index, event);
            }
        }
        ReactDOM.render(<App />, document.getElementById('app'))
    </script>
</body>

</html>

以上是关于JSX详解&&React的事件绑定&&事件参数的传递的主要内容,如果未能解决你的问题,请参考以下文章

React——嵌入已有项目 && jsx

React基础Day01-React概述&脚手架搭建&JSX&组件

如何渲染 JSX 元素数组(React 组件)

React 系列导航

[React 基础系列] 事件处理

2-2-9 & 10 & 11 React Hooks 封装公共行为