掌握react,这一篇就够了

2023-11-04

react众所周知的前端3大主流框架之一,由于出色的性能,完善的周边设施风头一时无两。本文就带大家一起掌握react。

jsx语法

前端MVVM主流框架都有一套自己的模板处理方法,react则使用它独特的jsx语法。在组件中插入html类似的语法,简化创建view的流程。

下面让我们来认识一下构建的两种元素

原生元素

ReactDOM.render((
  <div>
    <h1>标题</h1>
  </div>
), document.getElementById('root'))

通过简单的语法页面就会被插入一个div+一个h1标签。原生的html元素可以被直接使用。以上的语法并不是js支持的语法,需要被转换之后才能运行。

自定义元素

react强大之处就在于可以组件的自定义,实现组件的复用。如果我们创建了一个组件。我们也可以通过jsx语法调用。

import * as React from 'react'

class Page extends React.Component {
  render() {
    return (<div>
      home111 &copy; © \ua9
    </div>)
  }
}

ReactDOM.render((
  <div>
    <Page/>
  </div>
), document.getElementById('root'))

我们定义了一个Page组件,可以在jsx里面像调用html一样直接调用。

插入动态数据

let name = 'hi'

ReactDOM.render((
  <div>
    {name}
  </div>
), document.getElementById('root'))

使用{}就可以插入数据,但是{}中间的必须是js表达式,不能是语句。如果表达式的执行结果是一个数组,则会自动join。

注释

jsx语法和html语法一样,也是可以插入注释,只不过写的时候有一些区别

子组件注释

let name = 'hi'

ReactDOM.render((
  <div>
    {/* 注释 */}
    {name}
  </div>
), document.getElementById('root'))

在子组件中插入注释,需要使用{}包裹起来,在/ /之间插入注释文字。

属性注释

let name = 'hi'

ReactDOM.render((
  <div>
    {name}
    <img /* 
        多行注释
    */ src="1.jpg"/>
  </div>
), document.getElementById('root'))

在标签中间,可以插入一个多行注释,类似上面的代码。

属性props

  1. 可以向使用html的attr一样使用属性,就像下面img的src一样
let name = 'hi'

ReactDOM.render((
  <div>
    <img src="1.png"/>
  </div>
), document.getElementById('root'))
  1. 如果需要传递动态属性,使用{},多个属性,使用展开运算符
let props = {
    src: '1.png',
    alt: '1图片'
}

ReactDOM.render((
  <div>
    <img src={"1.png"}/>
    <img {...props}/>
  </div>
), document.getElementById('root'))
  1. 两个转换,class-->className for-->htmlFor

因为class和for是javascript关键字,所以这里需要用转换之后名称

ReactDOM.render((
  <div className="tab">
    <label htmlFor="name">姓名:</label><input id="name"/>
  </div>
), document.getElementById('root'))
  1. 布尔属性

如果一个属性的值是布尔值,当这个值是true的时候则可以省略=后面的值,只保留key。

ReactDOM.render((
  <div className="tab">
    <input type="text" required/>
    <input type="text" required={true}/>
  </div>
), document.getElementById('root'))
  1. 原生元素的自定义属性

react对元素属性做了校验,如果在原生属性上使用此元素不支持的属性,则不能编译成功。必须使用data-前缀

ReactDOM.render((
  <div className="tab">
    <input type="text" data-init="22"/>
  </div>
), document.getElementById('root'))

插入html

如果动态的插入html元素,react出于安全性考虑会自动帮我们转义。所以一定要动态的插入元素的话,使用dangerouslySetInnerHTML

ReactDOM.render((
  <div className="tab">
    <div dangerouslySetInnerHTML={{__html: '<span>test</span>'}}></div>
  </div>
), document.getElementById('root'))

React组件创建

React.createClass

这是旧版本的api,使用React.createClass创建组件,配套的一些api,有getDefaultProps, getinitialstate。官方已经不建议使用了,使用下面新的api替代。

ES6 classes

import * as React from 'react'

class Page extends React.Component {
  render() {
    return (<div>
      home
    </div>)
  }
}

这是一个实现了render方法的class。也是一个基本的react组件。

无状态函数

