前端的工作:实现整一个前端页面以及交互逻辑,以及利用ajax与node交互
后端的工作:提供API接口,利用redis来管理session,与数据库交互
前端结构
├── build // 构建相关
├── bin // 执行脚本
├── public // 公共文件
│ ├── favicon.ico // favicon图标
│ └── index.html // html模板
│ └── robots.txt // 反爬虫
├── src // 源代码
│ ├── api // 所有请求
│ ├── assets // 主题 字体等静态资源
│ ├── components // 全局公用组件
│ ├── directive // 全局指令
│ ├── layout // 布局
│ ├── plugins // 通用方法
│ ├── router // 路由
│ ├── store // 全局 store管理
│ ├── utils // 全局公用方法
│ ├── views // view
│ ├── App.vue // 入口页面
│ ├── main.js // 入口 加载组件 初始化等
│ ├── permission.js // 权限管理
│ └── settings.js // 系统配置
├── .editorconfig // 编码格式
├── .env.development // 开发环境配置
├── .env.production // 生产环境配置
├── .env.staging // 测试环境配置
├── .eslintignore // 忽略语法检查
├── .eslintrc.js // eslint 配置项
├── .gitignore // git 忽略项
├── babel.config.js // babel.config.js
├── package.json // package.json
└── vue.config.js // vue.config.js
main.js是程序的入口,在这里,定义了vue实例对象,其中引用的包都是全局的,在全局方法和组件挂载完之前,页面显示的是public/index.html中的元素(加载中),挂载完后public/index.html中会显示App.vue中的元素。
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
App.vue中<router-view />表示路由的切换显示
<template>
<div id="app">
<router-view />
<theme-picker />
</div>
</template>
来到router/index.js中,可以看到不同的子路径对应的模块,当路径path:' '时,加载的是Layout组件。redirect重定向到index路径。
{
path: '',
component: Layout,
redirect: 'index',
children: [
{
path: 'index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
},
layout是布局组件,整体布局是通过这个组件完成的。
比如Sidebar为左侧的菜单目录,菜单目录又有主菜单和子菜单、Logo和Link,通过与后端的交互来获取这些信息并展示在页面上。
在Sidebar/index.vue中,导入了以下方法和组件,有Logo和侧边菜单,子菜单和链接都先被导入到了侧边菜单中。
import { mapGetters, mapState } from "vuex";
import Logo from "./Logo";
import SidebarItem from "./SidebarItem";
import variables from "@/assets/styles/variables.scss";
项目启动后,进入的是登录页,在views/login.vue中看到有注册链接,但是登录页没有展示。
<div style="float: right;" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link>
</div>
改成true就显示出来了。
// 验证码开关
captchaEnabled: true,
// 注册开关
register: true,
获取验证码的方法调用
getCode() {
getCodeImg().then(res => {
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled;
if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img;
this.loginForm.uuid = res.uuid;
}
});
},
如果验证码开关为true则发送请求,获得验证码图片和一个uuid。
import { getCodeImg } from "@/api/login";
到api里找到登录的方法。
export function login(username, password, code, uuid) {
const data = {
username,
password,
code,
uuid
}
return request({
url: '/login',
headers: {
isToken: false
},
method: 'post',
data: data
})
uuid与token是对应关系,在redis里会发现。
登录方法里引入了这个拦截器,requset是对axios的封装,所有请求与响应都要先过拦截器再说。
import request from '@/utils/request'
配置了统一的前缀/dev-api,若超过10秒,则视为超时
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000,
});