JSX

173 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第19天,点击查看活动详情

什么是React?

React是用于构建用户界面的JavaScript库, 核心专注于视图,目的实现组件化开发。

组件化的概念

可组合:组件的组合使用。 可重复:一个组件反复使用。 可维护:每个组件很小 易于维护

搭建开发环境

全局安装

 yarn add create-react-app -g
 npm install create-react-app -g

创建项目 这里注意项目名称不能使用大写字母 以及关键字:如 react。 像如下的my-app就可以。

creat-react-app my-app

进入到文件夹,启动

yarn start 
npm  start

初始化的项目启动后,会看到如下界面

image.png 我们看一下文件 image.png

引入了react的两个包,其中ReactDOM是去操作dom的,他的内容会更多一些。

import React from 'react';
import ReactDOM from 'react-dom/client';

什么是jsx

是一种JS和HTML混合的语法、将组件的结构、数据、样式组合在一起

ReactDOM.render(
    <h1>hello world</h1>,
    // js语法 id选择器
    document.getElementById('root')
)

我们借助babel看一下。

左面是我们的html语法,右边是React的Jsx语法。 babel。 因为浏览器是不识别JSX的,所以我们的React都经过了babel的转译 image.png

什么是元素(虚拟DOM)

JSX 是一种语法糖,最终都会通过Babel转译为 createElement语法。

React元素 也就是虚拟DOM

  • React元素是构成React应用的最小单位。
  • React元素用来描述你在屏幕上看到的内容。
  • React元素实际上是普通的js对象,ReactDOM来确保浏览器中的DOM和React元素保持一致。

我们打印一个虚拟DOM看一看

const element = React.createElement("h1",{
  id:'title'
},'hello')
console.log(element,'elementelementelement')

实质上是一个对象。

  • type标签的类型
  • props 其中children是子元素,如下只有一个子元素所以是字符串。当是多个时,就会是一个数组。 image.png JSX 编译成createElement是在webpack编译的时候,也就是打包的时候执行的。

我们打包一下

npm run build

然后去build文件去找,可以看到将虚拟DOM,编译成了 createElement image.png

ReactDOM.render

render方法负责把虚拟DOM转为真实DOM注入容器。

ReactDOM.render(elemet,document.getElemetById('root'))

JSX属性

calss[className]

在jsx中不使用calss 而需要使用className

let elemet = <h1 className='title'>hellow</h1>

style[style{{}}]

不使用 style="",需要使用 style={{}}相当于一个对象

let elemet = <h1 className='title' style={{color:'red'}}>hellow</h1>

for[htmlFor]

这个属性用于输入框获得焦点

let elemet = <div><label htmlFor='title'/><input id='title'></div>

JSX 表达式

如果在JSX中读取JS变量的话,用 {}

let style = {background:'red'}
let elemet = <div style={style}></div>
let data = "我是文章"
let element = <span>{data}</span>

JSX其实是一个对象

JSX其实是一个对象,可以在 if 或者 for 中使用。

if中使用

import React from 'react';
import ReactDOM from 'react-dom';
function greeting(name){
  if(name){
    return <h1>hello,{name}</h1>
  }else{
    return <h2>hello,stranger</h2>
  }
}
const element = greeting('yueyunpeng')
ReactDOM.render(element,document.getElementById('root'))

for中使用

注意使用循环后,遍历生成的元素需要一个key属性,用于区分。

import React from 'react';
import ReactDOM from 'react-dom';
let persons = ['岳云鹏','雷佳音','沈腾']
let element = persons.map((name)=><li key={name}>{name}</li>)
ReactDOM.render(<ul>{element}</ul>,document.getElementbyId('root'))

React更新(DIFF)

把之前的虚拟DOM和新的虚拟DOM进行比较,只更新变化的。

如下 遍历users对象

let users = [{'name':'张三' },{'name':'李四'},{'name':'王保长'}]
// key 可以使用index索引
let element = users.map((user,index)=><li key={index}>{user.name}</li>)
ReactDOM.render(<ul>{element}</ul>,document.getElementbyId('root'))

当我们 数组中的对象顺序改变,便会通过DIFF算法 将之前的虚拟DOM与现在虚拟DOM进行比较。然后找到最简单的更改方式。如下:只需要把王保长的位置从第三个移到第一个

let users = [{'name':'王保长'},{'name':'张三' },{'name':'李四'}]
// key 可以使用index索引
let element = users.map((user,index)=><li key={index}>{user.name}</li>)
ReactDOM.render(<ul>{element}</ul>,document.getElementbyId('root'))

key

key是给React使用的,并不是给程序员使用的。key让组件有了唯一标识。相同的key React认为是同一个组件,这样后续相同的key对应组件都不会被创建。

key相同

如果两个元素的key相同,且元素类型相同,若元素属性变化,则React只更新组件对应的属性,这种情况下,性能开销会相对较小。如下的变化

<div style={{background:'red'}} key='same'></div>
<div style={{background:'blue'}} key='same'></div>

key不同

在render函数执行的时候,新旧两个虚拟DOM会进行对比,如果两个元素有不同的key,那么在前后两次渲染中就会被认为是不同的元素,这时候旧的元素会被unmount,新的元素会被mount

有无key值

没有key值

如果没有key得情况下,他直接会移除原先的第二个子元素,然后再append进去剩下的子元素,而其实我们这个操作只需要一个insert操作就能完成。为了解决这种问题,react需要我们提供给一个key来帮助更新,减少性能开销。

 

有key值

如果有key值得情况下,react就会通过key来发现tree2的第二个元素不是原先tree1的第二个元素,原先的第二个元素被挪到下面去了,因此在操作的时候就会直接指向insert操作,来减少dom操作的性能开销

不推荐使用index作为key

如果我们用index来标识key,数组在执行插入、排序等操作之后,原先的index并不再对应到原先的值,那么这个key就失去了本身的意义,并且会带来其他问题。

使用随机数

key 的值以Math.random() 随机生成而定,这使得数组元素中的每项都重新销毁然后重新创建,有一定的性能开销