function Button(props, context) {
    return (
        <button>
            <em>{props.text}</em>
            <span>{context.name}</span>
        </button>
    );
}

纯函数,不存在state,只接受props和state。纯函数有优点,优点就是易于测试,无副作用。

React数据流

state

state是组件的内部状态,需要在视图里面用到的状态,才需要放到state里面去。如下,我们在类上创建一个state属性,在视图里面通过使用this.state.name去引用。而这里的state定义则代替的是getinitialstate方法。

import * as React from 'react'

class Page extends React.Component {
  state = {
      name: '小明'
  }    

  render() {
    return (<div>
      {this}
    </div>)
  }
}

如何更新state呢,直接更改state其实可以可以的,不过这样子无法触发组件视图的更新机制。所以使用setState()api。值得注意的是setState是异步的,原因是react内部需要对setState做优化,不是state变了立刻去更新视图,而是拦截一部分state的改变,等到合适的时机再去更新视图。

import * as React from 'react'

class Page extends React.Component {
  state = {
      name: '小明'
  }    

  render() {
    setTimeout(() => this.setState({name: '小明儿子'}), 5000)
  
    return (<div>
      {this.state.name}
    </div>)
  }
}
真实开发中绝不要在render函数里面去更改state,以上只是为了演示

props

props是组件之间传递数据的最主要api, react推崇的是自顶向下的数据流向,也就是组件的数据要从父组件传给子组件。如果子组件需要向父组件传递数据,则需要使用回调函数的方式。

import * as React from 'react'

class Child extends React.Component {
  render() {
    return (<div>
      {this.props.parentName}
    </div>)
  }
}

class Parent extends React.Component {
  state = {
      name: '小明'
  }    

  render() {
    setTimeout(() => this.setState({name: '小明儿子'}), 5000)
  
    return (<div>
      <Child parentName={this.state.name}/>
    </div>)
  }
}

可以看到Child组件显示了父组件的name。当父组件状态更新了,子组件同步更新。那如何在子组件中更改父组件状态呢?答案是回调函数。

import * as React from 'react'

class Child extends React.Component {
  update() {
      this.props.onChange('小明名字改了')
  }

  render() {
    return (<div>
      {this.props.parentName}
      <button onClick={this.update.bind(this)}>更新</button>
    </div>)
  }
}

class Parent extends React.Component {
  state = {
      name: '小明'
  }    

  changeName(name) {
      this.setState({
          name
      })
  }
  
  render() {
    setTimeout(() => this.setState({name: '小明儿子'}), 5000)
  
    return (<div>
      <Child onChange={this.changeName.bind(this)} parentName={this.state.name}/>
    </div>)
  }
}

注意哈:props是不可以更改的,这既不符合react单向数据流思想,也为维护带来灾难。

事件

react里面的用户事件都是合成事件,被React封装过。内部使用的还是事件的委托机制。
常用的事件有点击事件onClick,input的onChange事件等,官网都可以查到。

合成事件的this指向问题

就像上文一样,我们绑定事件的方式很奇怪,使用了bind来显示绑定this的指向。因为传递到组件内部的只是一个函数,而脱离了当前对象的函数的this指向是不能指到当前组件的,需要显示指定。

通过bind

<button onClick={this.update.bind(this)}>更新</button>

构造器内部指定

import * as React from 'react'

class Child extends React.Component {
  constructor(props) {
     super(props) 
     this.update = this.update.bind(this)
  }

  update() {
      this.props.onChange('小明名字改了')
  }

  render() {
    return (<div>
      {this.props.parentName}
      <button onClick={this.update}>更新</button>
    </div>)
  }
}

箭头函数

import * as React from 'react'

class Child extends React.Component {
  update => e = {
      this.props.onChange('小明名字改了')
  }

  render() {
    return (<div>
      {this.props.parentName}
      <button onClick={this.update}>更新</button>
    </div>)
  }
}

装饰器

import * as React from 'react'

class Child extends React.Component {
  constructor(props) {
     super(props) 
  }

  @autoBind
  update() {
      this.props.onChange('小明名字改了')
  }

  render() {
    return (<div>
      {this.props.parentName}
      <button onClick={this.update}>更新</button>
    </div>)
  }
}

