全家桶
1.React介绍
React起源与发展
React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决
定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源
了。
为什么要学习React
传统的JavaScript或者之前学习的jquery 操纵DOM 非常的繁琐(编码麻烦),并且效率低下(因为只要我们操纵DOM 那么浏览器就会频繁的对页面进行绘制与排列 )
document.getElementById("xxxx");
document.getElementsByClassName("xxx");
document.getElementsByTagName("xxxx");
$(".xxx")
$("#xxx")
...
...
传统的JavaScript操纵DOM 浏览器会进行大量的重绘重排
传统的JavaScript没有组件化编码方案,代码复用性非常低
React是什么?
官方: React是一个用于构建用户界面的javascript库
react是一个将数据渲染为HTML的开源javascript库
React的特性
1.采用组件化模式 声明式编码 提高开发效率以及组件化复用性
2.在ReactNative中可以使用React语法进行移动端开发
3.使用虚拟DOM+diff算法尽量减少与真实DOM的交互
虚拟Dom--VirtualDom与diff算法
传统的dom操纵会在数据改变的时候 重新把页面的所有内容都绘制一遍 (哪怕是10000条数据 之多了一条 那么他也会重新渲染10001次)
虚拟dom--快减少更新次数 减少更新区域 提高性能
虚拟dom相当于在js和真实dom中间加了一个缓存。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都首先重新构建整个DOM树(减少页面更新次数),然后React将当前整个DOM树和上一次的DOM树进行对比(DOM Diff算法-计算出虚拟DOM中真正变化的部分),得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。
React与传统MVC的关系
轻量级的视图层库!
React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可MVC开
发模式;React 构建页面 UI 的库。可以简单地理解为,React 将界面分成了各个独立的小块,每一个块
就是组件,这些组件之间可以组合、嵌套,就成了我们的页面。
2.HelloWord16.8版本
16.8是react的一个分水岭 其中有很多新增特性 在企业中使用中使用
跟多高版本的特性在后面会慢慢学到
1.获取依赖包
(1)react.js文件是创建React元素和组件的核心文件
(2)react-dom.js文件用来把React组件渲染为DOM,此文件依赖于react.js文件,需在其后被引入。
(3)Babel的主要用途是将ES6转成ES5 同时可以把JSX 语法转换新标准的JavaScript代码让现今浏览器兼容的代码
2.编写代码
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 1.引用react核心库文件 -->
<scriptsrc="react.16.8.6.js"></script>
<!-- 2.引用react支持dom操作的react-dom -->
<scriptsrc="react-dom.16.8.6.js"></script>
<!-- 3.引用babel -->
<scriptsrc="babel.min.js"></script>
</head>
<body>
<!-- 4.创建一个容器 用来容纳后续渲染内容 -->
<divid="demoDiv"></div>
<scripttype="text/babel">/* 5.此处不要错了 让babel解析其中的内容*/
// 6.创建虚拟dom
let VDom= <h1>你好么么哒!!!</h1>
// 7.把创建的虚拟dom渲染到页面上
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
思考
虽然react 官方推荐我们使用jsx的方式来创建虚拟dom 但是有同学就会好奇 为什么官方要推荐使用jsx来创建虚拟dom
3.VirtualDom的两种创建方式
我们要完成如下图的页面dom
方式1 使用jsx来创建虚拟DOM
其实jsx的方式创建虚拟dom我们刚才在写helloword的时候已经使用过了 我们只需要稍加改造就行了
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
//使用()代表是个整体 直接添加id 与 内容
let VDom=(
<h1 id="xixi">
<span>你坏</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
方式2 使用原生js来创建虚拟DOM
原生js中使用 document.createElement()来新建dom节点
在我们引用React之后 可以使用React.createElement(标签名,标签属性,标签内容)来创建虚拟dom
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<!-- 由于使用原生 那么就不需要babel了 -->
<!-- <script src="babel.min.js"></script> -->
</head>
<body>
<divid="demoDiv"></div>
<!-- 由于使用原生那么就不用babel -->
<scripttype="text/javascript">
// let VDom=React.createElement(标签名,{标签属性},标签内容)
letVDom=React.createElement("h1",{id:"xixi"},React.createElement("span",{},"你好"))
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
总结
jsx出现的原因 就是因为 传统方式创建虚拟DOM太麻烦了 所以才需要JSX来创建虚拟DOM简化创建虚拟DOM的复杂度(也可以理解为jsx就是传统dom操作的语法糖--语法糖也叫糖衣语法就是用简单的语法完成之前复杂的事情)
4.虚拟DOM与真实DOM区别
我们查看下虚拟dom与真实dom到底是什么?
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let VDom=(
<h1 id="xixi">
<span>你坏</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
console.log("虚拟dom",VDom);
console.log("真实dom",document.getElementById("demoDiv"));
</script>
</body>
</html>
大家会发现浏览器中显示 虚拟dom就是一个我们常见的普通对象
但是虚拟dom和真实dom里面是什么呢?
我们使用debugger看一下
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let VDom=(
<h1 id="xixi">
<span>你坏</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
let ZDom=document.getElementById("demoDiv")
console.log("虚拟dom",VDom);
console.log("真实dom",ZDom);
// 设置断点
debugger
</script>
</body>
</html>
在浏览器中查看会发现
虚拟dom
真实dom
对比后会发现
虚拟dom会比较轻 而真实dom 比较重 因为虚拟dom只需要在react内部在使用需要使用那么多属性
总结
1.虚拟dom就是一个我们常见的普通对象
2.虚拟dom会比较轻 而真实dom 比较重 因为虚拟dom只需要在react内部在使用需要使用那么多属性
3.虚拟dom最终会被react转换成真实dom 展现在页面上
5.jsx语法规则
jsx=javascript xml (xml是一种早起存储数据的格式 是一种要求语法非常严谨的数据格式--现在都使用json)
jsx对语法的要求非常的严格 严格到变态
一个根标签
多行标签需要有一个容器进行包裹
语法严谨
标签必须闭合 必须按照w3c规范来编写
Jsx变量 属性插值 与 注释
定义虚拟dom的时候不加双引号 同时jsx遇见{} 会当js表达式解析 遇见<>当html解析
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let text="xixi";
let demotext="你好"
let VDom=(
<h1 id={text}>
{/*插入变量*/}
<span>{demotext}</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
总结:
插入变量: 因为在jsx中遇见{}就会把里面的东西当成js表达式 解析 所以如果我们想插入变量 就把这个变量放到{我是变量}
插入属性: 因为在jsx中遇见{}就会把里面的东西当成js表达式 解析 所以我们如果想给属性插入变量 就把这个变量直接放到 属性={变量}
插入注释:因为在jsx中遇见{}就会把里面的东西当成js表达式 解析 所以我们注释 {/* 我是注释 */}
样式
行内样式
行内样式需要写入一个样式对象
注意语法 第一个{}是jsx的语法 第二个{}是对象的语法
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let text="xixi";
let demotext="你好"
let VDom=(
<h1id={text}>
<spanstyle={ {color:"red",backgroundColor:"yellow"}}>{demotext}</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
类样式
jsx中类名不能使用class来设置(因为class是js的关键字)使用className来设置
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
<style>
.demo{
color:red;
background-color: yellow;
}
</style>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let text="xixi";
let demotext="你好"
let VDom=(
<h1 id={text}>
<span className="demo">{demotext}</span>
</h1>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
数据遍历
在日常工作中我们进场需要把数据进行遍历展示到页面中 那么在jsx中怎么遍历呢?
特殊情况(工作不会遇见)
如果数据是一个数组 那么react会自动把这个数据中的内容遍历出来并且展示
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let arr=["EZ","VN","MF","NOC"]
let arrb=[<li>EZ</li>,<li>VN</li>,<li>MF</li>,<li>NOC</li>]
let VDom=(
<div>
<ul>
{/*
大家会发现ract会把我们的数据进行遍历
但是这样也有问题就是 ul中不会自动生产标签
*/}
{arr}
</ul>
<ul>
{/*
虽然这样可以遍历出来数据 但是工作中 没有那个后端会给我们返回arrb这 样的数据 所以这种方式行不通
*/}
{arrb}
</ul>
</div>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
那么怎么办呢?
遍历数据
首先我们在遍历数据的时候可以使用 数组的map方法 因为map方法可以遍历数据并且返回出新的内容
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
let arr=["EZ","VN","MF","NOC"]
let VDom=(
<div>
<ul>
{
arr.map((v,i)=>{
return (
<likey={i}>{v}</li>
)
})
}
</ul>
</div>
)
ReactDOM.render(VDom,document.getElementById("demoDiv"))
</script>
</body>
</html>
注意
在jsx中 一对大括号中 放的是js表达式
表达式:通过计算可以返回结果的公式 所以上面的map就是一个表达式 因为map可以返回一个新的结果
但是注意 jsx大括号中不能放置 if switch for 这些js语句 因为他们只是控制程序的执行顺序 不能返回新的结果 所以他们不是表达式
但是注意 jsx大括号中不能放置 if switch for 这些js语句 因为他们只是控制程序的执行顺序 不能返回新的结果 所以他们不是表达式
但是注意 jsx大括号中不能放置 if switch for 这些js语句 因为他们只是控制程序的执行顺序 不能返回新的结果 所以他们不是表达式
6 面向组件编程
组件与组件化 模块与模块化
模块与模块化
模块:用来封装可以重复使用的js代码块
模块化:整个项目都是使用模块的方式来完成的
组件与组件化
组件: 用来封装重复使用的ui代码块
组件化:整个项目都是使用组件的方式来完成的
组件的概念
组件就是把ui部分拆分成一个个独立的并且可以重复使用的部件 在吧这些部件拼装在一起 形成一个页面
组件的设计目的是提高代码复用率,降低测试难度和代码的复杂程度。
1 .提高代码复用率:组件将数据和逻辑进行封装。2 .降低测试难度:组件高内聚低耦合(各个元素高集成度低关联性),很容易对单个组件进行测试。3 .代码的复杂程度:直观的语法,可以极大提高可读性。
React Dev Tools
注意:React Dev Tools是谷歌浏览器的插件 所以别的浏览器不行
在开发原生js的时候,我们经常使用浏览器自带的开发者工具,它足以帮助我们查看和调试js中变量的各种信息。
对于react框架来说,因为它是采用动态渲染生成的代码结构,因此,我们需要一种可以分析react代码结构和变量状态的工具,而react dev tools 就是这样的工具
安装
安装方式1
如果你有科学上网工具 直接可以在谷歌浏览器商店中搜索下载
安装方式2
打开谷歌浏览器--》右上角三个点--》更多工具--》扩展程序--》最最最最关键的一步就是在右上角有个开发者模式的选项打开--》选择左侧上方加载已经解压的扩展程序--》找到对应提供的文件路径即可
设置快捷使用
如果想设置快捷使用
第一步
第二步
默认是灰色的 只要你访问的页面是由react写的 那么他就会显示正常
组件分类
函数组件/无状态组件/工厂组件
函数式组件的基本意义就是,组件实际上是一个函数 这个函数返回一段jsx
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
// 首字母大写
// 首字母大写
// 首字母大写
// 首字母大写
function Fun(){
return (
<div>
<h1>我是一个函数组件</h1>
</div>
)
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
调试
使用刚才安装的调试工具查看
类组件
类组件,顾名思义,也就是通过使用ES6类的编写形式去编写组件,该类必须集成React.Component 其中有一个render的渲染方法 里面有段jsx
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="demoDiv"></div>
<script type="text/babel">
class Fun extends React.Component{
render(){
return (
<div>
<h1>我是一个类组件</h1>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
区别
函数组件的创建形式使代码的可读性更好,并且减少了大量冗余的代码,大大的增强了编写一个组件的便利
函数组件不会被实例化,整体渲染性能得到提升,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。
函数组件由于没有实例化过程,所以无法访问组件this中的对象,若想访问this就不能使用这种形式来创建组件
函数组件无法访问生命周期的方法
思考
既然上面说了 函数组件没有this 而类组件中有this 那么类组件中的这个this里面有什么?
7 属性1-state 组件状态(数据/变量)
state状态机
大家发现上图中有state这个属性
state属性:
state 是组件对象最重要的属性,值是对象(可以包含多个 key-value 的组合)
组件被称为“状态机”(状态机制),通过更新组件的 state 来更新对应的页面显示(重新渲染组件)
1.初始化state 读取
默认情况下 state中是null 我们需要在类组件中初始化 所以我们可以放到 comstructor中进行初始化操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="demoDiv"></div>
<script type="text/babel">
class Fun extends React.Component{
// 初始化
constructor(props){
super(props)
// 1.设置state
this.state={
bool:true
}
}
render(){
return (
<div>
{/*2.使用state状态*/}
<h1>我是一个类组件--{this.state.bool?"你好":"你坏"}</h1>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
2.修改state
更新状态需要调用 this.setState() 方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="demoDiv"></div>
<script type="text/babel">
class Fun extends React.Component{
constructor(props){
super(props)
this.state={
bool:true
}
}
fun=()=>{
// 修改需要使用setState
this.setState({
bool:!this.state.bool
})
}
render(){
return (
<div>
<h1 onClick={this.fun}>我是一个类组件--{this.state.bool?"你好":"你坏"}</h1>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
setState调用后发生了什么
setState是异步的
(如果有大量数据修改的话不会因为修改数据而造成程序的卡顿)
importReact, { Component } from'react'
exportdefaultclassdemobextendsComponent {
// 初始化state状态数据需要放到constructor中进行初始化
// es6中继承的规则中得知 子类是可以不写constructor 他会在实例化的时候
// 自动补充一个
// 但是如果你写了 那么必须在其中写super() 因为super就是调用父类的构造方法
// 此时子类才有this
constructor() {
super()
// 初始化state
this.state={
text:"我是字符串",
num:888,
bool:true,
arr:[1111,2222,333],
obj:{
name:"xixi"
}
}
}
fun=()=>{
// 修改state的数据
// this.setState({
// num:123,
// text:"xixi"
// })
// 下面的console.log打印的结果是修改之后的 还是修改之前的?
// 是修改之前的结果 所以从而证明了setState是一个异步任务
// console.log(this.state.num)
// 但是我就是想setState修改完数据之后 打印新的结果怎么办?
// 因为setState是异步 异步都会有回调函数
this.setState({
num:123,
text:"xixi"
},()=>{
// setState第二个参数是一个回调函数 当数据修改完他才会调用
console.log(this.state.num)
})
}
render() {
return (
<>
{/* 2.使用state数据 */}
<h1>我是测试state使用的例子----{this.state.num}---{this.state.text}</h1>
<buttononClick={this.fun}>点我修改</button>
</>
)
}
}
调用了setState之后会自动触发render渲染
render就是渲染方法 只有render方法执行了 那么页面才会根据数据的改变而随之发生改变
render就是渲染方法 只有render方法执行了 那么页面才会根据数据的改变而随之发生改变
render就是渲染方法 只有render方法执行了 那么页面才会根据数据的改变而随之发生改变
render就是渲染方法 只有render方法执行了 那么页面才会根据数据的改变而随之发生改变
state的简写写法
因为类中可以直接编写赋值语句所以我们的state也可以直接创建 简化了写法
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
class Fun extends React.Component{
// 创建state
state={
bool:true
}
fun=()=>{
// 修改需要使用setState
this.setState({
bool:!this.state.bool
})
}
render(){
return (
<div>
<h1onClick={this.fun}>我是一个类组件--{this.state.bool?"你好":"你坏"}</h1>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
hook-useState
useState
useState 是reactHOOK给我们提供的 最基本最常用的一个HOOK 主要作用就是用来管理当前本地的状态
useState() 返回值是一个数组(长度为2)数组的第一项标识的是当前的值 数组的第二项标识的时候修改这个值的函数
let [xiaoming , setXiaoming]=useState(初始值)
创建与读取
import {useState} from "react"
let Funcom=()=>{
// 使用useState()c创建函数组件的状态
let [xiaoming,setxiaoming]=useState("你好么么哒!!!")
return (
<div>
{/* 读取 */}
<h1>我是一个函数组件--{xiaoming}</h1>
</div>
)
}
export default Funcom
修改
import {useState} from "react"
let Funcom=()=>{
// 使用useState()创建函数组件的状态
let [xiaoming,setxiaoming]=useState("你好么么哒!!!")
return (
<div>
{/* 读取 */}
<h1>我是一个函数组件--{xiaoming}</h1>
{/* 修改数据 */}
<button onClick={()=>{setxiaoming(xiaoming="你好呵呵哒")}}>点我修改</button>
</div>
)
}
export default Funcom
创建多个状态呢
1.你写多个useState
import {useState} from"react"
letFuncom=()=>{
// 1.你写多个useState了解
let [xiaoming,setxiaoming]=useState("1")
let [xiaohong,setxiaohong]=useState("2")
return (
<div>
{xiaoming}---{xiaohong}
</div>
)
}
exportdefaultFuncom
2.一次行创建多个值
import {useState} from"react"
letFuncom=()=>{
// 1.你写多个useState了解
// let [xiaoming,setxiaoming]=useState("1")
// let [xiaohong,setxiaohong]=useState("2")
// 2.一次性创建多个值
let [xiaoming,setxiaoming]=useState({
dataa:"第一个值1",
datab:"第一个值2",
datac:"第一个值3",
datad:"第一个值4",
datae:"第一个值5",
dataf:"第一个值6"
})
return (
<div>
{/* {xiaoming}---{xiaohong} */}
{xiaoming.dataa}----{xiaoming.datad}
</div>
)
}
exportdefaultFuncom
一次性创建多个值怎么修改
1.多个useState 要修改的话就依次调用其中的修改方法
2.一次行创建多个值的方式如何修改呢
import {useState} from "react"
let Funcom=()=>{
// 1.你写多个useState了解
// let [xiaoming,setxiaoming]=useState("1")
// let [xiaohong,setxiaohong]=useState("2")
// 2.一次性创建多个值
let [xiaoming,setxiaoming]=useState({
dataa:"第一个值1",
datab:"第一个值2",
datac:"第一个值3",
datad:"第一个值4",
datae:"第一个值5",
dataf:"第一个值6"
})
let fun=()=>{
// 一次性创建多个的修改操作 不要忘了保留原始数据
setxiaoming({...xiaoming,datad:"我被改了"})
}
return (
<div>
{/* {xiaoming}---{xiaohong} */}
{xiaoming.dataa}----{xiaoming.datad}
<button onClick={fun}>点我修改</button>
</div>
)
}
export default Funcom
总结state
state就是react中用来创建状态的 状态就是数据
在我们使用state的时候有两种情况 分别是函数组件和类组件
类组件 中使用state来进行状态的创建 在修改的时候必须调用setState来进行修改 因为setState是异步的 并且会自动触发render重新渲染 从而让状态数据改变之后 页面也跟着改变
函数组件:他有另外一个名字叫无状态组件 也就是说默认情况不能使用state状态 如果要使用 我们可以使用react16.8新增的一个特性叫HOOK中的useState来进行状态的创建 useState接收一个参数 并且返回数组长度为2的一个内容 第一个是保存的变量 第二个是修改的动作
8 事件
在react中事件的绑定 使用小驼峰命名法
例:onclick 在react中 onClick onchange 在react中 onChange
绑定完事件之后在调用函数的时候不加()不加() 因为加了函数就自动调用了
绑定完事件之后在调用函数的时候不加()不加() 因为加了函数就自动调用了
绑定完事件之后在调用函数的时候不加()不加() 因为加了函数就自动调用了
绑定完事件之后在调用函数的时候不加()不加() 因为加了函数就自动调用了
基本事件操纵
事件绑定 使用小驼峰命名法 鼠标左键点击事件 onclick------》onClick onchange------》onChange
修改this指向
想想函数中的this指向
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="demoDiv"></div>
<script type="text/babel">
class Fun extends React.Component{
fun(){
console.log(this)//undefined
}
render(){
return (
<div>
<button onClick={this.fun}>点我</button>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
this是 undefined 所以我们在使用setState等属性方法的时候就会报错
怎么解决呢?
方式1 bind()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>
<body>
<div id="demoDiv"></div>
<script type="text/babel">
class Fun extends React.Component{
fun(){
console.log(this)
}
render(){
return (
<div>
{/*bind方式修改this*/}
<button onClick={this.fun.bind(this)}>点我</button>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
方式2 通过创建箭头函数
在创建函数的时候创建一个箭头函数
方式3 在constructor中提前对事件进行绑定
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
class Fun extends React.Component{
constructor(props){
super(props)
// 提前绑定this
this.fun=this.fun.bind(this)
}
fun(){
console.log(this)
}
render(){
return (
<div>
<buttononClick={this.fun}>点我</button>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
方式4 将事件调用的写法改为箭头函数的形式
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metahttp-equiv="X-UA-Compatible"content="IE=edge">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Document</title>
<scriptsrc="react.16.8.6.js"></script>
<scriptsrc="react-dom.16.8.6.js"></script>
<scriptsrc="babel.min.js"></script>
</head>
<body>
<divid="demoDiv"></div>
<scripttype="text/babel">
class Fun extends React.Component{
fun(){
console.log(this)
}
render(){
return (
<div>
{/*使用箭头函数调用*/}
<buttononClick={()=>{this.fun()}}>点我</button>
</div>
)
}
}
ReactDOM.render(<Fun/>,document.getElementById("demoDiv"))
</script>
</body>
</html>
函数参数传递
因为在react中函数调用的时候不加() 那我我们如果要传递函数的实参怎么传递?
方式1
使用bind方式进行传递
<button onClick={this.fun.bind(this,"我是实参1","我是实参2")}>点我传递函数实参</button>
方式2
使用箭头函数调用函数进行传递
<button onClick={()=>{this.funb(1111,2222)}}>点我传递实参2</button>
事件对象event
使用event
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="react.16.8.6.js"></script>
<script src="react-dom.16.8.6.js"></script>
<script src="babel.min.js"></script>
</head>