React 中的JSX

486 阅读2分钟

1. react的三大特点

  1. 声明式编程

    • 声明式编程是目前整个大前端开发的模式:Vue、React、Flutter、SwiftUI
    • 它允许我们只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染我们的UI界面
  2. 组件化开发

    • 组件化开发页面目前前端的流行趋势,我们会讲复杂的界面拆分成一个个小的组件

  1. 多平台的适配

2. JSX

  1. JSX】可以被看做是【JS】的扩展语法,它既不是【字符串,也不是一个html】,他包含一个JS的所有功能,当浏览器进行解析的时候,遇到【<>】,会当作html代码进行编译,在【JSX】创建DOM的时候,必须有根元素进行包裹
function App() {
	return (
  	<div>
    	我是内容
    </div>
  )
}
export default App

2.1 JSX中书写JavaSscipt代码

  1. 通过在【JSX】语法的内部通过【{ }】的方式,对JavaScript代码进行包裹,浏览器遇到【{}】,就会当作JavaScript代码,进行编译
1. 动态显示数据与注释的添加 】
function App() {
  const name = 'JSX语法'
  return (
  	<div>
    	{ name }
      { /* 注释内容 */ }
    </div>
  )
}
export default App2. JSX里可以的使用模板字符串 】
const name = '模板字符串'
function App() {
  return (
  	<div> {`${name}`} </div>
  )
}
export default App3. 可以调用函数方法,也可以调用内置方法 】
const hello = () => {
  	console.log('你好 ')
}
function App() {
  return (
  	<div>
      { hello() } // 调用方法
      { Math.random() } // 调用系统方法
      { console.log('JSX') }
    </div>
  )
}
export default AppPS: 在调用方法的时候,不仅仅可以调用自定义的方法,也可以调用系统内置的方法,进行使用 】

【 4. JSX中逻辑判断,只能够使用三元表达式,不支持if语句 】
const isShow = true
function App() {
	return (
  	<div>{ isShow ? 'JSX' : 'react'  }</div>
  )
}
export default App5. JSX语法本身就是语句,可以赋值给变量,可以当作函数的参数等 】
const dvs = <p>可以赋值给变量</p>
function App() {
  return (
  	<div>
      { dvs }
    </div>
  )
}

【 6. 给元素添加属性 】
function App() {
	return (
  	<div class={ age }></div>
  )
}
export default AppPS:在给元素添加属性的时候,一般会存在两种情况,一种是普通的类名添加,另一种是通过给属性赋值【{变量}】 】

2.2 JSX事件

  1. 事件绑定
1. 事件绑定,事件驼峰命名法={ 事件处理名称 } 】
const handle =()=> {
	console.log('JSX中的事件')	
}
function App() {
	return (
  	<div>
    	<button onClick={handle}>普通事件绑定</button> // 普通书写是不需要添加【(),如果加上括号就立即执行了】
      
      <button onClick={() => {handle()}}>箭头函数绑定</button> // 通过箭头函数的方式绑定事件
    </div>
  )
}
export default App2. bind绑定事件,类组件常用,它可以改变事件的this的指向 】
import React,{Component} from 'react'
class Heaber extends Component{
	constructor () {
    super();
    this.state = { // 初始化状态
        const: 0
    }
    this.handoler = this.handoler.bind(this) // 更改this操作(方式一)
	}
  render() {
    return (
    	<div>
      	<button onClick={this.innerText.bind(this)}>bind</button>
      </div>
    )
  }
  innerText () {
  	this.setState({
    	const++
    })
  }
}
  1. 事件传参
1. 箭头函数的方式参数传递 】
const handle =(a,b) => {
	console.log(a,b)
}
function App() {
	return (
  	<div>
 			<button onClick={() => {handle(1,2)}} >箭头函数传参</button>   	
    </div>
  )
}
export default App2. bind的方式进行参数传递 】
const handole = (a,b) => {
	console.log(a,b)
}
function App() {
	return (
  	<div>
    	<button onClick={handole.bind(null,1,2)}>bind传惨</button> // 参数传递从第二个参数开始
    </div>
  )
}
  1. 事件对象【如何获取事件对象】
