React 学习

React 基础

react.development.js 核心js
react-dom.development.js dom渲染js文件 有先后顺序

使用...展开语法: 
	let arr = [1,2,3,4];
	console.log(...arr) // 1,2,3,4
内联样式写法:
	<input type="text" name="username" style={{fontSize:'12px'}}>
类式组件:
	class MyComponent extens React.Component{
		1. render() 方法核心
		render(){
			return(
				// render 只能返回单节点(一个div包裹)
			)
		}
	}
初始化对象状态state
	1. 可以在实例对象创建时:
		constructor() {this.state = {a:1}}
	2. 也可以直接在类中定义: 
		class Persion {
			state = {a: 1} 
		}
	3. 如果需要修改state中的值, 使用 this.setState({a:2})

react对标签属性的限制
	需要引入prop-types.js
	类外面的写法 
	1.react 组件类型限制:
		类.propTypes={
			name: PropTypes.string.isRequire,   限制name为必填string类型
			age: PropTypes.number				限制age为数字类型
			say: PropTypes.func					限制say为函数类型
		}
	2.react 指定默认属性
		类.defaultProps = {
			sex: '男',  设置默认sex为男
			age: 17
		}
	3.类里面的写法 static, 对象静态属性
		static propTypes={
			name: PropTypes.string.isRequire,   限制name为必填string类型
			age: PropTypes.number				限制age为数字类型
			say: PropTypes.func					限制say为函数类型
		}

函数式组件: 
	1. 所有的参数都会在props中
	2. 函数式组件中 没有state	, 没有refs
	function MyComponent(props){
		return (
			<h1>test</h1>
		)
	}
总结: 组件传参数 可以使用...语法 , 解构赋值 const {a,b} = this.props // 
	解构赋值连续写法:
		const {target: {value}} = this.event // value 就是target.value 写法
	render() : 方法会被调用1+n次, 初始化渲染和组件更新才会调用
组件生命周期 (旧版 16):
	1.卸载组件:
		ReactDOM.unmountComponentAtNode(document.getElementById('root'))
	2. 组件挂载完毕
		componentDidMount(){ }
	3. 组件将要卸载执行
		componentWillUnmount(){}
	4. 组件将要挂载
		componentWillMount(){}
	5. 执行setState 会调用这个钩子决策,返回true通过,false 更新取消,默认一直为真
		shouldComponentUpdate(){} 
	6. 组件将要更新
		componentWillUpdate(){}
	7. 组件更新完毕 (可以接收3个参数, 第三个就是快照值)
		componentDidUpdate(){}
	8. 强制更新状态, 当执行this.forceUpdate()   只会执行componentWillUpdate() 钩子

	9. 当父组件更新时,子组件才会执行(第一次渲染不会执行哦)
		componentWillReceiveProps(props){}
组件生命周期 (新版):
	1.这个3个钩子如果使用,前面需要加上 UNSAFE_ 前缀, 在未来异步渲染中可能会出bug	
		componentWillMount
		componentWillReceiverProps
		componentWillUpdate
	2. 新增加两个钩子:
		无用: getDerivedStateFormProps(){} // new props setState forceUpdate 执行
		getSnapshotBeforeUpdate(){} // 该方法返回快照值,交给 componentDidUpdate 钩子

	总结: 
	常用的 也就是 constructor 实例化  render渲染 
	componentDidMount挂载完毕  componentWillUnmount

事件处理: 
	js中: onclick
	react: onClick={this.method}, onBlur={},onChange={}
	react 调用method方法会传递事件源(event)=> event.target.value 即可获取当前input值
表单提交:
	表单提交事件 - 受控组件(通过ref获取元素值): 
			this.refs.username.value
			this.refs.password.value
		handleSubmit = event=>{
			event.preventDefault() // 阻止默认表单提交
			// 不适用表单提交发送请求
		}
		<form onSubmit={this.handleSubmit}>
			<input ref={e=>this.username=e} type="text" name="username">
			<input ref={e=>this.password=e} type="text" name="password">
			<button>提交</button>
		</form>
	非受控组件 - 通过onChange 动态获取用户输入,存入state:
		changeUsername = e => {
			this.setState({username: e.target.value})
		}
		<input  name="username" onchange={this.chanageUsername}>
函数柯里化:
	1.在使用非受控组件时,会存在一个问题,就是我有很多个input,会出现很多个对应的方法
	2.函数柯里化解决这个问题:
		state = {
			username: ''
		}
		saveFormDate = name => {
			return e => {
				// key : value 方式存入state
				this.setState({[name]: e.target.value})
			}
		}
		<input type="text" onChange={this.saveFormDate('username')}> // 调用函数并传递一个name标识
	3.不用科里化实现:
		state = {
			username: ''
		}
		saveFormDate = (name,e) => {
			this.setState({[name]: e.target.value})
		}
		<input type="text" onChange={(e)=>{this.saveFormDate('username',e)}}> // onChange react 会帮你调用

