【招聘App】—— React/Nodejs/MongoDB全栈项目:个人中心&退出登录
前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅。最终成果github地址:https://github.com/66Web/react-antd-zhaoping,欢迎star。
一、个人中心信息展示
- 用户在登录后,authrouter.js中已经获取到所有的用户信息,并保存在redux;所以个人中心只需获取redux中的user数据即可
- component目录下:创建user个人中心组件目录
import React from 'react' import {Result, List, WhiteSpace, Button } from 'antd-mobile' import {connect} from 'react-redux' @connect( state => state.user ) class User extends React.Component{ render(){ const props = this.props const Item = List.Item const Brief = Item.Brief // console.log(this.props) return props.user ? ( <div> <Result img={<img src={require(`../img/${props.avatar}.png`)} style={{width: 50}} alt=""/>} title={props.user} message={props.type=='boss' ? props.company :null} /> <List renderHeader={()=>'简介'}> <Item multipleLine > {props.title} {this.props.desc.split('\n').map(v=><Brief key={v}>{v}</Brief>)} {props.money ? <Brief>薪资:{props.money}</Brief> : null} </Item> </List> <WhiteSpace /> <List> <Item>退出登录</Item> </List> </div> ) : null } } export default User
二、退出登录
清除cookie登录状态
- 安装第三方插件browser-cookies
npm install browser-cookies --save
-
为【退出登录】的onClick事件监听this.logout方法
<List> <Item onClick={this.logout}>退出登录</Item> </List>
坑:antd-mobile的TabBar的div层会覆盖整个页面,导致这里的onClick事件失效,需要设置其z-index为-1
-
使用Model弹框显示确认或取消‘退出登录’:通过browser-cookies的erase()清除cookie
import browserCookie from 'browser-cookies' logout = () => { const alert = Modal.alert alert('注销', '确认退出登录吗???', [ { text: '取消', onPress: () => console.log('cancel') }, { text: '确认', onPress: () => { browserCookie.erase('userid') //清除cookie }} ]) }
清空redux数据
- 清除cookie后需要自动刷新页面:清空redux数据,让页面自动跳转到登录页
- user.redux.js中:添加logout相关的reducer和action,将initState传入重置redux,并修改redirectTo为'/login'
//actioin type const LOGOUT = 'LOGOUT' //reducer中添加 case LOGOUT: return {...initState, redirectTo:'/login'} //action export function logoutSubmit(){ return {type:LOGOUT} }
-
user.js中:通过connect将redux中logoutSubmit方法传入组件
-
在清空cookie的同时清空redux数据,修改props中的redirectTo
-
判断props若没有user时,即用户没有登录或退出登录时,执行跳转
import {logoutSubmit} from '../../redux/user.redux' @connect( state=>state.user, {logoutSubmit} ) //alert确认后 this.props.logoutSubmit() //清空redux,并跳转到login页 //判断没有props.user时 <Redirect to={props.redirectTo} />
-
坑:
-
原因:当前已经跳转到login页面,但还想跳转到/login路由时,会报上述错误
-
解决:login.js中修改跳转页面的判断条件,存在redirectTo且redirectTo不等于‘/login’时跳转
{this.props.redirectTo&&this.props.redirectTo!=='/login' ? ……
三、函数式编程
- 高阶函数 :一个函数可以接受另一个函数作为参数,这样的函数称为高阶函数
function hello(){ console.log('hello everyOne I love react') } //高阶函数 function WrapperHello(fn){ return function(){ console.log('before say hello') fn() console.log('after say hello') } } hello = WrapperHello(hello) hello()
四、高阶组件
高阶组件:一个高阶组件是一个函数,它输入一个组件,然后返回一个新的组件
- 组件会把属性转化成UI,而高阶组件会把一个组件转化成另外一个组件
- 高阶组件最大的特点:重用组件逻辑
- 它并不是由React API定义出来的功能,而是由React的组合特性衍生出来的一种设计模式
- react-redux中的connect就是一个高阶组件
- 高阶组件的使用:
-
不要对原组件进行修改:对它们进行组合
-
惯例用法 : 将没有关系的属性 props 传递给所包装的组件
-
惯例用法 : 组合最大化
-
惯例用法 : 封装显示名称,便于调试
- 使用警告:
-
不要在 render 方法内使用高阶组件
-
静态方法必须要复制
-
Ref 没有被传递
简单的高阶组件Demo
- 普通方式
//组件就是一个函数 class Hello extends React.Component{ render(){ return <h2>hello everyOne I love React</h2> } } //高阶组件基本功能:属性代理 function WrapperHello(Comp){ class WrapComp extends React.Component{ render(){ return ( <div> <p>这是HOC高阶组件特有的元素</p> <Comp {...this.props}></Comp> </div> ) } } return WrapComp } Hello = WrapperHello(Hello)
-
装饰器方式:使用@包裹一层
//高阶组件 function WrapperHello(Comp){ class WrapComp extends React.Component{ render(){ return ( <div> <p>这是HOC高阶组件特有的元素</p> <Comp {...this.props}></Comp> </div> ) } } return WrapComp } //装饰器方式:使用@包裹一层 @wrapperHello class Hello extends React.Component{ render(){ return <h2>hello everyOne I love React</h2> } }
使用高阶组件优化项目代码
- component目录下:创建imooc-form表单高阶组件目录,抽离出login和register表单复用的handlechange函数
import React from 'react' export default function imoocForm(Comp){ return class WrapperComp extends React.Component{ constructor(props){ super(props) this.state = {} this.handleChange = this.handleChange.bind(this) } handleChange(key, val){ this.setState({ [key]: val }) } render(){ return <Comp handleChange={this.handleChange} state={this.state} {...this.props}></Comp> } } }
-
register.js中:使用@imoocForm包裹组件【login.js中同理】
-
在componentDidMount()中设置默认选择type为genius
-
此时组件中没有state和handleChange了,所有需要调用的时候都从this.props中获取
-
注意:@imoocForm必须在@connect后,connect也是高阶组件,参数为imoocForm返回的函数
import imoocFrom from '../../component/imooc-form/imooc-form' @connect( state => state.user, {register} ) @imoocFrom class Register extends React.Component{ componentDidMount(){ this.props.handleChange('type', 'genius') } handleRegister = () => { this.props.register(this.props.state) } //其它表单代码需要state和handleChange处都从this.props中获取
注:项目来自慕课网