1.react是facebook内部的一个javascript类库,用于构建用户界面的 JavaScript 库
2.react官网
https://react.docschina.org/
3.react不是一个弯针的MVC框架,最多可以认为是MVC中的V(View)
4.react引入虚拟DOM机制
5.react引入组件化思想
6.react使用facebook专门为其开发的一套语法糖–jsx
1.react的运行速度快
2.跨浏览器兼容,兼容IE6以上
3.一切皆组件
4.单向数据流
5.语法报错提示非常清晰
react不适合做一个完整的框架使用,react本身只是一个视图而已,
(1)引入react核心库
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>(2)设置一个挂载点
<body> <div id="box"></div> </body>(3)渲染虚拟DOM到挂载点
<script> let box = document.getElementById('box'); console.log(box); // 创建一个虚拟dom // console.log(React); let h1 = React.createElement('h1',{class:'myh1'},'这是一个虚拟dom-h1') //渲染虚拟dom ReactDOM.render(h1,box) </script>Rect中的createElement方法用来创建一个虚拟DOM的函数,支持三个参数
这个函数支持三个参数:
1.要创建的标签名称(只能是系统内置的标签)
2.要创建的标签属性(支持内置属性和自定义属性)
3.标签的内容
ReactDOM中的render方法用来渲染虚拟DOM到真是DOM中
这个函数支持三个参数:
1.要渲染的虚拟DOM元素
2.要渲染的位置
3.回调函数,一般不使用
安装
npm i -g create-react-app此命令仅执行一次,不用每次初始化项目时都来安装
初始化项目
create-react-app react-demo运行项目
npm start浏览器会自动打开,并且运行在3000端口上
项目目录结构
项目名称
node_modules 项目依赖目录
public 项目执行根目录
index.html 项目首页
静态资源
src 项目源码目录
APP.css 项目根组件的样式文件
APP.js 项目根组件
APP.test.js 项目根组件测试文件
index.css 项目全局样式表文件
index.js 项目启动文件
package.json 项目依赖配置文件
运行流程
/public/index.html
/src/index.js
/src/APP.js
如果要在页面结构中创建一个层级比较深的虚拟DOM结构的话,代码如下:
ReactDOM.render( React.createElement('div',null, React.createElement('h1',{id:'myh1'},'这是一个h1标题'), React.createElement('p',null, React.createElement('a',{}, React.createElement('span',{},'') ) ) ), document.getElementById('box') )如果虚拟DOM层级比较深/复杂,使用createElement方法就不合适了,所以要使用jsx。
jsx是js和xml的结合,是Facebook为react框架开发的一套语法糖
语法糖:糖衣语法,计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,而是更加方便程序员使用
jsx是一种js语法的扩展,允许js和html进行混写
(1)基本使用
引入babel核心库
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>(2)修改script的type属性
<script type="text/babel"></script>(3)创建虚拟DOM
let el = <div> <h1 id="qaz">这是一个虚拟DOM-h1</h1> <p>p标签哦</p> </div>(4)渲染虚拟DOM到挂载点
ReactDOM.render(el,document.getElementById('box'))(1)Adjacent JSX elements must be wrapped in an enclosing tag
虚拟DOM中也只能有一个根标签
(2) Invalid DOM property class. Did you mean className
在react的jsx语法中,class是一个类的关键词,所以标签的class关键词要改成className
(3)babel.min.js:7 Uncaught SyntaxError: Inline Babel script: Unterminated JSX contents
在jsx中所有的标签,都要有闭合标签,比如input br img hr 要写成
(4)react-dom.development.js:82 Warning: Invalid DOM property for. Did you mean htmlFor
在react的jsx语法中,for是一个循环的关键词,所以for属性要改成htmlFor
示例代码
<body> <div id="box"></div> <script type="text/babel"> let el = <div> <h1 className="111">标题1</h1> <h2>111</h2> <label htmlFor="name"></label> <input type="text" id="name"/> </div> ReactDOM.render(el,document.getElementById('box')) </script> </body>react的jsx语法中,当<就会解析成html语法
当遇到{开始就会解析成js语法
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jsx解析数据类型</title> <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> </head> <body> <div id="app"></div> <script type="text/babel"> let name = '小飞' let islogin = false//布尔值不要直接进行输出,可以做判断使用 let obj = { name : '中公优就业' }//对象不要直接输出,可以读取对象中的某个key属性 //数组元素如果是非对象类型,可以直接输出,但是对象不能直接输出 let arr = [ { name : '小飞', age:18 }, { name : '小李', age:19 } ] function randomStr(){ return Math.random() } let el = ( <div> { /* 字符串 */ } <p>姓名:{ name }</p> { /* 数字 */ } <p>{ 100 * 90 }</p> {/* 布尔值 */} <p> { islogin ? '已登录' : '未登录' } </p> {/* 对象 */} <p>{ obj.name }</p> {/* 数组 */} <p>{ /*arr*/ }</p> { /* 函数 */ } <p> { randomStr() } </p> </div> ) let app = document.querySelector('#app') ReactDOM.render(el,app) </script> </body> </html>又叫做无状态组件/木偶组件
格式:
import React from 'react' let Home = ()=>{ return ( <div>home</div> ) } export default Home;在APP.js中引入
import Home from './home'在标签中使用组件:
export default () => { return ( <div>脚手架根组件 <Home></Home> </div> ) }注意:
在react中,引入组件时,组件名称首字母必须大写
又叫做状态组件/业务逻辑组件
在react中,更多的使用组件是类组件,因为类组件可以有状态、生命周期和逻辑方法函数
格式一
import React from 'react' export default class 类名 extends React.Component{ render(){ return( <div>...</div> ) } }格式二:
import React,{Component} from 'react' export default class 类名 extends Component{ render(){ return( <div>...</div> ) } }类组件的类名一般都首字母大写,表示类名
状态是一个核心概念,允许构建可以存储数据的react组件,并根据数据变化自动更新视图页面
(1)在构造函数中定义状态
constructor() { super(); this.state = { time: new Date().toLocaleTimeString() } }(2)直接在类中定义状态
state = { time: new Date().toLocaleTimeString() }(1)直接修改状态
利用setState方法,来对状态进行修改(不要使用直接赋值的方式,页面不会变化)
直接对this.state进行赋值,state中的数据会变化,但是页面上的state引用出不会发生变化,因为页面已经渲染了
setState被调用时,react将数据和当前的state进行合并,然后调用render方法更新页面
export default class Clock extends Component { state = { time: new Date().toLocaleTimeString() } start(){ setInterval(()=>{ // setState是react中内置的更改状态的方法,他会自动的重现调用render方法,来重新渲染页面 this.setState({ time:new Date().toLocaleTimeString() }) },1000) } //组件挂载完成 componentDidMount(){ this.start(); } render() { return ( <div> <h1>clock</h1> <p>当前时间:{this.state.time}</p> <p>{this.name}</p> </div> ) } }setSate方法是一个**异步操作,**在没有执行完数据的和并和页面渲染时,是无法直接获取到更新之后的数据的,如果想要获取在调用setState之后获取到最新的数据,可以在回调函数里对数据进行操作
export default class Home extends Component { state = {num:1} changeNum(){ let n = this.state.num; n++; // setState参数 // 第一个参数是要合并到原来状态的数据 // 第二个参数是一个回调函数(可选),用来获取最新的数据 this.setState({num:n,}, ()=>{ console.log('最新',this.state.num);//在数据合并完成后,页面徐然完成后才执行 }) console.log('非最新',this.state.num)//此时获取到的数据不是最新的 } render(){ return ( <div> <h2>{this.state.num}</h2> <button onClick={()=>{this.changeNum()}}>增加数量</button> </div> ) } }不要在jsx语法中给函数添加小括号,否则就会自动执行
无法获取到this指向,如果想要保持this指向,需要bind进行this绑定
ES6方式的事件绑定,可以在指定的函数中保持this指向
<button onClick={this.handler1.bind(this)}>es5-this</button>此时,按钮板顶的事件对应的函数中就可以获取到this指向
es5方式的事件绑定,可以在对应函数中获取到事件对象
handler2(e){ console.log('222'); console.log(e) }ES6中默认在对应的函数中无法获取到事件对象,除非显示的传递事件对象
<button onClick = {(形参)=>{this.handler2(形参)}}>ES6</button>方式1:仅仅传递参数
es5方式的事件绑定中,bind(this)不是参数,要传递的参数放到this的后面
handler3(num){ console.log(num); }方式2:既传递参数又获取事件对象,默认最后一个形参是事件对象,无需在事件触发时进行传递
handler4(num,ev){ console.log(num); console.log(ev); }方式1:仅仅传递参数
<button onClick = {()=>this.handler3(200)}>ES6-仅传参</button>方式2:既传递参数又获取事件对象
<button onClick = {(e)=>this.handler4(200,e)}>ES6-参数和获取事件对象</button>注意:形参和实参位置要对应起来
handler4(num,ev){ console.log(num); console.log(ev); }由于react中没有vue中的指令系统,所以想要实现表单元素双向绑定,就要结合事件绑定和状态机来实现。
需要给指定的表单元素添加value属性来设置初始值,同时需要给表单元素再设置一个onChange事件(不设置的话它就是一个只读属性, 无法进行修改), 在onChange中结合事件绑定和setState方法来实现状态的变化并且页面上的内容也进行更新。
import React, { Component } from 'react' export default class Form extends Component { state = { name: '小王', phone:18 } iptChange(e,t) { // console.log(e.target.value)//获取事件对象,标签中的value属性 // this.setState({ // name: e.target.value // }) let data = this.state; data[e.target.id] = e.target.value;//法1 data[t] = e.target.value;//法2 this.setState(data); } submit() { console.log(this.state) } render() { return ( <div> <div> <label htmlFor="name">用户名</label> <input id="name" type="text" value={this.state.name} onChange={(e) => { this.iptChange(e,'name')}} autoComplete="off"></input> <p>{this.state.name}</p> </div> <div> <label htmlFor="phone">手机号</label> <input id="phone" type="text" value={this.state.phone} onChange={(e) => { this.iptChange(e,'phone') }}></input> <p>{this.state.phone}</p> </div> <br></br> <button onClick={() => { this.submit() }}>增加数量</button> </div> ) } }使用自定义属性和props
react中父子组件通信和vue中的父子组件通信非常相似,都是在父组件使用子组件时,通过自定义属性进行传递数据,然后在子组件中通过props来接收数据
示例代码:
父组件:
import React,{Component} from 'react' import Item from './item' export default class Children extends Component{ arr=[111,222,333] render(){ return ( <div> <h2>home组件</h2> { this.arr.map((d,i)=>{ return( <Item key={i} msg={d} ind={i}></Item> ) }) } </div> ) } }子组件
类组件方式:
import React,{Component} from 'react' export default class Item extends Component{ render(){ return ( <div> <h2>{this.props.msg}</h2> <h2>{this.props.ind}</h2> </div> ) } }函数式组件:
函数式组件默认,没有this,所以不能通过this.props来接收数据,但是他可以通过函数参数的方式来接收父组件传递的数据
import React from 'react' export default (props)=>{ return( <div > <p className="title">{props.obj.title}</p> <p className="zan">{props.obj.age}</p> </div> ) }在react中,子父组件通信用自定义函数来实现
父组件
addZan(num){ this.arr[num].zanNum++; this.setState({})//调用setState,用来重新渲染页面 } <Child key={index} obj={item} ind={index} addParent={(n)=>this.addZan(n)} ></Child>子组件
import React, { Component } from 'react' export default class child extends Component { zan(n){ this.props.addParent(n)//通过props来触发父组件的自典故事件,同时传递参数 } render() { return ( <div className="qaz"> <p className="title">{this.props.obj.title}</p> <p className="zan">点赞数量:{this.props.obj.zanNum} <button onClick={()=>this.zan(this.props.ind)}>点赞</button> </p> </div> ) } }公用容器和 e m i t , emit, emit,on
(1)创建一个公用容器
/src/bus.js
// 创建一个公用容器,实现非父子组件通信 const EventEmitter = require('events') const myEvent = new EventEmitter(); export default myEvent;在src/index.js中把公用容器引入并挂载到Component原型上,写最后
import React,{Component} from 'react'; import bus from './bus'//引入公用容器 Component.prototype.$bus = bus;(2)在A组件中发送数据
sentData(){ this.$bus.emit('事件名','要传递的数据') }(3)在其他组件的构造函数上来通过$on,来接收数据
constructor(){ super() this.$bus.on('事件名',(数据)=>{ }) }只有类组件才有生命周期,函数组件没有生命周期
(1)construcr 构造函数,在所有函数执行之前它先执行
(2)UNSAFE_componentWillMount 组件将要挂载
(3)render 页面渲染
(4)componentDidMount 组件挂载完成【*】
(1)shouldComponentUpdate 组件是否要更新数据,需要返回一个布尔值,为true表示要更新数据,为false时,表示不要更新数据
(2)UNSAFE_componentWillUpdate 组件需要更新数据时,组件会触发将要更新数据的钩子函数
(3)render 页面渲染
(4)componentDidUpdate 组件更新完成
(5)UNSAFE_componentWillReceiveProps 父组件传递的数据变化时,子组件中会自动触发此钩子函数,
但是更多的应用场景是父子组件通信时,父组件数据变化
componentWillUnmount 组件将要被销毁
在标签或组件上的ref属性,除了可以是字符串以外,还可以写成一个回调函数
回调函数会自动触发,并且不会在this.refs中存在
ref+回调函数也可以实现父子组件通信
如果需要子组件在展示前就获取到父组件传递的最新数据,可以考虑说那个回调函数
import React, { Component } from 'react' import Child from './child' export default class Index extends Component { render() { return ( <div> <h1 ref="myh1">index</h1> <Child ref={(e)=>this.changeChild(e)}></Child> </div> ) } changeChild(e){ console.log(e)//此时e就是子组件本身 e.setState({ num:500 }) } }createRef是react给提供的一个API方法,利用此方法也可以实现通过ref来获取DOM元素或者子组件,从而实现DOM操作或者组件传值操作
import React, { Component } from 'react' import Child from './child' export default class Index extends Component { constructor(){ super() this.chileEl = React.createRef()//创建空的ref对象 } render() { return ( <div> <h1 ref="myh1">index</h1> <Child ref={this.chileEl}></Child> </div> ) } componentDidMount(){ console.log(this.chileEl.current)//此时this.chileEl.current就是子组件本身 this.chileEl.current.state.num =222 } }state一般是给组件本身设置的初始数据(组件可以对数据进行任意操作)
props一般是子组件接收父组件传递的数据(子组件无法修改props)
如果想要根据父组件传递的数据来改变子组件本身的状态时,可以使用props和state混用的方式。
如果子组件的数据依赖于父组件传递的数据,当子组件的数据方式变化时,子组件无法获取带父组件最新的数据
父组件
import React, { Component } from 'react' import Item from './item' export default class Home extends Component { state={ num:100 } componentDidMount(){ this.setState({ num:50 }) } render() { return ( <div> <h1>home---{this.state.num}</h1> <Item num={this.state.num}></Item> </div> ) } }子组件
import React, { Component } from 'react' export default class Item extends Component { state={ sum:200 } componentDidMount(){ // 此时子组件获取到的父组件传递的数据是100,而不是父组件更新之后的50 this.setState({ sum:this.state.sum+this.props.num }) } render() { return ( <div> <h1>item</h1> <p>结果是:{this.state.sum}</p> </div> ) } }setState方法的参数,可以是一个对象+一个回调函数,还可以是一个函数
这个函数中的第一个参数是当前页面组件的初始状态,第二个参数是父组件传递过来的最新数据
子组件:
import React, { Component } from 'react' export default class Item extends Component { state={ sum:200 } componentDidMount(){ // 此时子组件获取到的父组件传递的数据是100,而不是父组件更新之后的50 // this.setState({ // sum:this.state.sum+this.props.num // }) this.setState(function(state,props){ console.log(state);//当前组件状态 console.log(props);//父组件中的修改之后的数据 return { sum:state.sum+props.num } }) } render() { return ( <div> <h1>item</h1> <p>结果是:{this.state.sum}</p> </div> ) } }react也是SPA 应用
/src/index.js中,渲染虚拟DOM之前,引入路由模块
import {BrowserRouter} from 'react-router-dom'//注意顺序 ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter> ,document.getElementById('root') );创建几个页面组件
然后在APP.js中引入创建好的页面
引入路由中内置的组件Switch、Router,用来设置路由出口和具体的路由规则
// 引入路由内置组件 import Home from './July/home' import Mine from './July/mine' import Order from './July/order' import {Switch,Route} from 'react-router-dom' export default () => { return ( <div> {/* 相当于vue-touter-view */} <Switch> {/* ROUTE是具体的路由规则,需要设置路由关键词和一直对应的组件 */} <Route path="/home" component={Home}></Route> <Route path="/mine" component={Mine}></Route> <Route path="/order" component={Order}></Route> </Switch> ) }(1)内置组件
相同:这两个内置标签都是在页面上生成超链接a标签,都需要设置to属性来告知跳转的链接地址
不同:link标签仅在页面上生成a标签和href属性,NavLink会在页面上生成a标签的同时会根据当前访问的路由地址来动态的设置激活状态
①Link
<Link to='/index/student'>学生管理</Link> <Link to='/index/course'>课程管理</Link>②NavLink
<NavLink to="/index/student">学生管理</NavLink> <NavLink to='/index/course'>课程管理</NavLink>(2)编程式导航
如果某个组件不是路由规则的页面组件,而是某个路由规则页面组件的组成部分时,想要使用react-router-dom的路由相关信息时,无法直接使用,想要解决这个问题,需要使用withRouter
import React, { Component } from 'react' import {withRouter} from 'react-router-dom' class Header extends Component { render() { return ( <div className="header"> <h1>Header</h1> <button onClick={()=>{this.logout()}}>退出登录</button> </div> ) } } export default withRouter(Header)此时,被路由规则包含的组成部分组件就可以使用react-router-dom相关的信息了
在路由实例的history中有以下方法可以实现页面跳转
push
replace
go(-1)
goback
import React, { Component } from 'react' import {withRouter} from 'react-router-dom' class Header extends Component { logout(){ // this.props.history.push('/login') // this.props.history.replace('/login') // this.props.history.go(-1) this.props.history.goBack() } render() { return ( <div className="header"> <p>Header</p> <button onClick={()=>{this.logout()}}>退出登录</button> </div> ) } } export default withRouter(Header)需要在哪个页面展示不用的子级页面,就自己在这个页面引入Switch、Router的内置路由组件,并定义具体的路由规格
/src/components/view/right.js
import React, { Component } from 'react' import Student from '../pages/student' import Course from '../pages/course' import {Switch,Route} from 'react-router-dom' export default class Right extends Component { render() { return ( <div className="right"> <Switch> <Route path="/index/student" component={Student}></Route> <Route path="/index/course" component={Course}></Route> </Switch> </div> ) } }App.js
在react-router-dom包中引入Redirect组件
import {Switch,Route,Redirect} from 'react-router-dom'在Switch中定义一个重定向的路由
<Switch> <Route path="/index" component={Index}></Route> <Route path="/login" component={Login}></Route> <Redirect path="*" to="/index"></Redirect> </Switch>二级路由重定向,特定的组件
<Redirect path="*" to="/index/course"></Redirect>参数固定
关键词/:参数名
长地址要在短地址前面或者路由规则设置exact
<Route exact path="/index/student" component={Student}></Route>exact属性用来标记路由规则精确匹配
(1)创建页面组件
(2)配置动态路由规则
<Route path="/index/student/:id" component={StudentInfo}></Route>(3)在列表页面进行跳转并拼接参数
<button className="btn btn-primary" onClick={()=>this.props.history.push('/index/student/'+item.id)}>编辑</button>(4)获取动态路由参数地址
<p>学生编号:{this.props.match.params.id}</p>参数数量不固定
(1)定义一个固定的路由规则
<Route path="/index/student/info" component={StudentInfo}></Route>页面跳转
toInfo(obj){ this.props.history.push({ pathname:'/index/student/info', search:`id=${obj.id}&name=${obj.name}` }) }3.获取查询参数
查询参数处理:
插件
npm i querystring --save使用
import querystring from 'querystring' let search = this.props.location.search.substr(1);//获取location中的search参数,并去掉问号 let obj = querystring.parse(search);在react-router-dom中Browser和history模式,HashRouter是hash模式
在src/index.js中
// import {BrowserRouter} from 'react-router-dom' import {HashRouter} from 'react-router-dom' ReactDOM.render( // <React.StrictMode> // <BrowserRouter> <HashRouter> <App /> </HashRouter> // </BrowserRouter>更换为hash模式,就能看见#
单向数据流动,可预测的
view 视图触发action
action 通知dispatcher(派发器)
dispatcher 通知仓库改变状态
store 仓库改变完成后通知视图(view)
(1)创建仓库
在src下创建一个文件夹
定义初始数据
/src/store/index.js
let state = { name:'flux', age:16 }(2)暴露数据
export default {state,dispatcher}(3)普通页面组件使用仓库中的数据
import React, { Component } from 'react' // 引入flux仓库 import store from '../store/index' export default class Home extends Component { render() { return ( <div className="main"> <p>{store.state.name}</p> </div> ) } }此时,多个页面组件都可以引入仓库,并使用仓库中的数据
(4)在页面发起动作,改变仓库中的数据
在仓库中通过派发器来注册改变仓库状态的具体方法
/src/store/index.js
// 引入派发器 import {Dispatcher} from 'flux' // 引入事件监听器 import EventEmitter from 'events' class State extends EventEmitter{ name='flux' age=16 } let state = new State() // 实例化派发器 const dispatcher = new Dispatcher(); // 通过派发器来派发具体的数据修改操作 dispatcher.register(action=>{ switch(action.type){ case 'changeName': state.name = action.params; break; case 'changeAge': state.age = action.params; break; default: break; } state.emit('change')//触发事件 })在普通页面组件中的挂载完成钩子函数中来监听数据的变化
componentDidMount(){ store.state.on('change',()=>{ this.setState({});//重新渲染页面 }) }此时仓库中的数据变化了,页面也会跟着从小渲染
在普通页面中通过仓库派发任务
store.dispatcher.dispatch({ type;'changeName', params:'hello' })Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,一个新的对象就会被创建(使用actions和reducers)。
核心概念:
actions
store
reducers
Redux三个原则
1.单一数据源
2.state是只读的
3.使用纯函数修改state
安装
npm i redux --save(3)基本语法
流程:
引入createStore
定义初始状态
定义纯函数
定义仓库
示例代码:
①引入createStore
/src/store/index.js
// 引入createStore import { createStore } from 'redux'②定义初始状态
const initalState = { name: '1', age: 2 }③定义纯函数
state 上一次修改完成后的状态
action是组件dispatch的动作
reducer一定要返回一个新的state,否则就检测不到state的变化
function reducer(state = initalState, action) { switch (action.type) { case 'changeName': return{ ...state, name:action.params } case 'changeAge': return{ ...state, age:action.params } default: return state;//一定要返回 } }④创建仓库
// 创建仓库 const store = createStore(reducer) export default store;⑤页面组件使用状态
//引入仓库 import store from '../storee/index'使用仓库中的数据
<p>仓库中的name{store.getState().name}</p>⑥改变状态
changeName(){ console.log(store) store.dispatch({ type:'changeName', params:'小芳' }) }⑦使用订阅者实现数据变化,页面就变化
componentDidMount(){ // 仓库数据变化,想要重新渲染页面,就要添加订阅者 this.unsubscribe = store.subscribe(()=>{ this.setState({}) }) } componentWillUnmount(){ this.unsubscribe();//在销毁之前,取消订阅 }主题包
npm install element-theme-default --save官网:https://ant.design/index-cn
(1)安装
npm install antd --save(2)引入
/src/index.js
import 'antd/dist/antd.css'(3)使用
antdimport {Button} from '' <Botton type="text">按钮</Button>jquery、fetch、axios
(1)axios
安装
npm i axios --save引入
import axios from 'axios'使用:
axios.get('目标地址').then(res=>{})配置代理
①package.json
"proxy":"目标域名地址:端口号"重启react项目,就可以进行代理转发
在package.json中添加proxy后,当访问一个react项目不存在的路由地址时,会自动转发到proxy对应的目标域名地址上
弊端:只能配置一个,需要寻找一遍路由地址再转发
②使用插件
http-proxy-middleware
安装
npm i http-proxy-middleware --save在/src下创建一个setupProxy.js文件【文件名不能写错】
const proxy = require('http-proxy-middleware'); module.exports = function(app){ app.use(proxy.createProxyMiddleware( "/关键词",{ target:'目标域名地址', changeOrigin:true, pathRewrite:{ "^/关键词":'' } } )) }重启项目就可以进行代理的转发
1.Warning:The tag is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter
在React中组件名称需要大写
2.Warning: Failed prop type: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.
表单元素设置value属性之后,默认就是只读属性,如果想要让他变成可以修改的控件,需要设置onChange事件,让这个控件变成受控组件