1、谷粒后台开发准备及登录页面
开发准备
代码仓库:https://github.com/changeclass/react-admin/commits/
技术选型
前端路由
创建项目
基于脚手架创建项目
create-react-app react-admin_client编辑基本结构
入口文件
/** * 入口文件 */ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render( <App />, document.getElementById('root') );根组件
/** * 应用根组件 */ import React, { Component } from "react"; export default class App extends Component { render () { return <div>ahha </div> } }其他目录结构
引入AntD
安装插件
yarn add antd # 实现组件按需打包的依赖 yarn add react-app-rewired customize-cra babel-plugin-import配置按需打包,在根目录创建
config-overrides.js文件。const {override, fixBabelImports} = require('customize-cra'); module.exports = override( fixBabelImports('import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css', }), );修改
package.json文件"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" },自定义主题
安装
yarn add less less-loader修改
config-overrides.js文件const { override, fixBabelImports, addLessLoader } = require('customize-cra'); module.exports = override( fixBabelImports('import', { libraryName: 'antd', libraryDirectory: 'es', style: true, }), addLessLoader({ lessOptions: { javascriptEnabled: true, modifyVars: { '@primary-color': '#2daebf' } } }) );引入路由
安装插件
yarn add react-router-dom入口文件
import { BrowserRouter, Route, Switch } from 'react-router-dom' import Admin from './pages/admin/admin'; import Login from './pages/login/login'; export default class App extends Component { render () { return ( <BrowserRouter> <Switch> <Route path='/login' component={Login}></Route> <Route path='/' component={Admin}></Route> </Switch> </BrowserRouter> ) } }子组件
/** * 管理的路由组件 */ import React, { Component } from 'react' export default class Admin extends Component { render() { return <div>Admin</div> } }
登录页面-布局
代码仓库:https://github.com/changeclass/react-admin/commits/dev
HTML结构
export default class Login extends Component { render () { return ( <div className='login'> <header className='login-header'> <img src={logo} /> <h1>React项目:谷粒商城</h1> </header> <section className='login-content'> <h2>用户登录</h2> <div>Form组件标签</div> </section> </div> ) } }login的样式
// login组件样式 .login { width: 100%; height: 100%; background-image: url('./images/bg.jpg'); background-size: 100% 100%; .login-header { display: flex; align-items: center; height: 80px; background-color: rgba(21, 20, 13, 0.5); img { width: 40px; height: 40px; margin: 0 15px 0 50px; } h1 { font-size: 30px; color: white; } } .login-content { width: 400px; height: 300px; background-color: #fff; margin: 50px auto; padding: 20px 40px; h2 { text-align: center; font-size: 30px; font-weight: bolder; } } }全局样式
html, body, p, ol, ul, li, dl, dt, dd, blockquote, figure, fieldset, legend, textarea, pre, iframe, hr, h1, h2, h3, h4, h5, h6 { margin: 0; padding: 0; } h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; } ul { list-style: none; } button, input, select, textarea { margin: 0; } html { box-sizing: border-box; } *, *::before, *::after { box-sizing: inherit; } img, video { height: auto; max-width: 100%; } iframe { border: 0; } table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } td:not([align]), th:not([align]) { text-align: left; } html, body { height: 100%; width: 100%; } #root { height: 100%; width: 100%; }
登录页面-Form表单
import { Form, Input, Button, Checkbox } from 'antd'
import { UserOutlined, LockOutlined } from '@ant-design/icons'
<Form
name='normal_login'
className='login-form'
onSubmit={this.handleSubmit}
>
<Form.Item>
<Input
prefix={
<UserOutlined
className='site-form-item-icon'
style={{ color: 'rgba(0,0,0,.25)' }}
/>
}
placeholder='Username'
/>
</Form.Item>
<Form.Item>
<Input
prefix={
<LockOutlined
className='site-form-item-icon'
style={{ color: 'rgba(0,0,0,.25)' }}
/>
}
type='password'
placeholder='Password'
/>
</Form.Item>
<Form.Item>
<Button
type='primary'
htmlType='submit'
className='login-form-button'
>
登录
</Button>
</Form.Item>
</Form>登录页面-表单收集
视频中使用了AntD3的获取方式,然而AntD4与3版本获取表单实例略有差异。
获取表单实例
为
Form组件添加属性ref,在类通过React.createRef创建表单引用。export default class Login extends Component { // 创建表单实例 formRef = React.createRef() // 表单提交事件 handleSubmit = () => { console.log(this.formRef) } render() { return ( <div className='login'> <header className='login-header'> <img src={logo} /> <h1>React项目:谷粒商城</h1> </header> <section className='login-content'> <h2>用户登录</h2> <Form name='normal_login' className='login-form' // 为表单添加引用 ref={this.formRef} // 为表单添加校检完成的事件 onFinish={this.handleSubmit} > </Form> </section> </div> ) } }
完整代码
import React, { Component } from 'react'
import { Form, Input, Button } from 'antd'
import { UserOutlined, LockOutlined } from '@ant-design/icons'
import './login.less'
import logo from './images/logo.png'
/**
* 登录的路由组件
*/
export default class Login extends Component {
// 创建表单实例
formRef = React.createRef()
// 表单提交事件
handleSubmit = () => {
console.log(this.formRef)
}
render() {
return (
<div className='login'>
<header className='login-header'>
<img src={logo} />
<h1>React项目:谷粒商城</h1>
</header>
<section className='login-content'>
<h2>用户登录</h2>
<Form
name='normal_login'
className='login-form'
// 为表单添加引用
ref={this.formRef}
// 为表单添加校检完成的事件
onFinish={this.handleSubmit}
>
<Form.Item>
<Input
prefix={
<UserOutlined
className='site-form-item-icon'
style={{ color: 'rgba(0,0,0,.25)' }}
/>
}
placeholder='Username'
/>
</Form.Item>
<Form.Item>
<Input
prefix={
<LockOutlined
className='site-form-item-icon'
style={{ color: 'rgba(0,0,0,.25)' }}
/>
}
type='password'
placeholder='Password'
/>
</Form.Item>
<Form.Item>
<Button
type='primary'
htmlType='submit'
className='login-form-button'
>
登录
</Button>
</Form.Item>
</Form>
</section>
</div>
)
}
}登录页面-Form的验证方式
声明式验证
<Form.Item name='username' // 声明式验证 rules={[ { required: true, whitespace: true, message: '请输入用户名' }, { min: 4, message: '用户名最少4位' }, { max: 12, message: '用户名最多12位' }, { pattern: /^[a-zA-Z0-9_]+$/, message: '用户名必须是大写字母、小写字母或下划线组成' } ]} > </Form.Item>自定义验证
<Form.Item name='password' rules={[{ validator: this.validatePwd }]} ></Form.Item>// 自定义验证-密码 // AntD4中已经没有callback回调函数了,而是返回Promise对象 validatePwd = (rule, value) => { // value 表示当前输入框传入的值 console.log(rule, value) if (!value) { return Promise.reject('密码必须输入') } else if (value.length < 5) { return Promise.reject('密码长度不能小于4') } else if (value.length > 12) { return Promise.reject('密码长度不能大于12') } else if (!/^[a-zA-Z0-9_]+$/.test(value)) { return Promise.reject('密码必须是大写字母、小写字母或下划线组成') } else { return Promise.resolve() } }
登录页面-Form的统一验证
新版直接使用 onFinish 事件,该事件仅当校验通过后才会执行。
<Form.Item
name='password'
rules={[{ validator: this.validatePwd }]}
></Form.Item>// 自定义验证-密码
// AntD4中已经没有callback回调函数了,而是返回Promise对象
validatePwd = (rule, value) => {
// value 表示当前输入框传入的值
console.log(rule, value)
if (!value) {
return Promise.reject('密码必须输入')
} else if (value.length < 5) {
return Promise.reject('密码长度不能小于4')
} else if (value.length > 12) {
return Promise.reject('密码长度不能大于12')
} else if (!/^[a-zA-Z0-9_]+$/.test(value)) {
return Promise.reject('密码必须是大写字母、小写字母或下划线组成')
} else {
return Promise.resolve()
}
}发送Ajax请求
安装axios插件
yarn add axios在
api/ajax.js文件中封装ajax请求,并处理错误请求/** * 发送异步请求的模块 * 1. 统一处理请求异常 */ import axios from 'axios' import { message } from 'antd' export default function ajax (url, data = {}, method = 'GET') { return new Promise((resolve, reject) => { let promise // 1. 执行异步请求 if (method === 'GET') { promise = axios.get(url, { params: data }) } else { promise = axios.post(url, data) } promise .then(response => { // 2. 成功调用resolve resolve(response) }) .catch(error => { // 3. 失败不调用reject,而是提示异常信息 message.error("请求出错了:" + error.message); }) }) };封装接口请求函数
为了方便请求接口,将请求的重心放在数据传输上,而将各种接口封装成一个函数,只需要向此函数传递参数即可。
/** * 包含应用中所有接口请求的函数的模块 * 每个函数的返回值都是Promise */ import ajax from './ajax' // 登录 export const reqLogin = (username, password) => ajax('/login', { username, password }, "POST") // 添加用户 export const reqAddUser = (user) => ajax('/manage/user/add', user, "POST")跨域问题
使用脚手架创建的项目只需要在
package.json文件中加入代理字段即可。{ "proxy":"http://127.0.0.1:5000" }数据持久化
登录时
将数据保存到local中,并同时放入内存中。
进入登录页面时
获取内存中是否有登录字段,如果有则重定向管理页面
进入页面
一进入页面将local中的用户数据存储到内存中。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小康博客!
评论
TwikooDisqusjs












