React DAY04

复习:
1.使用React的两种方式:
①脚本引入式:

<script src="./js/react.js"></script>
<script src="./js/react-dom.js"></script>
<script src="./js/babel.js"></script> 
<script type="text/babel">
	//1.创建虚拟DOM对象   React.createElement()
	//2.把真实DOM容器转换为虚拟DOM容器   ReactDOM.createRoot()
	//3.在虚拟DOM容器中渲染虚拟DOM元素   vparent.render(vchild)
</script>  

②脚手架方式:

Node.js>=V14.0、  npx  create-react-app  项目名、  cd 项目名 && npm start
public/index.html > div#root
src/index.js >  ReactDOM.createRoot().render(<App/>)
src/App.js  >  rcc或rfc

2.JSX中的数据绑定
内容绑定:<div>{表达式}</div>
属性绑定:<img src={表达式}/>
样式绑定:<div className={表达式} style={样式对象}></div>
事件绑定:<button onClick={函数} onClick={()=>函数(参数)}></button>
双向数据绑定:
条件渲染:

<div style={{display:表达式?'block':'none'}}></div>
{ 判定表达式 && (JSX)}
{ 判定表达式 ? (JSX1): (JSX2) }

列表渲染:
5.创建自定义组件的两种语法:
①函数式组件

function Rating( props ){
		return JSX
	}

②类式组件

class Rating extends React.Component{
	//挂载阶段:constructor()、render()、componentDidMount()
	//更新阶段:shouldComponentUpdate()、render()、componentDidUpdate()
	//卸载阶段:componentWillUnmount()
	state = { num: 18, age: 20 }
	add = ()=>{ this.setState({num: 19},()=>{}) }
	render(){  return  JSX }
}

6.React Hooks
React V16.8官方为函数式组件新增的特性:钩子
①本质就是函数,以use开头 ②只能在函数式组件中调用 ③只能在最顶层调用
官方目前提供了15个钩子函数,可以为函数式组件扩展15种功能
常用钩子之一: let [num, setNum] = useState(18) setNum(19) 异步但无第二个参数
常用钩子之二: useEffect( 生命周期方法 )

一、React概述

英文官网:https://reactjs.org/
中文网站:https://zh-hans.reactjs.org/
用于构建用户界面的 JavaScript 库 —— 其核心功能中不涉及HTML和CSS
其特点有三个:

①声明式 / 数据响应式
②组件化编程
③一次学习,到处编写 —— React可以创建网站、H5、WebApp、原生App

项目中使用React的两种方式:
方式1:脚本引入式

<script  src="react.js"></script>
<script  src="react-dom.js"></script>
<script  src="babel.js"></script>

方式2:脚手架方式 在服务器端编译/渲染
使用方法:
①确保Node.js版本号达标

  node  -v       必须确保版本号>=14.0.0

②下载全局脚手架工具 —— create-react-app

  npm   i   -g    create-react-app

③运行脚手架工具,创建空白项目

  create-react-app   项目名       //注意:React项目名不能包含大写字母
  提示:上述②③两步可以使用一行命令代替: npx  create-react-app  项目名

④进入空白项目

  cd  项目名

⑤启动其中的开发服务器,浏览器会自动打开,显示默认首页

  npm  start

二、JSX

JSX:JavaScript XML,使用XML语法创建JS对象的技术。这种语法本身是TS的一部分,与React没有必然的联系(不过JSX确实是因为React而流行)。
使用JSX需要注意:
1.语法类似于XML(严格来说不是HTML)
2.有且只能有一个根元素,根元素下面可以有多个子/孙元素;如果根元素有多个,那就在外面再套一个父元素:<></>、<React.Fragment></React.Fragment>
3.标签/属性名严格区分大小写
4.标签必须闭合
5.因为浏览器不支持TS语法,也就不支持JSX语法;——必须使用一款TS编译器,把JSX语法转换为标准JS语句
6.注意:JSX的本质是运行于严格模式下的React.createElement( ),是JS不是HTML!!!React项目可以不用JSX,但是使用了JSX,创建虚拟DOM元素语法会变得简单
7.JSX语法中可以任意添加换行
8.JSX中的注释: {/* 注释内容 */}
9.JSX中元素可以使用的属性与HTML标签的属性大体类似,但是有些是不同的,例如:

HTML: class				JSX:className
HTML: onclick / onkeyup	JSX:onClick / onKeyUp

10.JSX中可以执行数据绑定,不论是哪种绑定(内容绑定/属性绑定/样式绑定/事件绑定…)语法都是一样的:{ 表达式 }

<div  title={表达式}  style={表达式}  onClick={表达式}>{表达式}</div>
注意:React中“内容绑定”禁止绑定Object!!!“样式绑定”必须绑定一个样式Object!!!

三、React中自定义组件

React中提供了两种创建自定义组件的语法:
语法1: 函数式组件(Function Component)

function ZhRating( props ){
    return <div>⭐⭐⭐⭐⭐</div>
}
let vchild = <ZhRating color="#f00" count={5}/>

