zoukankan      html  css  js  c++  java
  • 从零开始,搭建一个简单的购物平台(三)

    从零开始,搭建一个简单的购物平台(二):https://blog.csdn.net/time_____/article/details/105408640
    项目源码(持续更新):https://gitee.com/DieHunter/myCode/tree/master/shopping

    这篇文章在上次的服务端登录基础上增加前端界面

    在开始前我们可以简单用postman测试一下token和登录的功能,可以先在后端生成一段token从前端请求

    验证token(成功和失败)

    紧接着验证一下用户登录(前提事先在数据库添加用户信息,添加过程及加密不做详细说明)

    测试成功后我们开始配置编写前端部分(只实现功能,对界面要求不高)

    文件结构:

    • 配置config.js文件夹,新建config.js文件用于存放配置常量(和服务端config.js一样)
      export default class Config {
        static Agreement = "http://";
        static BaseUrl = "127.0.0.1";
        static ServerUrl = "";
        static ServerPort = ":1024";
        static Path = "/";
        static CryptoKey = "tokenkey";//加密信息关键字
        static FilePath = this.Agreement + this.BaseUrl + this.ServerPort + this.Path;
        static ServerApi = {//接口名
          token: "checkToken",
          user: {
            userLogin: "user/userLogin",
          }
        };
        static StorageName = {//本地缓存localstorage名称
          token: "token",
          userInfo: "userInfo"
        };
      }
    • 在utils文件中新建方法,将其放在react.component的原型中,使继承组件可以直接调用
      storage:
      import { Component } from "react";
      class Utils {
        static saveStorage(key, val) {//添加缓存
          localStorage.setItem(key, JSON.stringify(val));
        }
        static getStorage(key) {//获取缓存
          try {
            return JSON.parse(localStorage.getItem(key));
          } catch (error) {}
        }
        static clearStorage(key) {//清除缓存
          try {
            localStorage.removeItem(key);
          } catch (error) {}
        }
      }
      Component.prototype.$utils = Utils;
      

      axios:

      import Config from "../config/config";
      import Axios from "axios";
      import { Component } from "react";
      import { message } from "antd";
      Axios.defaults.baseURL =
        Config.Agreement + Config.BaseUrl + Config.ServerPort + Config.Path;
      // 添加请求拦截器
      Axios.interceptors.request.use(
        function (config) {
          // 在发送请求之前做些什么
          return config;
        },
        function (error) {
          // 对请求错误做些什么
          return Promise.reject(error);
        }
      );
      // 添加响应拦截器
      Axios.interceptors.response.use(
        function (response) {
          // 对响应数据做点什么
          if (response.data.result === -999) {
            //token验证失败
            return message.error(response.data.msg);
          }
          return response.data;
        },
        function (error) {
          console.log(error)
          // 对响应错误做点什么
          message.error("操作失败");
          return Promise.reject(error);
        }
      );
      
      Component.prototype.$axios = Axios;
      

      Crypto:

      import * as CryptoJS from "crypto-js";
      import { Component } from "react";
      import config from "../config/config";
      const { CryptoKey } = config;
      class CryptoTool {
        /* Crypto加密方法
         * @param {object} _data       对用户请求后端的参数进行加密
         */
        static setCrypto(_data) {
          let key = CryptoJS.enc.Utf8.parse(CryptoKey);
          let encrypted = CryptoJS.AES.encrypt(JSON.stringify(_data), key, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
          });
          return encrypted.toString();
        }
         /* Crypto解密方法
         * @param {string} _token       将秘文解密成对象形式
         */
        static getCrypto(_token) {
          let key = CryptoJS.enc.Utf8.parse(CryptoKey);
          let decrypt = CryptoJS.AES.decrypt(_token, key, {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
          });
          return JSON.parse(CryptoJS.enc.Utf8.stringify(decrypt).toString());
        }
      }
      Component.prototype.$crypto = CryptoTool;
      
    • 在index.js中添加这些函数
      import React from "react";
      import ReactDOM from "react-dom";
      import App from "./App";
      import "./util/axios";
      import "./util/utils";
      import "./util/cryptoTool";
    •  随后在page/login中新增login.js,简单配置一下login页面后,在App.js中引入login页面
      import React from "react";
      import Login from "./page/login/login"
      
      function App() {
        return (
          <div className="App">
            <Login></Login>
          </div>
        );
      }
      
      export default App;
    • 在antd官网找到登录界面实例,直接把大部分复制到login界面,用less微调一下后实现以下界面
       
    • login.js
      import React from "react";
      import "./login.less";
      import { Card, Form, Input, Button, Checkbox, message } from "antd";
      import { UserOutlined, LockOutlined } from "@ant-design/icons";
      import config from "../../config/config";
      const { ServerApi, StorageName } = config;
      export default class Login extends React.Component {
        constructor(props) {
          super(props);
          this.checkToken(); //验证用户token是否过期
        }
        render() {
          return (
            <div className="cardBox">
              <Card title="登录">
                <Form
                  name="normal_login"
                  className="login-form"
                  initialValues={{ remember: true }}
                  onFinish={this.sendData}
                >
                  <Form.Item
                    name="username"
                    rules={[
                      {
                        required: true,
                        message: "请输入用户名/邮箱",
                      },
                    ]}
                  >
                    <Input
                      className="infoInput"
                      prefix={<UserOutlined className="site-form-item-icon" />}
                      placeholder="用户名/邮箱"
                    />
                  </Form.Item>
                  <Form.Item
                    name="password"
                    rules={[
                      {
                        required: true,
                        message: "请输入密码",
                      },
                    ]}
                  >
                    <Input
                      className="infoInput"
                      prefix={<LockOutlined className="site-form-item-icon" />}
                      type="password"
                      placeholder="密码"
                    />
                  </Form.Item>
                  <Form.Item>
                    <Form.Item name="remember" valuePropName="checked" noStyle>
                      <Checkbox>3天内免密</Checkbox>
                    </Form.Item>
                    <a className="login-form-forgot" href="#aaa">
                      忘记密码
                    </a>
                  </Form.Item>
                  <Form.Item>
                    <Button
                      type="primary"
                      htmlType="submit"
                      className="login-form-button"
                    >
                      登录
                    </Button>
                    或者<a href="#aaa">注册</a>
                  </Form.Item>
                </Form>
              </Card>
            </div>
          );
        }
        checkToken() {
          let token = this.$utils.getStorage(StorageName.token);
          if (!token) return;
          this.$axios
            .get(ServerApi.token, {
              params: { token },
            })
            .then((res) => {
              switch (res.result) {
                case 1:
                  message.success(res.msg).then(() => {
                    // this.props.history.push({
                    //   pathname: "/admin/findshop",
                    //   query: res,
                    // });
                  });
                  break;
                default:
                  // message.warning(res.msg);
                  break;
              }
            })
            .catch((err) => {
              console.log(err);
            });
        }
        sendData = (data) => {
          this.$axios
            .get(ServerApi.user.userLogin, {
              params: { crypto: this.$crypto.setCrypto(data) },
            })
            .then((res) => {
              switch (res.result) {
                case 1:
                  this.$utils.saveStorage(StorageName.token, res.token);
                  message.success(res.msg);
                  // this.props.history.push({
                  //   pathname: "/admin/findshop",
                  //   query: res,
                  // });
                  break;
                default:
                  message.warning(res.msg);
                  break;
              }
            })
            .catch((err) => {
              console.log(err);
            });
        };
      }
      
    • 效果如下:

    用户token验证,登录功能前端+后端基本实现

    总结

    前端与后端的项目搭建顺序可能有所不同,项目周期可能也不同,这时需要灵活使用前后端数据模拟和请求模拟工具,前端可以使用easymock和mockjs生成假数据,而后端最简单的直接放到浏览器url访问(仅限于get),或者使用postman,SoapUI等接口测试工具

  • 相关阅读:
    Linux-read 命令(20)
    47.Linux-DEVICE_ATTR()介绍及使用示例
    46.Linux-创建rc红外遥控平台设备,实现重复功能(2)
    46.Linux-分析rc红外遥控平台驱动框架,修改内核的NEC解码函数BUG(1)
    Xcode定位光标到行首行尾
    Mac 教程:OS X「剪切」移动文件的三种方法
    iOS Xcode最新真机调试包 DeviceSupport
    Flex布局做出自适应页面--语法和案例
    如何使用Android Studio与夜神模拟器开发调试
    Android源代码下载与编译
  • 原文地址:https://www.cnblogs.com/HelloWorld-Yu/p/13514439.html
Copyright © 2011-2022 走看看