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)