实战react技术栈+express前后端博客项目(4)-- 博客首页代码的
项目地址:https://github.com/Nealyang/R...
本博客为连载代码博客同步更新博客,随着项目往后开发可能会遇到前面写的不合适的地方会再回头修改。如有不妥~欢迎兄弟们不啬赐教。谢谢! 首页效果图(目前是假数据)
首页部分代码编写class Home extends Component { constructor(props) { super(props); this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this) } render() { const {login,register} = this.props; localStorage.setItem('userInfo',JSON.stringify(this.props.userInfo)); return ( this.props.match.params.tag && (tags.indexOf(this.props.match.params.tag) === -1 || this.props.location.pathname.lastIndexOf('/') > 0) ? <Redirect to='/404'/> : <div className={style.container}> <div className={style.contentContainer}> <div className={`${style.newsContainer} ${anStyle.animated} ${anStyle.fadeInUp}`}> <ArticleList/> <div className={style.paginationContainer}> <Pagination defaultCurrent={6} total={500}/> </div> </div> <div className={`${style.loginContainer} ${anStyle.animated} ${anStyle.fadeInRight}`}> {this.props.userInfo.userId?<Logined history={this.props.history} userInfo={this.props.userInfo}/>:<Login login={login} register={register}/>} </div> </div> </div> ) } } 因为将来我们会以标签来作为路由,展示不同标签页下的文章列表,所以当没有匹配到url没有匹配到对应标签的时候,我们显示404页面。 首页部分主要包括以下几项。轮播图(这里仅仅用作UI美观吧),标签,文章列表,分页,登录功能。 所以对于复杂编码的部分,我们单独抽出组件。而对于Home.js这个文件,也是点击所有标签对应的公共页面。只是文章列表不同而已。 登录注册form组件别的组件都是常规编码,这里说下form组件吧 class LoginFormCom extends Component { constructor(props) { super(props); } handleLogin = (e) => { e.preventDefault(); this.props.form.validateFields((err,values) => { if (!err) { this.props.login(values.userName,values.password) } }); }; render() { const {getFieldDecorator} = this.props.form; return ( <Form onSubmit={this.handleLogin} className={style.formStyle}> <FormItem> {getFieldDecorator('userName',{ rules: [{required: true,message: '请输入用户名!'}],})( <Input prefix={<Icon type="user" style={{fontSize: 13}}/>} placeholder="Username"/> )} </FormItem> <FormItem> {getFieldDecorator('password',message: '请输入密码!'}],})( <Input prefix={<Icon type="lock" style={{fontSize: 13}}/>} type="password" placeholder="Password"/> )} </FormItem> <FormItem> <Button className={style.loginButton} type="primary" htmlType="submit"> 登录 </Button> </FormItem> </Form> ) } } const LoginForm = Form.create()(LoginFormCom); export default LoginForm 这里我是将登录和注册单独拿出来写了两个组件的。具体写法可以参考antd官方文档。 saga部分这部分说的saga仅仅是一些全局信息的saga,包含错误信息提醒、全局的Loading、登录状态等。并非首页文章列表标签的saga reducerconst initialState = { isFetching: true,msg: { type: 1,//0失败 1成功 content: '' },userInfo: {} }; export const actionsTypes = { FETCH_START: "FETCH_START",FETCH_END: "FETCH_END",USER_LOGIN: "USER_LOGIN",USER_REGISTER: "USER_REGISTER",RESPONSE_USER_INFO: "RESPONSE_USER_INFO",SET_MESSAGE: "SET_MESSAGE",USER_AUTH:"USER_AUTH" }; export const actions = { get_login: function (username,password) { return { type: actionsTypes.USER_LOGIN,username,password } },get_register: function (data) { return { type: actionsTypes.USER_REGISTER,data } },clear_msg: function () { return { type: actionsTypes.SET_MESSAGE,msgType: 1,msgContent: '' } },user_auth:function () { return{ type:actionsTypes.USER_AUTH } } }; export function reducer(state = initialState,action) { switch (action.type) { case actionsTypes.FETCH_START: return { ...state,isFetching: true }; case actionsTypes.FETCH_END: return { ...state,isFetching: false }; case actionsTypes.SET_MESSAGE: return { ...state,isFetching: false,msg: { type: action.msgType,content: action.msgContent } }; case actionsTypes.RESPONSE_USER_INFO: return { ...state,userInfo: action.data }; default: return state } } // const front = combineReducers({ // // home // }); export default combineReducers({ // front,globalState: reducer,admin }) 说下几个状态。 FETCH_START: "开始进行异步请求",FETCH_END: "异步请求结束",USER_LOGIN: "用户登录",USER_REGISTER: "用户注册",RESPONSE_USER_INFO: "收到登录信息",SET_MESSAGE: "设置全局提醒",USER_AUTH:"USER_AUTH"//后面免登陆再说这个 对应中saga的处理 export function* login(username,password) { yield put({type: IndexActionTypes.FETCH_START}); try { return yield call(post,'/user/login',{username,password}) } catch (error) { yield put({type:IndexActionTypes.SET_MESSAGE,msgContent:'用户名或密码错误',msgType:0}); } finally { yield put({type: IndexActionTypes.FETCH_END}); } } export function* register (data) { yield put({type:IndexActionTypes.FETCH_START}); try { return yield call(post,'/user/register',data) } catch (error) { yield put({type:IndexActionTypes.SET_MESSAGE,msgContent:'注册失败',msgType:0}); } finally { yield put({type: IndexActionTypes.FETCH_END}); } } export function* loginFlow() { while (true) { let request = yield take(IndexActionTypes.USER_LOGIN); let response = yield call(login,request.username,request.password); if(response&&response.code === 0){ yield put({type:IndexActionTypes.SET_MESSAGE,msgContent:'登录成功!',msgType:1}); yield put({type:IndexActionTypes.RESPONSE_USER_INFO,data:response.data}) } } } export function* registerFlow () { while(true){ let request = yield take(IndexActionTypes.USER_REGISTER); let response = yield call(register,request.data); if(response&&response.code === 0){ yield put({type:IndexActionTypes.SET_MESSAGE,msgContent:'注册成功!',data:response.data}) } } } export function* user_auth () { while(true){ yield take(IndexActionTypes.USER_AUTH); try { yield put({type:IndexActionTypes.FETCH_START}); let response = yield call(get,'/user/userInfo'); if(response && response.code === 0){ yield put({type:IndexActionTypes.RESPONSE_USER_INFO,data:response.data}) } }catch (err){ console.log(err); }finally { yield put({type: IndexActionTypes.FETCH_END}); } } } saga中主要是对用户登录和注册的处理。每一个saga处理函数中都需要put一个请求开始和请求结束的action,如果请求错误,则需要设置全局状态提醒。 user_auth是后面免登陆的一个saga处理,后续介绍,这里大家可以略过。 总结如上,在登录的时候,我们dispatch一个login的action,saga则会捕捉该action,然后对应处理后,put相应的action给reducer。 具体的操作,大家可以自行github上查看代码 该部分主要是前端操作,所以代码部分都是在 /app 文件夹下。 项目实现步骤系列博客
交流倘若有哪里说的不是很明白,或者有什么需要与我交流,欢迎各位提issue。或者加群联系我~ 扫码关注我的个人微信公众号,直接回复,必有回应。分享更多原创文章。点击交流学习加我微信、qq群。一起学习,一起进步
欢迎兄弟们加入: Node.js技术交流群:209530601 React技术栈:398240621 前端技术杂谈:604953717 (新建) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |