React之JSX语法

1.认识JSX的语法

下面是一段JSX语法数组

<script type="text/babel">
  const element = <h2>Hello World</h2>
 ReactDOM.render(element, document.getElementById("app"));
</script>
复制代码

JSX是什么?bash

  • JSX是一种JavaScript的语法扩展(eXtension),也在不少地方称之为JavaScript XML,由于看起就是一段XML语法;
  • 它用于描述咱们的UI界面,而且其彻底能够和JavaScript融合在一块儿使用.(因此灵活性很高);
  • 它不一样于Vue中的模块语法,你不须要专门学习模块语法中的一些指令(好比v-for、v-if、v-else、v-bind);

为何React选择了JSX?babel

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

    • 好比UI须要绑定事件(button、a原生等等);
    • 好比UI中须要展现数据状态,在某些状态发生改变时,又须要改变UI;
  • 他们之间是密不可分,因此React没有将标记分离到不一样的文件中,而是将它们组合到了一块儿,这个地方就是组件(Component),JSX实际上是嵌入到JavaScript中的一种结构语法;函数

JSX的书写规范:学习

  • JSX的顶层只能有一个根元素,因此咱们不少时候会在外层包裹一个div原生(或者使用后面咱们学习的Fragment);
  • JSX中的标签能够是单标签,也能够是双标签;(注意:若是是单标签,必须以/>结尾;
  • 咱们一般在jsx的外层包裹一个小括号(),这样能够方便阅读,而且jsx能够进行换行书写;以下例子:
return (
          <div>
            <h2>电影列表1</h2>
            <ul>
              {liArray}
            </ul>

            <h2>电影列表2</h2>
            <ul>
              {
                this.state.movies.map((item) => {
                  return <li>{item}</li>
                })
              }
            </ul>
          </div>
        )
复制代码

1.2 JSX嵌入表达式

若是咱们jsx中的内容是动态的,咱们能够经过表达式来获取:ui

  • 书写规则:{表达式}
  • 大括号内能够是变量、字符串、数组、函数调用等任意js表达式;如上例子:

1.2.1jsx中的注释

jsx是嵌入到JavaScript中的一种语法,因此在编写注释时,须要经过JSX的语法来编写:this

<div>
  {/* 我是一段注释 */}
  <h2>Hello World</h2>
</div>
复制代码

1.2.2JSX嵌入变量

  • 当变量是Number、String、Array类型时,能够直接显示
  • 当变量是null、undefined、Boolean类型时,内容为空;
    • 若是但愿能够显示null、undefined、Boolean,那么须要转成字符串;
    • 转换的方式有不少,好比toString方法、和空字符串拼接,String(变量)等方式;
  • 对象类型不能做为子元素(not valid as a React child)不然会报错
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      name: "why",
      age: 18,
      hobbies: ["篮球", "唱跳", "rap"],
      
      test1: null,
      test2: undefined,
      flag: false,

      friend: {
        name: "kobe",
        age: 40
      }
    }
  }

  render() {
    return (
      <div>
        {/* 我是一段注释 */}
        <h2>Hello World</h2>
      </div>

      <div>
        {/* 1.能够直接显示 */}
        <h2>{this.state.name}</h2>
        <h2>{this.state.age}</h2>
        <h2>{this.state.hobbies}</h2>

        
        {/* 2.不显示 */}
        <h2>{this.state.test1}</h2>
        <h2>{this.state.test1 + ""}</h2>
        <h2>{this.state.test2}</h2>
        <h2>{this.state.test2 + ""}</h2>
        <h2>{this.state.flag}</h2>
        <h2>{this.state.flag + ""}</h2>
        
        {/* 3.报错,不显示 */}
        <h2>123{this.state.friend}</h2>
      </div>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById("app"));
复制代码

说明:为何null、undefined、Boolean在JSX中要显示为空内容呢?spa

  1. 在判断结果为false时,不显示一个内容;
  2. 在判断结果为true时,显示一个内容;

这个时候,咱们能够编写以下代码:code

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      flag: false
    }
  }

  render() {
    return (
      <div>
        {this.state.flag ? <h2>我是标题</h2>: null}
        {this.state.flag && <h2>我是标题</h2>}
      </div>
    )
  }
}
复制代码

1.2.3JSX嵌入表达式

JSX中,也能够是一个表达式。

  1. 运算表达式
  2. 三元运算符
  3. 执行一个函数
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "kobe",
      lastName: "bryant",
      age: 20
    }
  }

  render() {
    return (
      <div>
        {/* 运算表达式 */}
        <h2>{this.state.firstName + " " + this.state.lastName}</h2>
        {/* 三元运算符 */}
        <h2>{this.state.age >= 18 ? "成年人": "未成年人"}</h2>
        {/* 执行一个函数 */}
        <h2>{this.sayHello("kobe")}</h2>
      </div>
    )
  }

  sayHello(name) {
    return "Hello " + name;
  }
}
复制代码

1.2.4 jsx绑定属性

不少时候,描述的HTML原生会有一些属性,而咱们但愿这些属性也是动态的:

  1. 好比元素都会有title属性
  2. 好比img元素会有src属性
  3. 好比a元素会有href属性
  4. 好比元素可能须要绑定class (注意:绑定class比较特殊,由于class在js中是一个关键字,因此jsx中不容许直接写class,,写法:使用className替代)
  5. 好比原生使用内联样式style(style后面跟的是一个对象类型,对象中是样式的属性名和属性值,注意:这里属性名转成驼峰标识,而不是链接符- ;)

