react学习二: JSX语法的使用

JSX语法出现的原因:

为了在项目中不用老是使用 React 提供的 JS API 来创建虚拟DOM节点,于是React 官方,就提出了一套 JSX 语法规范,能够让我们在 JS 文件中,书写类似于 HTML 那样的代码,快速定义虚拟DOM结构

JSX:

符合 XML 规范的 JS 语法

JSX的原理:

JSX内部在运行的时候,也是先把 类似于HTML 这样的标签代码,转换为了 React.createElement 的形式;也就是说哪怕我们写了 JSX 这样的标签,也并不是直接把 我们的 HTML 标签渲染到页面上,而是先转换成 React.createElement 这样的JS代码,再渲染到页面中

JSX语法的本质:

还是以 React.createElement 的形式来实现的,并没有直接把 用户写的 HTML代码,渲染到页面上

JSX的使用:

先运行 `cnpm i babel-preset-react -D`

然后再 `.babelrc` 中添加 语法配置,在语法presets所对应的数组中增加react

{
  "presets": ["env", "stage-0", "react"],
  "plugins": ["transform-runtime"]
}

编写要渲染的虚拟DOM元素对应的html代码

var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1>JSX</h1>
    <p>符合 XML 规范的 JS 语法</p>
</div>

使用 ReactDOM 把元素渲染到页面指定的容器中

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

如果要在 JSX 语法内部,书写 JS 代码了,那么,所有的JS代码,必须写到 {} 内部;

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle}>JSX</h1>
    <p>符合 XML 规范的 JS 语法</p>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

当 编译引擎,在编译JSX代码的时候,如果遇到了`<`那么就把它当作 HTML代码去编译,如果遇到了 `{}` 就把 花括号内部的代码当作 普通JS代码去编译;在{}内部,可以写任何符合JS规范的代码;

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle+'abcd'}>JSX</h1>
    <p>符合 XML 规范的 JS 语法</p>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

在JSX中,如果要为元素添加`class`属性了,那么,必须写成`className`,因为 `class`在ES6中是一个关键字

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle+'abcd'}>JSX</h1>
    <p class='myp'>符合 XML 规范的 JS 语法</p>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

解决办法把p标签的class属性改写为className

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle+'abcd'}>JSX</h1>
    <p className='myp'>符合 XML 规范的 JS 语法</p>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

和`class`类似,label标签的 `for` 属性需要替换为 `htmlFor`

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle+'abcd'}>JSX</h1>
    <p className='myp'>符合 XML 规范的 JS 语法</p>
    <label for=""></label>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

解决办法把label标签的for属性改写为htmlFor

var mytitle = '这是使用变量定义的 tilte 值'
var myDiv = <div>
    这是使用jsx语法创建的div元素
    <h1 title={mytitle+'abcd'}>JSX</h1>
    <p className='myp'>符合 XML 规范的 JS 语法</p>
    <label htmlFor=""></label>
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

在JSX创建DOM的时候,所有的节点,必须有唯一的根元素进行包裹

循环元素:

{}里面只能简单表达式,不能放程序语句

  {
      for (var i = 0; i < 10; i++) {
        var p = <p className="myp" key={i}>符合 XML 规范的 JS 语法</p>
        arr.push(p)
      }
  }

会报错

var mytitle = '这是使用变量定义的 tilte 值'
var arr = []
for (var i = 0; i < 10; i++) {
  var p = <p className="myp">符合 XML 规范的 JS 语法</p>
  arr.push(p)
}
var myDiv = <div>
  这是使用 jsx 语法创建的div元素
  <h1 title={mytitle + 'aaaaa'}>JSX</h1>
  <p className="myp">符合 XML 规范的 JS 语法</p>
  <label htmlFor=""></label>
  {arr}
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

需要加入key属性唯一标识每个循环到的元素

var mytitle = '这是使用变量定义的 tilte 值'
var arr = []
for (var i = 0; i < 10; i++) {
  var p = <p className="myp" key={i}>符合 XML 规范的 JS 语法</p>
  arr.push(p)
}
var myDiv = <div>
  这是使用 jsx 语法创建的div元素
  <h1 title={mytitle + 'aaaaa'}>JSX</h1>
  <p className="myp">符合 XML 规范的 JS 语法</p>
  <label htmlFor=""></label>
  {arr}
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

如果要写注释了,注释必须放到 {} 内部

var myDiv = <div>
  /* 这是多行注释,你肯定看不到我 */
  { 
    // 这样写注释,不要和花括号放到一行 
  }
  { /* 这样写注释,可以和花括号放到一行  */ }
</div>
ReactDOM.render(myDiv, document.getElementById('app'))

第一种创建组件的方式

创建最基本的组件的方式

在React中,构造函数,就是一个最基本的组件

如果想要把组件放到页面中,可以把 构造函数的名称,当作 组件的名称,以 HTML标签形式引入页面中即可

注意:React在解析所有的标签的时候,是以标签的首字母来区分的,如果标签的首字母是小写,那么就按照 普通的 HTML 标签来解析,如果 首字母是大写,则按照 组件的形式去解析渲染,所以组件的首字母必须是大写