装饰器是es7语法,如果需要使用需要安装对应的babel:present版本。而typescript则原生支持。

autoBind原理大概就是劫持get方法,get时改变this指向

如何获得evnt原生事件

通过e.nativeEvent获取原生事件对象

import * as React from 'react'

class Child extends React.Component {
  constructor(props) {
     super(props) 
     this.update = this.update.bind(this)
  }

  update(e) {
      console.log(e.nativeEvent)
  }

  render() {
    return (<div>
      <button onClick={this.update}>更新</button>
    </div>)
  }
}

解决冒泡和取消默认事件

e.preventDefault() //取消默认行为
e.stopPropagation() //取消冒泡

这个和浏览器原生事件处理方案是一致的。问题是我们只可以调合成事件的e的方法,不可以通过e.nativeEvent方法做这些操作,原因是上文讲过的委托。

ReactDom

ref

特殊的props,ref组件对象的引用,现在官方也不建议直接给ref赋值,需要通过函数来赋值。

ReactDOM.render((
  <div>
    <Calendar ref={ref => this.c = ref} any-ss="text"/>
  </div>
), document.getElementById('root'))

render

顶层api,只有在根组件时候才需要使用。第一个参数是Component,第二个参数是dom节点

findDOMNode

通过传入component实例获取此component根dom节点,在这里可以去dom节点进行操作了,虽然极其不建议这么做,但是你确实可以做。

unmountComponentAtNode

卸载此组件,并销毁组件state和事件

接收组件的引用,也就是ref。仅仅是取消挂载,组件还在,如果需要彻底清除的话,需要手动删掉此dom。

表单

onchange配合value

与vue框架不同的是,react如果要实现表单元素变化,状态同步更新,必须要自己去监听表单事件。

import * as React from 'react'

class Child extends React.Component {
  state = {
      name: '小明'
  }

  constructor(props) {
     super(props) 
     this.update = this.update.bind(this)
  }

  update(e) {
      this.setState({
          name: e.target.value
      })
  }

  render() {
    return (<div>
      <input onChange={this.update} value={this.state.name}/>
    </div>)
  }
}

受控组件和非受控组件

受控组件和非受控组件这些都是指的表单组件,当一个表单的值是通过value改变的而不是通过defaultValue是受控组件,否则就是非受控组件。

下面组件中的input就是受控组件

import * as React from 'react'

class Child extends React.Component {
  state = {
      name: '小明'
  }

  constructor(props) {
     super(props) 
     this.update = this.update.bind(this)
  }

  update(e) {
      this.setState({
          name: e.target.value
      })
  }

  render() {
    return (<div>
      <input onChange={this.update} value={this.state.name}/>
    </div>)
  }
}

下面组件中的input是非受控组件

import * as React from 'react'

class Child extends React.Component {
  state = {
      name: '小明'
  }

  constructor(props) {
     super(props) 
     this.update = this.update.bind(this)
  }

  update(e) {
      this.setState({
          name: e.target.value
      })
  }

  render() {
    return (<div>
      <input onChange={this.update} defaultValue={this.state.name}/>
    </div>)
  }
}

组件之间通讯

父子之间通讯

父子之间通讯又分为父->子,子->父。

因为react单向数据流向的缘故,父->子通信的话直接通过props。父组件数据变动,直接传递给子组件。

子->父组件之间就要通过回调函数来通信了,父组件传递一个回调函数给子组件,子组件通过调用此函数的方式通知父组件通信。

跨级组件通信

react为了实现祖先组件和后辈组件之间的通信问题,引入了contextApi。

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}

Button.contextTypes = {
  color: React.PropTypes.string
};

class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
}

class MessageList extends React.Component {
  getChildContext() {
    return {color: "purple"};
  }