下面为各种属性绑定写法

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      title: "你好啊",
      imgUrl: "https://upload.jianshu.io/users/upload_avatars/1102036/c3628b478f06.jpeg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
      link: "https://www.baidu.com",
      active: false
    }
  }

  render() {
    return (
      <div>
        <h2 title={this.state.title}>Hello World</h2>
        <img src={this.state.imgUrl} alt=""/>
        <a href={this.state.link} target="_blank">百度一下</a>
        <div className={"message " + (this.state.active ? "active": "")}>你好啊</div>
        <div className={["message", (this.state.active ? "active": "")].join(" ")}>你好啊</div>
        <div style={{fontSize: "30px", color: "red", backgroundColor: "blue"}}>我是文本</div>
      </div>
    )
  }
}
复制代码

1.3 jsx事件监听

1.3.1和原生绑定区别

原生DOM原生有一个监听事件,常规操做通常为:

  1. 获取DOM原生,添加监听事件;
  2. 在HTML原生中,直接绑定onclick;
<button onclick="btnClick()">点我一下</button> //btnClick()这样写的缘由是onclick绑定的后面是跟上JavaScript代码;
<script>
  function btnClick() {
  console.log("按钮发生了点击");
}
</script>
复制代码

在React中是如何操做de?

React中的事件监听,这里主要有两点不一样

  1. React 事件的命名采用小驼峰式(camelCase),而不是纯小写;
  2. 咱们须要经过{}传入一个事件处理函数,这个函数会在事件发生时被执行;
class App extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.btnClick}>点我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log("React按钮点击了一下")
  }
}
复制代码

1.3.2this绑定问题

在事件执行后,咱们可能须要获取当前类的对象中相关的属性:

  • 好比咱们这里打印:this.state.message
    • 可是这里会报错:Cannot read property 'state' of undefined
    • 缘由是this在这里是undefined -若是咱们这里直接打印this,也会发现它是一个undefined
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李银河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>点我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
复制代码

为何是undefined呢?

  • 缘由是btnClick函数并非咱们主动调用的,并且当button发生改变时,React内部调用了btnClick函数;
  • 而它内部调用时,并不知道要如何绑定正确的this;

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

  • 这里咱们主动将btnClick中的this经过bind来进行绑定(显示绑定)
  • 那么以后React内部调用btnClick函数时,就会有一个this,而且是咱们绑定的this;
<button onClick={this.btnClick.bind(this)}>点我一下(React)</button>
复制代码

但若是我有两个函数都须要用到btnClick的绑定咱们发现 bind(this) 须要书写两遍;:

<button onClick={this.btnClick.bind(this)}>点我一下(React)</button>
<button onClick={this.btnClick.bind(this)}>也点我一下(React)</button>
复制代码

咱们能够经过在构造方法中直接给this.btnClick绑定this来解决(注意查看 constructor 中咱们的操做:this.btnClick = this.btnClick.bind(this);):

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李银河"
    }

    this.btnClick = this.btnClick.bind(this);
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>点我一下(React)</button>
        <button onClick={this.btnClick}>也点我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
复制代码

方案二:使用 ES6 class fields 语法

你会发现我这里将btnClick的定义变成了一种赋值语句:

  • 这是ES6中给类定义属性的方法,称之为class fields语法;
  • 由于这里咱们赋值时,使用了箭头函数,因此在当前函数中的this会去上一个做用域中查找;
  • 而上一个做用域中的this就是当前的对象;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李银河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={this.btnClick}>点我一下(React)</button>
        <button onClick={this.btnClick}>也点我一下(React)</button>
      </div>
    )
  }

  btnClick = () => {
    console.log(this);
    console.log(this.state.message);
  }
}
复制代码

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

由于 onClick 中要求咱们传入一个函数,那么咱们能够直接定义一个箭头函数传入:

  • 传入的箭头函数的函数体是咱们须要执行的代码,咱们直接执行 this.btnClick();
  • this.btnClick()中经过this来指定会进行隐式绑定,最终this也是正确的;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      message: "你好啊,李银河"
    }
  }

  render() {
    return (
      <div>
        <button onClick={() => this.btnClick()}>点我一下(React)</button>
        <button onClick={() => this.btnClick()}>也点我一下(React)</button>
      </div>
    )
  }

  btnClick() {
    console.log(this);
    console.log(this.state.message);
  }
}
复制代码

1.3.3事件参数传递

在执行事件函数时,有可能咱们须要获取一些参数信息:好比event对象、其余参数

状况一:获取event对象

  • 不少时候咱们须要拿到event对象来作一些事情(好比阻止默认行为)
  • 假如咱们用不到this,那么直接传入函数就能够获取到event对象;
class App extends React.Component {
  constructor(props) {

  render() {
    return (
      <div>
        <a href="http://www.baidu.com" onClick={this.btnClick}>点我一下</a>
      </div>
    )
  }

  btnClick(e) {
    e.preventDefault();
    console.log(e);
  }
}
复制代码

状况二:获取更多参数

  • 有更多参数时,咱们最好的方式就是传入一个箭头函数,主动执行的事件函数,而且传入相关的其余参数;
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      names: ["衣服", "鞋子", "裤子"]
    }
  }

  render() {
    return (
      <div>
        <a href="http://www.baidu.com" onClick={this.aClick}>点我一下</a>

        {
          this.state.names.map((item, index) => {
            return (
              <a href="#" onClick={e => this.aClick(e, item, index)}>{item}</a>
            )
          })
        }
      </div>
    )
  }

  aClick(e, item, index) {
    e.preventDefault();
    console.log(item, index);
    console.log(e);
  }
}
复制代码

本文是经过学习codewhy的 React课程总结

相关文章
相关标签/搜索