1. 普通事件调用怎样拿到事件对象 】
const handole =(ev) => { 【普通函数,在事件绑定的时候是不需要传递的,默认接收一个事件对象】
	console.log(ev)				
}
function App() {
	return (
  	<div>
    	<button onClick={handole}>普通事件</button>
    </div>
  )
}

【 2. 箭头函数方式传递事件对象 】
const handole =(ev) => { 【情况一】
	console.log(ev)
}
const handole =(a,b,ev) => { 【情况二:如果在参数传递的时候,不仅仅传递了事件对象,还有其他参数,默认事件对象是最后被接收的】
	console.log(a,b,ev)
}
function App () {
	return (
  	<div>
    	<button onClock={(ev) =>{handole(ev)}}>箭头函数</button>
    </div>
  )
}

【 3. bind的方式是如何传递的 】
const handole = (a,b,ev) =>{ 【如果bind在传递参数时,没有传递事件对象,默认接收一个事件对象,是在其他参数之后接收的】
	console.log(a,b,ev)
}
function App() {
	return (
  	<button onClock={handole.bind(null,100,200)}>bind</button>
  )
}

2.3 类组件中方法的this问题

【 例子: 】
import React,{Component} from 'react'

class App extends Component{
	constructor () {
    super();
    this.state = { // 初始化状态
        content: 0
    }
	}
  render() {
    return (
    	<div>
      	<button onClick={this.innerText}>bind</button>
      </div>
    )
  }
  innerText () {
  	console.log(this.state.content) // undefined state,
  }
}
【 问题 】
	* 在事件触发的时候,方法被调用,但是打印的是undefined state ,意思是undefined下面没有state属性,
  	问题就出在,绑定事件上【 回看 】
    
【 1. 解决方式一:在元素绑定事件的时候,通过bind将this改变 】
render() {
  return (
  	<div>
    	<button onClick={this.innerText.bind(this)}>bind</button>
    </div>
  )
}
【 2. 解决方式二:在类组件的构造器中对this的绑定进行更改 】
constructor () {
   super();
   this.state = { // 初始化状态
       content: 0
   }
   this.handoler = this.handoler.bind(this) // 对事件的this指向进行更改
}
【 3. 解决方式三:在书写事件程序的时候使用箭头函数的方式,由于箭头函数是没有this的,默认会向外面查找this 】
innerText = () => {
	console.log(this.state.content)
}

【 4. 解决方式四:绑定时使用箭头函数 】
render() {
  return (
  	<div>
    	<button onClick={() => {this.innerText()}}>bind</button>
    </div>
  )
}

3. 遍历数据

  1. 在react中,对数据的循环遍历,通过使用【高级方法map】对数据进行循环遍历,在对数据循环遍历的时,要给遍历的每一项加上一个【key】值,提高渲染的性能
const arr = [
  {
  	id: 1,
    name: 'jsx'
  },
  {
  	id: 2,
    name: 'map'
  }
]
function App() {
	return (
  	<div>
    	<ul>
        {
        	arr.map(item => {
          	return (
            	<li key={item.id}>{item.name}</li>
            )
          })
        }
      </ul>
    </div>
  )
}
export default App

3.1 后端返回数据,前端对数据进行截取

  1. 在有些开发的时候,前端向后端发送请求,请求数据,后端返回数据较多,但是,前端页面需求只需要很少的几条,这时,我们要对后端返回的数据进行截取操作,只截取需要的条数从前到后进行截取
【 调用数组的方法slice 】
【 循环数据并进行数据筛选 】
arr.slice(0,9).map(item => { // 在循环数组之前,对数据进行截取,然后返回新的数组,在进行遍历
	return (
  	<li key={item.id}>{item.name}</li>
  )
})

3.2 对数据进行过滤