  render() {
    const children = this.props.messages.map((message) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}

MessageList.childContextTypes = {
  color: React.PropTypes.string
};

MessageList中的color会自动更新到儿孙组件里面去,实现跨级啊通信。如果需要反过来通信,则需要借助其他工具,比如事件系统(Pub/Sub)。

没有嵌套关系组件之间通信

组件之间通信最主流的两种方式脱胎于观察这模式和中介者模式这两种。

跨级之间通信现在最主流的方式就是观察这模式的实现Pub/Sub,react社区中的redux也是使用这种方式实现的。

vue2.X版本也去掉了跨组件通信的功能。那如何在2.x中做跨组件通信呢?如果不借助外力的话,是不是可以使用$parent和$childen的递归调用实现全局组件通信呢?比如我想广播一个事件,我就查找到所有的子组件,挨个触发$emit(xx),上报一个事件也是同理,只不过需要查找所有的$parent。结合起来就可以实现组件之间的通信,只不过这种查找效率比较低,需要慎用和优化

创建了一个程序员交流微信群,大家进群交流IT技术

图片描述

如果已过期,可以添加博主微信号15706211347,拉你进群

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

掌握react,这一篇就够了 的相关文章

  • 禁用内容安全策略

    当我开发网站时 我经常想看看特定功能在网站上的外观如何 所以我会使用 chrome 开发者工具并经常运行一些 javascript 脚本 我经常发现一些脚本由于内容安全策略 CSP 而无法运行的问题 我完全理解该策略是为了防止跨站点脚本攻击
  • chrome 调试器承诺在暂停时不会解析?

    也许我没有正确调试承诺 但基本上 如果您在断点处停止并运行异步代码 它实际上不会完成 直到您恢复执行为止 这是一个问题 调试器允许您快速试验多个 api 方法 但如果您恢复它 您就不能 debugger now type the follo
  • React-native:将场景绑定到导航栏

    我正在整理这个提问 回答应用程序 并遇到了这个障碍 我想从导航栏触发场景中的功能 与登录应用程序类似 我在导航栏中有一个用于提交答案的按钮 RightButton route navigator index navState if rout
  • 用隐藏单元格补充 colspanned 表格有什么不好吗?

    我一直在表格上开发一些排序和选择功能 我发现在具有跨单元格的表格中定位非常困难 我只是添加了跨区单元格并将其隐藏 它看起来不错 它与我的 js 一起工作 非常适合索引 但我想知道这是否是合法的方法 stuffing display none
  • VBA / HTML / jQuery 选择自动完成 - 在列表中选择

    我正在尝试使用 Excel 中的 VBA 在网站的列表中选择一个值 这不是一个 正常列表 该网站使用 jQuery 选择自动完成 如下所示 example http davidwalsh name demo jquery chosen ph
  • jquery 验证错误位置

    这看起来很简单 但我无法弄清楚 我正在使用 jquery 验证插件 我验证所有文件 但我想要的是在输入文本行中显示验证消息警报 例如在电子邮件输入中 请填写电子邮件地址 但现在它出现在所有字段下 在我的html中
  • Jquery从下拉列表中获取所选值的id

    我有一个下拉列表 可以从数据库获取值 如下所示 get getJobs function jobs seljobs jobs var i 0 jobs forEach function n alert job id n id 32 67 4
  • Leaflet js虚构地图

    我是 Leaflet 的新手 我想了解如何创建完全交互式的虚构地图 我有一张图像想要转换为传单地图 该图像基本上像图表一样具有许多连接和点 我想首先将该图像转换为地图 能够将鼠标悬停在这些点上 突出显示它们并显示有关它们的信息 并且还可以在
  • 即使我可以监视其他方法,也无法监视事件处理程序

    我想使用 Jest Jasmine Enzyme 测试 React 中的事件处理程序 MyComponent js import React from react class MyComponent extends React Compon
  • javascript中按tab键时如何调用函数?

    我有一个这样的功能 function whenEmpty field if field value field style backgroundColor ffcccc alert Please fill the field field f
  • JavaScript 中数组的 HTML 数据列表值

    我有一个简单的程序 它必须从服务器上的文本文件中获取值 然后将数据列表填充为输入文本字段中的选择 为此 我想要采取的第一步是我想知道如何动态地将 JavaScript 数组用作数据列表选项 我的代码是
  • Javascript - 将值从下拉框传递到 Google Maps API

    我正在使用 Google 地图 API 为一家出租车公司创建报价表 目前 用户在 2 个文本框中输入出发点和接载点 API 会计算两点之间的距离以及行程费用 我正在尝试添加两个具有设定位置的下拉框 以便用户可以选择这些位置之一或使用文本框输
  • 是否有任何非轮询方式来检测 DOM 元素的大小或位置何时发生变化?

    很长一段时间以来 我一直在寻找一种方法来检测 DOM 元素的大小或位置何时发生变化 这可能是因为窗口调整了大小 或者因为向该元素添加了新的子元素 或者因为在该元素周围添加了新元素 或者因为 CSS 规则已更改 或者因为用户更改了浏览器的字体
  • Typeahead.js substringMatcher 函数说明

    我只是在做一些研究Typeahead js这是一个非常酷的图书馆 感谢文档 我已经成功地获得了一个基本的示例 该文档也非常好 但是我试图弄清楚以下代码块实际上在做什么 var substringMatcher function strs r
  • 将数组排序为第一个最小值、第一个最大值、第二个最小值、第二个最大值等

    编写一个JS程序 返回一个数组 其中第一个元素是第一个最小值 第二个元素是第一个最大值 依此类推 该程序包含一个函数 该函数接受一个参数 一个数组 该函数根据要求返回数组 输入示例 array 2 4 7 1 3 8 9 预期输出 1 9
  • Nodejs mysql 获取正确的时间戳格式

    我在用着mysqljs https github com mysqljs mysql得到结果后sql我变得不同TimeStamp格式如下 created at Sat Jul 16 2016 23 52 54 GMT 0430 IRDT 但
  • Jquery - 通过在字符串中构建 id 的 id 获取元素

    我在使用 jquery 元素时遇到问题 我正在 var 中构造名称 例如 var myId myGotId myId attr title changed myId 返回空 我想通过 id 获取我的元素 但动态构建我的 Id 连接字符串 编
  • 防止文本区域出现新行

    我正在开发聊天功能 使用 Vue 并使用文本区域作为输入 以便溢出换行 并且对于编写较长消息的用户来说更具可读性 不幸的是 当用户按下 Enter 键并提交时 光标会在提交之前移动到新行 从而使用户体验感觉不佳 关于如何使用普通 Javas
  • 单击列表时使用 bootstrap Dropdown 防止下拉菜单消失

    我正在使用使用引导下拉菜单 http twitter github com bootstrap javascript html dropdowns生成下拉菜单 我想防止点击菜单时菜单消失 我已经实现了以下代码 但它不起作用 知道如何修复它吗
  • 在 GWT 中,在任何主机页标记上添加事件处理程序

    我想为任何标签添加 MouseOver 事件处理程序 举个例子 我想为旧版 HTML 页面中的每个锚点页面添加事件处理程序 继GWT指南 http code google com webtoolkit doc 1 6 DevGuideUse

随机推荐

  • 一个网站服务器有多少个ip,一个服务器可以有多少个ip地址

    一个服务器可以有多少个ip地址 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 会话保持 指负载均衡器可以识别客户与服务器
  • 通过高通平台简单总结的权限问题

    android 5 x开始 引入了非常严格的selinux权限管理机制 我们经常会遇到因为selinux权限问题造成的各种avc denied困扰 有时候我们在添加了一些驱动或应用的时候 发现不能用 但是程序本身查不出问题来 那就要抓log
  • 详解JAVA远程debug

    目录 1 什么是远程debug 2 远程debug普通JAVA程序 环境 测试程序 程序启动指令 编译器配置 3 远程debug JAVA Web程序 4 远程debug spring boot程序 1 什么是远程debug 远程debug
  • 2021.11.17网上商城项目01

    网上商城项目 数据库 Unity 1 导入Unity连接数据库的插件 插件已上传 有需要的同学可以自行下载 2 先创建一个工具类用于数据库的连接 更新 读取 以及数据库的连接 读取的关闭 这样就可以不用每次都写 减少了代码的冗余 需要使用数
  • TCP/IP协议栈各层涉及到的协议

    21 tcp FTP 文件传输协议 22 tcp SSH 安全登录 文件传送 SCP 和端口重定向 23 tcp Telnet 远程连接 80 tcp HTTP 443 tcp HTTPS 计算机各层网络协议 五层 应用层 典型设备 应用程
  • jsp页面中文乱码解决方法

    在运行jsp页面时 发现本该出现中文的地方 出现的是乱码 中文乱码出现的原因一般是编码不符 检查一下代码 可以看到
  • PyQt5-多线程的使用

    PyQt中的多线程 它能实现多任务 让界面用一个线程更新 让逻辑代码在另外一个线程中 互不影响 如果不使用多线程的话 在运行一个时间较长的代码时 程序会卡住 使用多线程 import sys import time from PyQt5 i
  • Linux中使用Docker安装ElasticSearch7.10.x集群

    使用Docker安装ElasticSearch7 10 x单节点请访问这里 一 集群环境说明 服务器IP地址 192 168 137 1 192 168 137 2 192 168 137 3 二 前期准备 1 拉取镜像 docker pu
  • linux下percona-toolkit工具包的安装和使用(超详细版)

    一 检查和安装与Perl相关的模块 PT工具是使用Perl语言编写和执行的 所以需要系统中有Perl环境 依赖包检查命令为 rpm qa perl DBI perl DBD MySQL perl Time HiRes perl IO Soc
  • 【Python】只需2行代码,轻松将PDF转换成Word(含示范案例)

    文章目录 一 前期准备 二 pdf2docx功能 三 限制 四 案例 一 前期准备 可将 PDF 转换成 docx 文件的 Python 库 该项目通过 PyMuPDF 库提取 PDF 文件中的数据 然后采用 python docx 库解析
  • 来自对Socket的深度剖析

    Socket是什么 socket 的中文解释为 插座 非常的生动形象 在计算机通信领域 socket 被翻译为 套接字 它是计算机之间进行通信的一种约定或一种方式 通过 socket 一台计算机可以接收其他计算机的数据 也可以向其他计算机发
  • 【技巧】easyUI的datagrid,如何在翻页以后仍能记录被选中的行

    easyUI的datagrid在复选框多选时 如何在翻页以后仍能记录被选中的行 注意datagrid中需要配置idField属性 一般为数据的主键 转载于 https www cnblogs com yx007 p 8081522 html
  • 接口测试面试题含答案

    1 解释一下正向和逆向测试 正向测试 针对接口设计预期的功能和行为 验证接口是否按照预期工作 逆向测试 针对错误输入 不合理的条件或非预期的使用方式 验证接口是否能够适当地处理这些情况并提供合理的错误处理 2 什么是API和Web服务 AP
  • 支持CUDA运算的显卡算力表

    GPUs supported Supported CUDA level of GPU and card CUDA SDK 1 0 support for compute capability 1 0 1 1 Tesla CUDA SDK 1
  • c++17 using继承所有构造函数

    include tmp h include
  • 三维坐标系怎么画?

    在中学时代主要接触的是二维平面坐标需系 但是在学习空间几何图形时 会需要用到三维坐标系 这就需要我们也要掌握其绘制方法 在黑板上画三维坐标系有点困难 所以要借助专业的绘图工具来完成 下面就一起来学习具体绘制技巧 几何画板作为专业的几何绘图软
  • 智能手机普及游戏 国内外巨头上演GPU芯片争霸

    转自 http tech sina com cn t 2014 02 12 16139155996 shtml 新浪科技讯 2月12日下午消息 随着近日国家解除游戏机禁令以及游戏向手机终端转移 国内外移动通信芯片厂商高通 75 62 0 9
  • umi-request设置请求头_scrapy_splash 设置随机请求头

    本文为 霾大 scrapy splash 爬取 js 加载网页初体验 zhuanlan zhihu com 的补充 在上面的文章中我们仅仅是初步完成了 scrapy splash 的简单使用 接下来我们将介绍如何是使得 splash 在 r
  • 时间序列模型(二):AR模型

    全文共8000余字 预计阅读时间约18 30分钟 满满干货 建议收藏 介绍 在时间序列分析中 我们经常遇到一种强大而灵活的模型 即ARIMA模型 这个模型已经在各种领域 如经济学 气候学 股票市场分析等 发挥了巨大的作用 尽管ARIMA模型
  • 掌握react,这一篇就够了

    react众所周知的前端3大主流框架之一 由于出色的性能 完善的周边设施风头一时无两 本文就带大家一起掌握react jsx语法 前端MVVM主流框架都有一套自己的模板处理方法 react则使用它独特的jsx语法 在组件中插入html类似的