目录
react
recat基本概念
react是由facebook开发的
recat是一个专门用于构建用户界面的javascript库
为了解决页面更新dom加载慢的问题 所以推出的react这个js库 来高效的解决大型项目中的dom加载国漫页面渲染过慢的问题
recat特点
声明式设计:我们只需要告诉程序干什么 程序会自己帮我们完成
高效
灵活
组件化
单项数据流
发展史
2013年推出的 在13年9月份 就受到了市场的追捧 15年3月 推出了一个reactNative的技术(使用react写app)
兼容性
ie8以下无效
脚手架创建-cra
cra---create-react-app
1.全局安装cra
npm install -g create-react-app
2.查看版本
create-react-app --version
3.cd到项目下
4.开始创建项目 create-react-app 项目名
5.cd到项目下
6启动 npm start
JSX
我们在react中编写内容使用的是JSX的语法 JSX=javascript and XML
遇见<就会当htm解析 遇到{}当js解析 jsx的外层最好用一对()包裹>
注意:jsx是一个非常严格的语法要求 标签必须遵循w3c规范完成 标签必须关闭
JSX优点:
1.安全可靠 因为在编译的时候就会发现错误
绑定变量
使用{}来进行绑定
<h1>你坏-----{text}</h1>
html的属性插入变量
不要双引号 直接{}
{/* 属性插变量 */}
<a href={ahref}>{btntext}</a>
多行标签
多行标签必须有一个父容器来进行包裹
jsx 注释
{ /*我是jsx的注释*/ }
遍历数据
在react中遍历数据使用map()
{
arr.map((v,i)=>{
return (
<li key={i}>{v}</li>
)
})
}
<table>
{/* 不加会有警告 */}
<tbody>
{
obj.map((v,i)=>{
return (
<tr key={i}>
<td>{v.name}</td>
<td>{v.age}</td>
</tr>
)
})
}
</tbody>
</table>
设置样式
类样式
以为class是es6类的关键字 所以要使用className
引用样式使用import哎进行引用
import React, { Component } from 'react'
export default class homed extends Component {
render() {
return (
<div>
{/* 在react中如果要设置类样式 class必须变成className */}
<h1 className="demoh">类样式</h1>
</div>
)
}
}
引用样式文件
import React, { Component } from 'react'
// 引用css文件
import "./homed.css"
export default class homed extends Component {
render() {
return (
<div>
{/* 在react中如果要设置类样式 class必须变成className */}
<h1 className="demoh">类样式</h1>
</div>
)
}
}
行内样式
行内样式使用对象的方式来进行设置 所以{ {}} 外面的{}是jsx的语法 里面的{}是对象的语法
而且如果多个单词 那么把-去掉 后面的单词首字母大写
import React, { Component } from 'react'
// 引用css文件
import "./homed.css"
export default class homed extends Component {
render() {
return (
<div>
{/* 在react中如果要设置类样式 class必须变成className */}
<h1 className="demoh">类样式</h1>
{/* 行内样式使用对象的方式来进行设置 */}
{/* 而且如果多个单词 那么把-去掉 后面的单词首字母大写 */}
<h1 style={
{color:"red",backgroundColor:"pink"}}>行内样式</h1>
</div>
)
}
}
组件
本质 自定义标签
组件的特点优势
强内聚 弱耦合
提高了代码的复用性
减低了测试难度
代码的复杂度也大大降低
组件的分类
在react中他有两种组件的写法
函数组件--无状态组件
语法:
function 函数名(组件名 但是名字首字母必须必须必须必须 必须 大写){
return (
jsx
)
}
类组件--有状态组件
语法:
class 类名(当前组件名首字母大写) extends React.Component{
render(){ render方法也叫做渲染方法 他的作用就是渲染当前的jsx
return(
jsx
)
}
}
props
正向传值
props能修改吗?
props是只读的 不能修改
语法:
props函数组件
语法 :
只需要在函数组件中添加一个怕props的形参 即可使用props
子组件接收
// 子组件需要把props当成形参传入
let Zi=(props)=>{
let {text,num}=props
return(
<div>
zizizziziziziz---{text}--{num}
</div>
)
}
export default Zi
父组件传递
import Fz from "./funpropszi.jsx"
let Fu=()=>{
let obj={text:"text数据",num:"num数据"}
return(
<div>
fufufufuffufufu
{/* 传递参数可是用扩展运算符 */}
<Fz {...obj}/>
</div>
)
}
export default Fu
props类组件
this.props.xxx
1.子组件设置props
import React, { Component } from 'react'
export default class propszi extends Component {
render() {
return (
<div>
zizizzizizizizzz---{this.props.text}
<br />
{this.props.num}
</div>
)
}
}
2.父组件传递
import React, { Component } from 'react'
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
render() {
return (
<div>
fuffufufufufuffu
{/* 父组件传值 */}
<Pz text="我是父组件的text" num="我是父组件的num"/>
</div>
)
}
}
上面的写法太low了 改变一下
子组件接收数据的时候 使用解构赋值的方式取出this。props的数据
import React, { Component } from 'react'
export default class propszi extends Component {
render() {
// 由于this.props是一个对象 为了让代码看起来更加简洁 所以我们
// 使用解构赋值的方式 把props中的数据快速取出来
let {text,num}=this.props
return (
<div>
zizizizizizizziiz---{text}---{num}
</div>
)
}
}
父组件传递
import React, { Component } from 'react'
import Pz from "./propszi.jsx"
export default class propsfu extends Component {
render() {
let obj={text:"我是父组件的text",num:"我是父组件的num"}
return (
<div>
fuffufufufufuffu
{/* 父组件传值 使用扩展运算符可以简化我们在父组件给
子组件传递数据时候的复杂度
*/}
<Pz {...obj} />
</div>
)
}
}
props 验证
rccp
注意:
自 React v15.5 起,React.PropTypes
已移入另一个包中。请使用 [prop-types
库](prop-types - npm) 代替。
// import React, { Component } from 'react'
// export default class propszi extends Component {
// render() {
// // 由于this.props是一个对象 为了让代码看起来更加简洁 所以我们
// // 使用解构赋值的方式 把props中的数据快速取出来
// let {text,num}=this.props
// return (
// <div>
// zizizizizizizziiz---{text}---{num}
// </div>
// )
// }
// }
import React, { Component } from 'react'
// 包要引
import PropTypes from 'prop-types'
export default class propszi extends Component {
// 使用PropTypes来进行props的验证
static propTypes = {
text: PropTypes.string,
num:PropTypes.number
}
render() {
let {text,num}=this.props
return (
<div>
zizizizizizizziiz---{text}---{num}
</div>
)
}
}
状态机state
状态==数据
状态机===数据机制
数据等同于状态 状态改变页面也会改变
函数组件可以使用状态码?
函数组件默认情况下不能使用状态 后面会学到高阶语法 HOOK才能使用
语法
状态创建
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
render() {
return (
<div>
<h1>状态的使用</h1>
</div>
)
}
}
读取状态
在想使用的地方使用 this.state.xxx
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
render() {
return (
<div>
<h1>状态的使用</h1>
{/* 使用状态 */}
<em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
</div>
)
}
}
修改state
修改state不能直接使用=修改 而是要调用一个叫 setState()来进行修改
import React, { Component } from 'react'
export default class statedemo extends Component {
// 创建状态 需要写在constructor中
// 在es6中 子类写不写constructor 在实例的过程中 都会给补上他
// 但是如果我们写了 那么必须写super()
// super就是调用父类构造方法 只有写了子类才有自己的this
// 如果只写了constructor不写super()那么以后使用this的时候指向都是错误的
constructor(){
super()
// 创建状态
this.state={
text:"字符串",
num:18,
arr:[111,2222,33333],
obj:{name:"xxixi"}
}
}
// 创建函数
fun=()=>{
// 修改state数据必须使用setState()
this.setState({
num:888,
text:"我变了"
})
}
render() {
return (
<div>
<h1>状态的使用</h1>
{/* 使用状态 */}
<em>{this.state.num}-----{this.state.text}---{this.state.arr[1]}</em>
<button onClick={this.fun}>点我修改</button>
</div>
)
}
}
为什么要使用setState()来修改state
因为调用了setState之后 他会自动触发render方法重新渲染页面 从而让数据改变之后 页面页也会发生改变
setState 在修改数据的时候是异步的
由于setState是一个异步的 所以他第一个参数是一个对象 用来修改数据 第二个参数是一个回调函数 是当修改完数据之后自动触发回调函数
this.setState({
num:888,
text:"我变了"
},()=>{
// 我就是想等数据修改之后在console中打印出来
console.log(this.state.num);
})
ref
用来标识组件内部的元素 但是注意 函数组件由于没有实例所以不能使用ref
使用
1.字符串方式(已经淘汰了)
2.回调函数方式
import React, { Component } from 'react'
export default class refdemo extends Component {
fun=()=>{
console.log(this.refinput.value);
}
render() {
return (
<div>
<h1>ref回调函数的方式</h1>
{/* 回调函数方式绑定ref 需要在dom节点上挂载一个函数
函数的形参是当前dom节点 (形参)=>{随便创建一个变量=形参}*/}
<input type="text" ref={(demoinput)=>{this.refinput=demoinput}}/>
<button onClick={this.fun}>点我得到值</button>
</div>
)
}
}
3.React.createRef() react16.3新增
import React, { Component } from 'react'
export default class refdemob extends Component {
constructor(){
super()
// 1.创建createRef
this.refdemo=React.createRef()
}
fun=()=>{
// 3.使用
console.log(this.refdemo.current.value);
}
render() {
return (
<div>
<h1>createRef()</h1>
{/* 2.绑定 */}
<input type="text" ref={this.refdemo}/>
<button onClick={this.fun}>点我得到值</button>
</div>
)
}
}
事件处理机制
事件的绑定
使用小驼峰命名法来进行事件的绑定 onclick---->onClick
如果事件要调用函数 那么函数是不加()
函数实参传递
由于react中的函数是没有()的 所以传统的实参传参方式是没有办法进行的
.bind方式进行实参的传递
onClick={this.fun.bind(this,你要传递的数据)}
事件箭头函数调用函数传参
{/* 通过箭头函数调用函数传参 */} <button onClick={()=>{this.funb("参数")}}>点我传参2</button>
事件的修饰
react中如果想阻止事件传播或者默认行为的话 使用同原生一样的方式
this指向修改
1.就是创建函数的时候使用箭头函数创建
2.通过.bind方式解决this
<button onClick={this.funb.bind(this)}>bind修改this</button>
3.把函数的调用变成使用箭头函数调用
<button onClick={()=>{this.funb()}}>箭头函数调用函数</button>
4.在constructor中提前绑定
constructor(){
super()
this.state={
text:"你好"
}
// 提前给函数绑定this
this.funb=this.funb.bind(this)
}
条件渲染
根据我们的需要 显示或者隐藏某写内容
1.三元运算符
import React, { Component } from 'react'
export default class democ extends Component {
constructor(){
super()
this.state={
bool:true
}
}
render() {
return (
<div>
<h1>条件渲染</h1>
{this.state.bool?<h1>吃了</h1>:<h1>没有吃</h1>}
</div>
)
}
}
2.if全家桶
注意注意注意:在jsx不能写if
import React, { Component } from 'react'
export default class demod extends Component {
constructor(){
super()
this.state={
num:5
}
}
render() {
let com=""
if(this.state.num==1){
com= <h1>第1</h1>
}else if(this.state.num==2){
com= <h1>第2</h1>
}else if(this.state.num==3){
com= <h1>第3</h1>
}else if(this.state.num==4){
com= <h1>第4</h1>
}else if(this.state.num==5){
com= <h1>第5</h1>
}
return (
<div>
<h1>条件渲染</h1>
{com}
</div>
)
}
}
状态提升
react中转台提升就是多个组件需要反映相同的数据变化 我们可以把这个数据提升到这几个组件的父组件之上 然后在父组件中改变数据 那么通过props分发给这几个子组件即可反映相同的数据变化