注意:React要求,HTML元素对应的JSX标签必须用纯小写;自定义组件名必须采用大驼峰命名法(每个单词首字母必须大写)

语法2: 类式组件(Class Component)

class ZhRating  extends  React.Component {
    render( ){
       //使用this.props读取组件属性
       return <div>⭐⭐⭐⭐⭐</div>
    }
}
let vchild = <ZhRating color="#f00" count={5}/>

四、重点&难点&面试题:React中有时this指向会丢失/this会指向undefined,为什么?如何解决?

一般情况下,class中的方法访问当前类中的属性或其它方法,都要使用this——它指向当前类的当前实例;
有一种特例:JSX事件处理函数中的this,却指向undefined!!!
可能性1:this指向事件源对象? 否——虚拟DOM元素不能做事件源
可能性2:this指向class或实例? 否——类的实例方法赋值给另一个对象了
可能性3:this指向window? 否——Babel编译后的结果运行在严格模式
可能性4:this指向undefined? 是
解决方案:
方案1:使用箭头函数(不能传参)

f1 = ()=>{  log(this)  }
<button onClick={ this.f1 }>

方案2:使用箭头函数(可以传参)

f1 = function( ){  log(this)  }
<button onClick={ ( )=>this.f1( ) }>

方案3:使用bind固定this指向(多次bind会生成多个副本)

f1 = function( ){  log(this)  }
<button onClick={ this.f1.bind( this ) }>

方案4:使用bind固定this指向(生成且仅生成一次副本)

constructor(){
   super()
   this.f1 = this.f1.bind( this )
}
f1 = function( ){  log(this)  }
<button onClick={ this.f1 }>

五、组件的状态数据(State)

面试题:Vue.js和React的区别?尤雨溪答:
Vue.js中的数据响应式采用“Push-Based”机制——数据的改变会自动推送出去,告诉渲染系统重新渲染;

data: { return {  count: 1 } }
this.count = 2		//此处的修改会执行两项任务:①修改模型变量  ②通知渲染系统重新渲染整个视图

React中的数据响应式采用“Pull-Based”机制,即组件的模型数据改变必须手工通知渲染系统。

state = {  count:  1 }
this.state.count = 2		//此处的修改仅仅修改了变量的值,不会通知渲染系统
this.setState({ count: 2 })   //setState()会修改状态变量,并通知渲染系统

面试题:关于setState()方法
① setState()方法只会覆盖state中的同名属性,而不丢弃其它属性
② setState()方法是异步执行的,启动渲染系统很耗时,不会立即进行
③ setState()因为是异步的,所以它后面的语句会先执行,然后才去修改状态变量;如果想查看修改后的状态数据,必须放在第二个参数(状态修改并重新渲染后的回调) setState( state, callback )

六、JSX中的数据绑定 —— React中没有指令的概念

注意:JS中变量、常量、运算式、调用方法都是“表达式”;但是if、for、function不是“表达式”!!!{ }中只能放置表达式!!!
内容绑定:<div>{表达式}</div>
属性绑定:<img src={表达式}/>
样式绑定:<div className={表达式} style={表达式}>
事件绑定:<button onClick={函数} onMouseEnter={函数}>
双向数据绑定:React中没有双向数据绑定的概念,但可以使用两个方向上的绑定模拟实现双向数据绑定
方向1:Model=>View

<input value={uname}/>

方向2:View=>Model

<input onChange={e=>setUname(e.target.value)}/>  

条件渲染:
仿v-show:<any style={{display: this.state.show ? "block" : "none"}}/>
仿v-if:{ 判定表达式 && (JSX) } { 判定表达式 ? (JSX1) : (JSX2) }
列表渲染:

let empList = ['亮亮', '小明', '小鑫']
<ul>{ empList.map( (e, i)=>JSX ) }</ul>     

面试题:React中获取表单元素当前的输入内容,有两种方式?

方式1:受控组件 —— 监控用户的每一次输入是否合规
React要求每个表单元素都只能有“单一数据源”,要么是“用户输入”,要么是“模型变量”,不能二者同时生效:

  <input />  ——  此时数据源就是“用户输入”
  <input value="模型变量" onChange={e=>setXxx(e.target.value)}/>  —— 此时数据源就是“模型变量”—— 此时输入框就不能再接收用户输入了,这种状态称为“输入框被模型变量控制住了”,称为“受控组件”

方式2:非受控组件 —— 不必监视用户的每次输入,最后提交时能够读取到值即可
非受控组件不能指定value属性,只能在最后提及时通过ref找到该元素,获取其中最新输入

  let resumeRef = useRef()
  <input ref={resumeRef}  defaultValue="初始值"/>
  resumeRef.current.value 就是当前最新的输入的内容

七、class组件的生命周期方法

第一阶段:挂载阶段

constructor():创建组件对象
render():渲染组件的内容
componentDidMount():组件完成挂载

第二阶段:更新阶段(state/props发生改变)

shouldComponentUpdate():此次数据改变应该重新渲染组件吗?
render():重新渲染组件内容
componentDidUpdate():组件完成更新

