##React框架
react是一个什么框架呢?
1. 组件化:使代码更加模块化,重用代码更重要,让代码更具有复用解耦性
2. Virtual Dom:让性能更好,让我们脱离了直接操作dom节点来操作页面
3. 单项数据流:使数据更安全了
4. mvc :使用数据控制视图
5. 渐进式框架:可以把所有的插件包裹进去
一.安装react框架口令
1. npx create-react-app 项目名
2. cd 项目名
3. npm start
二.项目目录介绍
1. node-moudle 项目依赖 非常大
2. public 入口文件 到时候打包的时候会根据这个文件来反射到我们dist文件中去
3. src:源代码文件
三.jsx语法
介绍:javaScript +xml(html)
解析jsx语法:遇到<>按照html语法解析,遇到{}按照javaScript
四.创建组件和组件传值
1. 我们新创建两个jsx文件
2. 我们需要引入react,创建类继承react组件的类,里面有个render函数(就是渲染的意思),里面需要return(你要写的组件内容)注意:组件里面也是只能有一个根元素的,就是所有的代码需要一个div来包裹下,记得用export default 导出,外部才能引用
3. 我们需要使用组件也就是直接用import 导入就可以使用了
4. 组件之间传值分为父传子和子传父
5. 父传子:父组件需要直接用一个属性的形式传给子组件,子组件需要用一个属性:props来接受下。
6. 子传父:(子组件是不能改变父组件传过来的数据的,保证了单项数据流的概念)子组件传值给父组件,需要让父组件传递一个方法过来,子组件在调用父组件传过来的方法把数据当参数的形式放在父组件传过来的方法里面,父组件那边就可以调用这个方法拿到子组件传过来的数据了
- 如下图:
// 子组件
import React from 'react'
export default class child extends React.Component {
change = () => {
this.props.hand("你好,我是子组件传过来的数")
}
render() {
// 用this.props来接受父组件传递的数据
const { name } = this.props
return (
<div>
<div>{name}</div>
<button onClick={this.change}>传递</button>
</div>
)
}
}
// 父组件
import React from 'react';
import Child from './child'//引用子组件
export default class App extends React.Component{
changFatherData=(data)=>{
// 接受子组件传递的数据。并打印出来
console.log('====================================');
console.log(data);
console.log('====================================');
}
render(){
return (
<div >
{/* //传递数据的方式,如果子组件想传递值给父组件,需要传递一个方法给子组件,让子组件调用传递过来 */}
<Child name="我是组件传过来的数据" hand={this.changFatherData} />
</div>
);
}
}
五.state的使用
1. 组件中的状态,一般我们是操作dom都是直接操作的,现在我们是操作state来操作视图
2. state一般是定义在constructor里面的,外面调用直接用this.state.你在state定义的变量名,就可以拿到了,要想修改需要调用this.setState来修改就可以了
3. this.setState这个方法是一个异步的操作,当我们改变的时候我们直接在后面 直接打印的话是没有修改的,要想拿到改变后的值,需要在this.setState后面有一个回调函数,我们可以在那个里面到这个改变之后的值
- 如图:
import React from 'react';
export default class App extends React.Component{
constructor(props){
super(props);
this.state={
// 一个组件存储数据的地方
data:1
}
}
//创建个方法来改变data
changeData=()=>{
this.setState({
data:2
},()=>{
console.log(this.state.data,"我是在回调函数中拿取data的值")
})
console.log(this.state.data,"我是在外面调用拿取data的值")
}
render(){
return (
<div >
<p>{this.state.data}</p>
{/* 代码里面直接调用this.state.变量名就可以了 */}
<button onClick={this.changeData}>把data的数字1改成2</button>
</div>
);
};
}
六.组件中的生命周期
随着我们对react的理解和使用越来越多,生命周期的参考价值也越来越多了,那react有哪些生命周期呢,分别有哪些作用呢?
1. componentWilllMount:在组件渲染之前调用
2. componentDidMount:在组件渲染之后调用
3. shouldComponetUpdate: 返回false或者true,true是允许改变,false是不允许改变
4. componentWillUpdate:数据在改变前
5. componentDidUpdate :数据在改变后
6. componentWillReveiceProps:props发生改变执行
7. componentUnMount:组件卸载前执行
七.条件渲染
一般条件渲染我们使用是三目运算:
import React from 'react';
export default class App extends React.Component{
constructor(props){
super(props);
this.state={
data:false
}
}
render(){
const {data}=this.state
return (
<div>
{
data?
<div>true的时候</div>:
<div>false的时候</div>
}
<button onClick={()=>this.setState({data:!this.state.data})}>改变条件</button>
</div>
);
};
}
八.列表渲染
介绍:当我们需要循环数据的我们可以使用数组里面的map方法来循环标签的时候,渲染到页面去,主要我们需要添加一个key值(这里牵扯到了虚拟dom的底层的diff运算,他是需要做个表示来查找更改的地方来直接修改更改之后的地方的,就不需要从新都渲染一便了,大大的提高了性能)
如图:
import React from 'react';
export default class App extends React.Component{
constructor(props){
super(props);
this.state={
dataList:[
{
name:"小明",
age:18
},
{
name:"翠花",
age:16
}
]
}
}
render(){
return (
<div>
<ul>
{
this.state.dataList.map((e,i)=>{
return (<li key={i}>
<p>我的名字是{e.name}</p>
<p>年芳{e.age}</p>
</li>)
})
}
</ul>
</div>
);
};
}
九.ref的使用
1. 首先使用react里面的一个方法createRef来创建
2. 在把创建出来的ref绑定在元素上面就可以在页面渲染完成的时候拿到了
3. 在componentDidMount里面调用获取到节点
- 如图:
import React from 'react';
export default class App extends React.Component{
constructor(props){
super(props);
this.refDom=React.createRef()
}
componentDidMount(){
console.log(this.refDom.current.innerHTML)
}
render(){
return (
<div>
{/* <input type="text" ref={this.refDom}/> */}
<p ref={this.refDom}>你好我是ref对象获取的值</p>
</div>
);
};
}
十.propsTypes类型检查
作用:主要是对传入子组件中的数据进行类型验证做判断,分为三种验证类型验证,必填验证,默认值验证
具体使用可以参考官网的链接:[react官网prop-types类型验证](https://react.docschina.org/docs/typechecking-with-proptypes.html)
十一.路由的使用
1. 先安装 cnpm i react-router-dom --save
2. 路由的作用:一般我们react框架主要是单页面应用(SPA)当我们页面切换的时候就需要路由:
3. 路由又分为 HashRouter(就是路由后面带#号的),BowersRouter(histroy.push,这个上线之后会bug,我们需要告诉后台做重定向,不然页面会404)
4. link的使用:跳转路由的按钮
import React, { Component } from 'react'
import {Link} from "react-router-dom"
export default class nav extends Component{
render(){
return(
<ul>
<li>
<Link to="/login">登录组件</Link>
</li>
<li>
<Link to="/home"> home组件</Link>
</li>
</ul>
)
}
}
5. exact的使用:精准匹配
6.strict :更精准的使用
7.switch的使用:主要是当前页面只能有一个路由
8.需要添加一个404页面
9.component:引用那个组件
10.render 也可以指定一个组件,不过是需要通过一个函数的形式来指认
11.NavLink的,是需要Link指定的路由高亮,他有一个active的class来设置样式
12.路由传值:
可以在path后面直接跟一个/:变量名就可以了(注意当我们跳转页面的时候根据我们的匹配规则,会直接跳到404页面去,这肯定不是我们想要的,我们只需要在变量名后面加一个?号就可以了,代表这个参数可传可不传)
13.路由的参数的获取方式:
(1)我们可以直接用props.match.params.变量的名字就可以拿到了
(2)使用new URLSearchParams(props.location.search),在调用get方法里面传你要的key就可以拿到数据了
(3)queryString.parse(props.location.search)就可以获取(我们需要把前面的一个?截取了去)
14.link里面的属性:
(1)pathname:路径
(2)hash:模式
(3)search:参数
(4)state:是一个对象,里面传递的是一个外面看不到的参数,可以随便定义
15.重定向 redirect:主要业务是当我们就是需要是跳登录页面等等。。。
(1)我们还可以通过别的方式来重定向 :可以通过push和replace
16.widthRouter的使用:主要有的组件不是路由,我们是需要路由跳转的时候,拿不到history,这个是我们就需要高级组件widthRouter来拿到
17.prompt:主要是当我们需要离开这个页面的我们需要个提示框来提示客户的时候
(1)when:当什么的时候触发
(2)要提示客户的信息
十二.redux的使用
1. 安装redux : npm install --save-dev redux
2. 首先我们要创建一个仓库 store ,我们需要通过redux里面的createStore来创建,
3.我们需要创建一个reducer(它是一个纯函数的形式,主要是创建一个接受state,action来处理store里面的数据)
4. subscribe:主要是监听store里面的数据
5. getState:获取store里面的数据
6. dispatch:store触发这个方法把参数发给你定义的red ucer里面去来改变store里面的数据
// reducer文件
const data=(state=0,action)=>{
switch(action.type){
case "ICREMENT" :
return state+=1;
case "DCREMENT":
return state-=1;
default:
return state
}
}
export default data
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import{createStore} from 'redux'//引入redux
import data from './reducers/index' //引入reducer
const store=createStore(data) //创建store并且把reducer放在里面
store.subscribe(()=>console.log("state",store.getState()))//监听store里面的数据,并且获取store里面的数
ReactDOM.render(
// 触发dispatch来触发reducer里面的 定义的条件来操作store里面的数据
<App icrement={()=>store.dispatch({type:"ICREMENT"})} dcrement={()=>store.dispatch({type:"DCREMENT"})}
/>
,
document.getElementById('root')
);
十三.react-redux的使用
1. 安装命令:cnpm i --save-dev react-redux
2. Provider :在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了。
3. connect :让store和页面建立连接,后面有两个括号,前面是放连接数据和处理数据的,后面一个是类的名字
4. mapStateToProps:让store里面的数据映射到页面上,做数据连接
5. mapDispatchToProps:就是操作数据修改数据的,通过dispatch定义的action的函数发到reducer里面来修改store里面的数据
6. bindActionCreators:当我们需要引入很多action操作函数的时候可以通过这个来合并,让书写更简单一点
7. combineReducers:当我们需要引入很多reducer操作函数的时候可以通过这个来合并,让书写更简单一点
// action文件
export const add=()=>{
return{
type:"ADD"
}
}
export const icm=()=>{
return{
type:"ICM"
}
}
// reducer里面的current文件
const reducer=(state=0,action)=>{
switch(action.type){
case "ADD":
return state+=1;
case "ICM":
return state-=1
default:
return state
}
}
export default reducer
// index.js 主文件
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {createStore} from 'redux'
// import reducer from './reducers'
import {Provider} from 'react-redux'
import reducers from './reducers'
const store=createStore(reducers)
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
,
document.getElementById('root')
);
// app文件
import React from 'react';
import {connect} from 'react-redux'
import * as actions from "./actions" //引用所有的函数,用个别名代替
import {bindActionCreators} from 'redux'//引入bindActionCreators,当我们需要引入很多action操作函数的时候可以通过这个来合并,让书写更简单一点
class App extends React.Component{
render(){
console.log(this.props)
let {current}=this.props
return (
<div className="App">
<p>{current}</p>
<button onClick={()=>this.props.actions.add()}>加一</button>
<button onClick={()=>this.props.actions.icm()}>减一</button>
</div>
);
}
}
// 创建mapStateToProps
const mapStateToProps=(state)=>{
return {
current:state.current
}
}
// 创建 mapDispatchToProps
const mapDispatchToProps=(dispatch)=>{
return{
actions:bindActionCreators(actions,dispatch)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(App);
十四.redux 中间件使用
- logger:安装口令:cnpm install --save-dev redux-logger
- 直接在创建store后面使用applyMiddleware加载中间的方法来加载中间件了,如果有多个的话可以在后面直接逗号隔开就可以了
- redux-thunk:专门处理异步的中间件:cnpm i --save-dev redux-thunk ,我们处理异步请求的时候就不会报错了
- redux的调试工具:cnpm i --save-dev redux-devtools-extension
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {createStore,applyMiddleware} from 'redux'
// import reducer from './reducers'
import {Provider} from 'react-redux'
import reducers from './reducers'
import logger from 'redux-logger'//导入 logger
import {composeWithDevTools} from 'redux-devtools-extension' //redux的调试工具
const store=createStore(reducers,{},composeWithDevTools(applyMiddleware(logger))) //加载中间件logger
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
,
document.getElementById('root')
);
十五.高阶组件
- fragment:用来嵌套最外层的
- shoucomponentUpdata:生命周期里面有两个参数:nextprops,nextstate,用来判断和之前的数据发没发生改变,来判断是否继续更新数据
- component和pureCompoent的区别:component不会对数据进行比较,pureComponent会对数据做浅比较