React学习笔记 --- JSX核心语法(上)

560 阅读5分钟

JSX简介

示例

// 这里是JSX语法,所以可以吧html代码片段赋值给一个变量
// 可以认为这个html片段就是一个值,
// 其最后会被转换为VDOM,最后在页面上渲染为真实的DOM
const res = <h2>Hello World</h2>

ReactDOM.render(res, document.getElementById('app'))

1.1 JSX的2个先决条件

  1. 使用了babel进行编译和转换
  2. script上声明了使用babel进行编译 即 type='text/babel'

1.2 什么是JSX

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

1.3 为什么使用JSX

React的设计哲学和别的框架的设计思想是不一样的,例如在Vue中就使用了templatescriptstyle界面,样式,布局进行了分离

但是在React中的设计哲学是all in js,在React中,认为所有的内容都可以写在JS中,界面和布局与js代码存在内在耦合,其主要表现为

  1. 比如UI需要绑定事件(button、a原生等等);
  2. 比如UI中需要展示数据状态,在某些状态发生改变时,又需要改变UI

所以React没有讲标记分离到不同的文件中,而是将它们组合到了一起,这个地方就是组件 (Component)

在这里,我们只需要知道,JSX其实是嵌入到JavaScript中的一种结构语法

1.4 JSX的一些书写规范

  • JSX的顶层只能有一个根元素,所以我们很多时候会在外层包裹一个原生div或main标签(或者使用后面我们学习的Fragment)

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

    • 这个括号不是必须的,但是加上括号和不加括号是有些许的区别的
      • 加上括号后,书写JSX是可以进行换行书写的,如果没有括号,所有的jsx必须书写在一行,如果换行会报错
      • 加上括号后,相比不加括号,更利于代码的阅读和维护
  • 在jsx中可以书写单标签,也可以书写双标签,但是如果使用了单标签的时候,JSX中使用的是严格语法,也就是说在JSX中

    单标签必须闭合,例如<App />

1.5 JSX的注释

JS中的注释

// 行内注释
// ...

// 块级注释
/*
	....
*/

// 多行注释
/**
*
*
*/

JSX中的注释

{/* 我是jsx中的注释 */}

{/*  
	如果在JSX中使用// 或者直接使用/**/来进行注释的话
    这些注释会被作为文本节点被输出出来
*/}

dVWaBq.png

在JSX中使用JS注释,其会被作为文本节点,然后输出

1.6 在JSX中使用变量

情况1: Number,String,Array 可以被正常渲染

class App extends React.Component{
 constructor(str, num, arr) {
     super()

     this.state = {
         str: 'Klaus',
         num: 23,
         arr: ['Klaus', 'Alice', 'Kobe']
     }
 }

 render() {
     {/* 解构赋值 */}
     const {str, num, arr} = this.state

     return (
         <div>
             <div>{ str }</div>
             <div>{ num }</div>
             
             {/* 
             	JSX在读取数组数据的时候
             	会自动取出其中的每一个数组元素后显示
             */}
             <div>{ arr }</div>
         </div>
     )
 }
}

ReactDOM.render(<App />, document.getElementById('app'))

dVgM7T.png

情况2: null,undefined, boolean 默认是不会被React渲染在页面上

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

     this.state = {
         nullElem: null,
         undefinedElem: undefined,
         trueElem: true,
         falseElem: false
     }
 }

 render() {
     const {nullElem, undefinedElem, trueElem, falseElem} = this.state

     return (
         <div>
             <div>{ nullElem }</div>
             <div>{ undefinedElem }</div>
             <div>{ trueElem }</div>
             <div>{ falseElem }</div>
         </div>
     )
 }
}

ReactDOM.render(<App />, document.getElementById('app'))

结果: 界面上没有任何的输出

React中不显示输出null,undefined,boolean值的原因

render() {
 return (
     <div>
         {/*  这是传统的写法  */}
         <div>{ this.state.age > 18 ? 'OK' : '' }</div>

         {/*  在React中可以这么写 */}
         <div>{ this.state.age > 18 ? 'OK' : null }</div>
         <div>{ this.state.age > 18 ? 'OK' : undefined }</div>


         {/*
             flag 是在state中定义的boolean值

             如果flag为true 输出结果为 this.state.name
             如果flag为false 输出结果为 false
         */}
         <div>{ this.state.flag && this.state.name }</div>

     </div>
 )
}

如果希望将null,boolean,undefined可以显示在页面上

只有将这些转化为字符串后才可以正常显示

转换方式如下:

  1. 调用toString方法,只适合于Boolean.null, undefined是没有toString方法的
  2. 调用String方法,null,undefined,boolean都是可以被调用的
  3. 直接加上空字符串,例如null + ''null,undefined,boolean都是可以被调用的

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

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

     this.state = {
         obj: {
             name: 'Klaus',
             age: 23
         }
     }
 }

 render() {
     return (
         <div>
             <div>{ this.state.obj }</div>
         </div>
     )
 }
}

ReactDOM.render(<App />, document.getElementById('app'))

结果: dVWlAf.png

JSX最后会被做为React的子类来进行解析,但是对象是不可以作为React的子类的,因此报错

1.7 在JSX中使用表达式

this.state = {
    firstName: 'Klaus',
    lastName: 'Wang',
    isLogin: true
}

render() {
    const {firstName, lastName, isLogin} = this.state

    return (
        <div>
            {/* JSX中可以使用运算符表达式 */}
            <div>{ firstName + ' ' + lastName  }</div>
            <div>{ 10 + 4 }</div>
            {/* JSX中可以使用三目表达式(三元运算符) */}
            <div>{ isLogin ? '欢迎回来' : '请先登录' }</div>
            {/* 其余的运算符包括逻辑与,逻辑或,map,filter等 */}
        </div>
    )
}
this.state = {
    firstName: 'Klaus',
    lastName: 'Wang'
}

getFullName() {
    // 注意: 这里的this是正确的, 默认不是undefined
    return this.state.firstName + this.state.lastName
}

render() {
    return (
        <div>
            {/*
              这个方法是我们自己定义的方法 ,是我们自己调用的
              和之前的事件callback 不一样,事件callback是React来替我们进行调用的
              但是这里是我们自己主动进行调用,所以这里我们隐式绑定的this就是实例对象
              所以不需要在认为进行绑定
             */}
            { this.getFullName() }
        </div>
    )
}

上一篇 React学习笔记 --- React初体验 下一篇 React学习笔记 --- jsx核心语法(下)