refs获取元素(2,3 都可以 没有什么影响):
	1.字符串方式(将要废弃):
		声明: 类似vue: <input ref="input1">	
		使用: this.refs.input1.value 就可以获取input的值
	2.回调方式-内联方式 (render 更新会渲染两次):
		render(){
			return (<div>ref={(e)=>{this.input1=e}}</div>)
			简写方式
			return (<div>ref={e=>this.input1=e}</div>)
		}
	3.优化回调方式,调用类方法:
		// 在类中定义方法
		saveInput=(e)=>{
			this.input1 = e;
		}
		render(){
			return (<div>ref={this.saveInput}</div>)
			简写方式
			return (<div>ref={e=>this.input1=e}</div>)
		}
	4.createRef 最新方式:	
		创建: myRef = React.createRef() // 只能存放一个元素
		使用: <input ref={myRef}>
		获取input值: this.myRef.current.value 

子组件如何给父组件传值:
	1. 函数回调的方式
	class A extends React.Component{
		callback_date = childDate => {
			console.log(childDate)
		}

		render(){
			return (
				// 当header 中调用callback_parent 会调用父组件方法
				<Header callback_parent={this.callback_date}/>
			)
		}
	}
数组方法:
	forEach() 循环,遍历
	const arr2 = arr.map((v,i,arr)=>{v}) 遍历
	filter() 过滤使用
	reduce() 统计使用
react 配置代理:
	setupProxy.js 新建
	const proxy = require('http-proxy-middleware') 使用这个模块
react 脚手架使用:
网络请求:
	axios  
父子组件通信:
	pubsubjs.js  
	1. 谁用数据谁就订阅消息(先订阅在发布)
路由组件和一般组件有什么不同:
	1. 写法不同:
		<About />
		<Route path="/about" component={About}></Route>
	2. 存位置不同:
		pages/   components/
	3. 接收参数不同:
	路由组件接收到的props:
		history:
			go
			goBack
			goForward
			push
			replace
		location:
			pathname: "/about"
			search: ''
			state: 
		match:
			parms: {}
			path: '/about'
			url: '/about'
react 如何使用路由:
	1. 引入 react-router-dom.js 
	2. 引入组件库  import {Link, BrowserRouter,Route} from 'router-router-dom'
		路由类型:  全局唯一必须把Link 和 Route包起来 应该放在最外侧
			<BrowserRouter> 
				<App/>
			</BrowserRouter>
	路由分类: BrowserRouter: 非锚点路由 /a/ba/c, HashRouter锚点路由  /home#/aaa #号后面不会发送到服务端
		Route 注册路由(坐映射关联)
		Link 路由链接实现组件切换, 必须在外侧包裹哪一种路由类型:
		<BrowserRouter> 
			<Link to="/about">点击我去about组件</Link>
			<Link to="/home">点击我去home组件</Link>
	3.注册路由(link 对应的) exact={true} 精准匹配(默认是模糊匹配路由,不能随便开启,开启会导致2级路由失效)
			<Route path="/about" exact={true} component={About}></Route>
			<Route path="/home" component={Home}></Route>
		</BrowserRouter>
	4. 提高路由匹配效率:
		<Switch/> 效率比较高, 匹配到路由会直接返回,不会继续匹配
	5. 如何实现路由点击高亮效果:
		使用Link升级版: 
			<NavLink to="/about" activeClassName={xxx}>点击我去about组件</NavLink> 
			***标签体内容是一个特殊的属性. this.props.children 可以获取标签体内容
			4.1 点击默认追加action class, 也可以使用actionClassName 指定样式
	6. 默认选中:
		<Redirect to='/about'/>  
		1. 一般写在最下方,没有匹配到路由的情况下跳转到redirect指定的路由
	 
路由组件传值几种方式:
	1.第一种params: 直接在路由后面拼接: 
		<Link to="/about/1">点击我去about组件</Link>
		声明接收一个变量id (可以拼接多个/:id/:title),About组件props中查看 , this.props.match.params
		<Route path="/about/:id" component={About}></Route>
	2. 第二种search: 
		<Link to="/about/?id=1&title=aaa">点击我去about组件</Link>
		无需声明接收,直接在About 中props接收, this.props.location.search  // ?id=1&title=aaa 需要自己处理
		***可以借助querystring 库处理
		<Route path="/about" component={About}></Route>
	3. ***state 方式, 不是组件的state,不能按照之前的方式,, 地址栏不会显示参数
		<Link to={{pathname:'/about', state:{id:1,title:'xxx'}}}>点击我去about组件</Link>
		无需声明接收,直接在About 中props接收, this.props.location.state  // 无需处理,比较爽
编程式导航(只有路由组件才有history):
	通过点击事件函数跳转,this.porps.history.push/this.porps.history.replace
		this.porps.history.push('/about')
		this.porps.history.replace('/about')  跳转不留痕迹
		this.porps.history.goBack()
		this.porps.history.goForward()
使用withRouter ,让一般组件有路由组件的API,解决一般组件使用history问题
	import {withRouter} from 'react-router-dom'
	class Header extends Component{}
	export default withRouter(Header)

		

  

posted @ 2021-05-27 21:30  qukaige  阅读(51)  评论(0编辑  收藏  举报