function Hello(props) {
  return <div>
    <h1>这是在Hello组件中定义的元素</h1>
  </div>
}
ReactDOM.render(<div>
    <Hello></Hello>
</div>,document.getElementById('app'))

父组件向子组件传递数据

在组件中,如果想要使用外部传递过来的数据,必须,显示的在 构造函数参数列表中,定义 props 属性来接收;

通过 props 得到的任何数据都是只读的,不能从新赋值

function Hello(props) {
  return <div>
    <h1>这是在Hello组件中定义的元素---{props.name}---{props.age}---{props.person.address}</h1>
  </div>
}
var name = 'axiaoha'
var age = 22
var person = {
  name: 'aha',
  age: 20,
  gender: '女',
  address: '广州'
}
ReactDOM.render(<div>
    <Hello name={name} age={age} person={person}></Hello>
</div>,document.getElementById('app'))

将组件封装到单独的文件中

如果把子组件单独提取出来放到一个jsx文件中去,需要注意的几点:

在jsx文件中要记得导入包

import React from 'react'

在webpack.config.js文件中要加入第三方加载器加载jsx文件的匹配规则,和js文件使用的是同一个第三方加载器

{ test: /\.jsx?$/, use: 'babel-loader', exclude: /node_modules/ }

子组件所对应的Hello.jsx文件代码:

import React from 'react'

function Hello(props) {
  return <div>
    <h1>这是在Hello组件中定义的元素 --- {props.name}</h1>
    <p id="">哈哈哈哈</p>
  </div>
}

// 把创建的组件暴露出去
export default Hello

在main.js中,需要导入子组件

import Hello from './components/Hello.jsx'

使用 ReactDOM 把元素渲染到页面指定的容器中

ReactDOM.render(<div>
  {/* <Hello name={person.name} age={person.age} gender={person.gender} address={person.address}></Hello> */}

  <Hello {...person}></Hello>
</div>, document.getElementById('app'))

第二种创建组件的方式

class关键字基本概念

https://blog.csdn.net/zerobaek/article/details/84553617

使用class关键字创建组件

使用 class 创建的类,通过 extends 关键字,继承了 React.Component 之后,这个类,就是一个组件的模板了

class Hello2 extends React.Component{

}

如果想要引用这个组件,可以把 类的名称, 以标签形式,导入到 JSX 中使用

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

会报错:

No `render` method found on the returned component instance: you may have forgotten to define `render`.通过分析报错,在 class 实现的组件内部,必须定义一个 render 函数

解决,在Hello2类中加入render函数:

class Hello2 extends React.Component{
  render(){
    
  }
}

然后会报第二个错误:

 Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.通过分析报错,在 render 函数中,还必须 return 一个东西,如果没有什么需要被return 的,则需要 return null

解决,在render函数中加一个return返回值:

class Hello2 extends React.Component{
  render(){
    return <div>
      <h1>这是使用class类创建的组件</h1>
    </div>
  }
}

父组件向子组件传值

ReactDOM.render(<div>
  <Hello2 address="广州" info="天河区"></Hello2>
</div>, document.getElementById('app'))
class Hello2 extends React.Component{
  render(){
    return <div>
      <h1>这是使用class类创建的组件</h1>
      <h3>外界传递过来的参数:{this.props.address} --- {this.props.info}</h3>
    </div>
  }
}

在function定义的组件中,如果想要使用props,必须先定义,否则无法直接使用,但是在class定义的组件中,可以直接使用this.propsz来直接访问,不需要预先接受props;在 constructor 中,如果想要访问 props 属性,不能直接使用 this.props, 而是需要在 constructor 的构造器参数列表中,显示的定义 props 参数来接收,才能正常使用;

  constructor(props){
    // 注意: 如果使用 extends 实现了继承,那么在 constructor 的第一行,一定要显示调用一下 super()
    //  super() 表示父类的构造函数
    super(props)
    console.log(this.props)
    console.log(props)
  }

两种创建组件方式的对比

使用 function 构造函数创建的组件,内部没有 state 私有数据,只有 一个 props 来接收外界传递过来的数据;

使用 class 关键字 创建的组件,内部,除了有 this.props 这个只读属性之外,还有一个 专门用于 存放自己私有数据的 this.state 属性,这个 state可读可写

基于上面的区别:我们可以为这两种创建组件的方式,下定义了: 使用 function 创建的组件,叫做【无状态组件】;使用 class 创建的组件,叫做【有状态组件

有状态组件和无状态组件,最本质的区别,就是有无 state 属性;同时, class 创建的组件,有自己的生命周期函数,但是,function 创建的 组件,没有自己的生命周期函数

什么时候使用 有状态组件,什么时候使用无状态组件:

如果一个组件需要存放自己的私有数据,或者需要在组件的不同阶段执行不同的业务逻辑,此时,非常适合用 class 创建出来的有状态组件;

如果一个组件,只需要根据外界传递过来的 props,渲染固定的 页面结构就可以了,此时,非常适合使用 function 创建出来的 无状态组件;(使用无状态组件的小小好处: 由于剔除了组件的生命周期,所以,运行速度会相对快一点)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值