第三阶段:卸载阶段

componentWillUnmount():组件即将卸载

八、重点/难点/面试题:Hook(钩子)

自从React诞生,“函数式组件”功能一直有缺失:没有状态、没有生命周期方法 —— 没有父类,导致函数式组件只能编写一些简单的固定内容的组件。
V16.8开始,官方为“函数式组件”弥补了不足——增加了“Hook”的概念,同时由于自身的优势(天然没有this),导致越来越多的程序员开始偏向使用“函数式组件”。
当前的项目中,可以同时使用“类式组件”和“函数式组件”。

Hook的定义:
①钩子,用于勾住/增加一些扩展的功能
②每个Hook都是一个函数,都必须以 use 开头,例如:useState()、useRef()
③Hook函数只能在“函数式组件”中使用,不能用于“类式组件”
④Hook函数只能在“函数式组件”的最顶层调用,不能在内层调用

function Child(){
		useState()  				//合法!最顶层
		f1=function(){  useState() } 	//错误!
		if(){ useState() }  			//错误!
		for(){ useState() }  			//错误!
		useState()  				//合法!最顶层
	}

React官方提供的常用钩子之一 —— useState( ):为组件添加状态变量

import  { useState }  from  'react'
let  [ 状态变量名,  修改状态变量的方法名 ] = useState( 状态变量初始值 )

React官方提供的常用钩子之二 —— useEffect( ):为组件添加生命周期方法

//生命周期方法1 —— 用于监视整个组件数据的改变(从无到有,从1到2...)
useEffect( ( )=>{
    //生命周期方法1 = 组件挂载 + 任意数据更新
} )
//生命周期方法2 —— 用于监视组件特定数据的改变(从无到有,从1到2...)
useEffect( ( )=>{
    //生命周期方法2 = 组件挂载 + 指定数据更新
} , [count, age, ...] )     //依赖列表有内容
//生命周期方法3 —— 用于监视组件挂载
useEffect( ( )=>{
    //生命周期方法3 = 组件挂载 
} , [ ] )     //依赖列表为空
//生命周期方法4 —— 用于监视组件数据的更新(获取旧值)和销毁——可用于执行旧数据的清理操作
useEffect( ( )=>{
    return  ( )=>{
         //生命周期方法4 = 任意数据更新(旧值) + 组件卸载         
    }
} )    
//生命周期方法5 —— 用于监视特定数据的更新(获取旧值)和销毁——可用于执行旧数据的清理操作
useEffect( ( )=>{
    return  ( )=>{
         //生命周期方法5 = 指定数据更新(旧值) + 组件卸载         
    }
} , [count, age, ...])    //依赖列表不为空
//生命周期方法6 —— 用于监视组件的销毁——可用于执行组件的清理操作
useEffect( ( )=>{
    return  ( )=>{
         //生命周期方法6 = 组件卸载         
    }
} , [ ])    //依赖列表为空
框架	组件库
Vue.js	PC端:ElementUI
移动端:MintUI、VantUI
uni-app	偏移动端:uni-ui
React	PC端:Ant Design
移动端:VantUI、ReactNative

九、React Native组件库

React是一个MVVM框架;
ReactNative是一个基于React框架的移动端UI组件库——是Facebook官方提供的;
官网:https://reactnative.dev/
中文网:https://reactnative.cn/
Vue.js+Vant项目运行原理:
.vue => Webpack编译打包 => .html/.css/.js => 运行于客户端浏览器
React+RN项目运行原理:
.js/.jsx => Webpack编译 => .java或.oc => JAVA或OC编译 => .apk或.ipa安装包 => 安装到手机中运行为原生App(完全脱离浏览器)

(可选操作)在自己电脑上搭建RN编译环境,创建出一个空白的RN项目——3GB+
  ①安装基础软件
  ②安装AndroidStudio
  ③运行AndroidStudio,使用它下载AndroidSDK
	C:\Users\tedu\AppData\Local\Android\Sdk
  ④修改Windows系统环境变量,指定AndroidSDK安装路径
  ⑤创建RN空白项目,下载必需的第三方模块
  ⑥编译RN空白项目,得到JAVA代码再打包得到.apk安装包
(必选操作)运行空白RN项目,在自己的电脑和手机中运行该项目——250MB+
  ①PC端运行RN项目自带的开发服务器
	cd  MyRnApp   &&   npm  start
	提示:开发服务器只会占用8081端口
  ②启动安卓模拟器,安装RN项目编译得到的App
	APK路径:MyRnApp\android\app\build\outputs\apk\debug
  ③启动手机中的App,在App设置中配置开发服务器的IP和端口号
	查看Windows服务器当前的真正IP地址: ipconfig
  	例如,我当前电脑的IP地址是  192.168.0.105
 	点击手机“菜单键”>Settings>DebugServerHost&PortForDevice>输入:
	192.168.0.105:8081
  ④重启手机中的App,会自动连接开发服务器,获取最新的内容

如果提示:App已停止、App无法启动、App启动后白屏.....请重启Windows再重试上述几步
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值