【 循环数据并进行数据筛选 】
arr.filter(item => {
	return 代码块
}).map(item => { // 在循环数组之前,对数据进行筛选,然后返回新的数组,在进行遍历
	return (
  	<li key={item.id}>{item.name}</li>
  )
})

4. 对样式的处理

  1. 在react中,动态绑定类名的话,是不能使用class,而是使用【className】

4.1 行内样式

1. 行内样式 】
const style = { // 方式二,注意是逗号隔开
	width: 100,
  height: 100
}
function App () {
	return (
  	<div>
    	<button style={{ width:'100px' }}>方式一</button>【例如background-color == 必须使用驼峰方式】
      <button style={ style }>方式二</button>
      <button style={[ style,style ]}>方式三</button> 【 多个样式的写法】
    	【 可以使用三元表达式,决定哪一个类生效 】
    </div>
  )
}

【 2. 使用伪类 】
	* 下载包,由于react中,不可以处理伪类,所以需要使用包,来处理伪类【npm install --save-dev radium】
import Radium from 'rudium'
const styles = {
  backgroundColor: 'green',
  ":hover": {
    backgroundColor: `rgb(0,0,1)`
  }
}
function App() {
	return () {
    <button style={ styles } ></button>
	}
}
export default Radium(App)

【 3. 媒体查询 index.js 入口文件】
import { StyleRoot } from 'radium'
ReactDOM.render(
  <React.StrictMode>
        // 需要使用改标签对组件进行包裹使用,这样设置的媒体查询可以进行使用
   <StyleRoot> <App /></StyleRoot>
        
  </React.StrictMode>,
  document.getElementById('root')
);

4.2 外联样式

* 全局外联样式

【 引入,入口文件,app.jsimport './app.css'

【 组件内部使用 】
function App() {
  return (
      <div className={ 'box' }></div>
  )
}
export default App

* 单个组件外部样式

【 引入 】
	* 在使用单个组件外联样式的时候,再给样式表命名的时候,一般采用两种形式,
	  第一种就是与组件名称相同,`某一个组件.module.css`
import style from '样式路径'

function App() {
	return (
    <div className={ style.某一个类名 } ></div>
  )
}
export default App

5. 对于元素的属性的操作

1. img > src属性 】
	* 有些时候,前端向后端请求数据,请求一些图片的数据,在这个时候,后端给前端返回一张非常大的图片
		前端要根据页面,区调整图片的大小,这样调整,性能不是很好,当浏览器加载的时候,加载的是一个很大的
    图,所以在后端返回图片的时候,需要对图片进行一些出处理,并不是通过css对图片进行设置
    
    * 创建一个方法,用于处理图片的大小,一般在开发的时候,常见专门的处理图片的文件
		function getImgUrl( imgUrl,size ) {
    	return imgUrl + `?param=${size} + ${size}` // 对大图进行处理
    }

		function App() {
    	return (
      	<div>
        	<img src={getImgUrl(图片地址,要设置的图片大小)}/>
        </div>
      )
    }


【 2. 元素 > class属性 】

【 3. a > href属性 】

【 4. 元素 > style属性 】

【 5. label > for属性 】

6. JSX的本质(需要补充源码)

  1. 【JSX】的本质仅仅只是【React.createElement(component,props,...children)】的语法糖写法
  2. 所有的【JSX】最终都会通过【babel】进行转换,转换成【React.createElement】的函数调用

7. 初识虚拟DOM的创建过程(需要补充源码)

  1. 【JSX】转换成【React.createElement()】函数,在通过这个函数创建一个【ReactElement】对象

  2. react通过【ReactElement】对象,去组成【JavaScript的对象树】

  3. 被组成出来的【JavaScript的树】就是【虚拟DOM】

  4. 【ReactElement】的结构

  1. 在react中是如何将【虚拟DOM】转换成真实的DOM,在react中通过【ReactDOM.render()】将【虚拟DOM】与【真实的DOM】【映射在一起(同步一起)】