1、自己的github建一个项目。
2、本地vue2.0项目初始化。
安装node.js,检查node版(node -v)。
安装webpack(npm install webpack -g),检查webpack版本。(webpage -v)。
安装vue-cli脚手架(npm install vue-cli -g),检查版本。(vue -V)。
接下来用vue-cli构建项目
vue init webpack myProject
3、将项目关联git地址,首次提交代码。
新建一个文件夹名为(vue2.0)
git init 初始化git生成一个.git文件
git remote add origin git地址 将文件关联到git远程仓库
将myProject文件夹中的初始化的文件拖到vue2.0文件夹中。
git add . 添加文件提交到暂存区
git commit -m 'init' 提交文件到本地仓库
git push -u origin master 这里加上-u是因为:远程库是空的,加了-u后,以后即可直接用git push代替git push origin master
4、安装iview等一些项目中需要用到的第三方模块。
iview-ui官网https://www.iviewui.com/
在main.js中全局引入,具体看官网的快速上手。
5、准备开发工作。
直观思路是不是要开发登录 ---》home等页面。登录页面在router.js里面定义路由和页面路径,然后考虑路由跳转的文件,未登录状态下页面要跳转至登录页面,判断是否登录的标识是,localstore里面是否有token,如果没有的话需要将路由更改跳转到login页面。vue router.js中使用router.beforeEach去实现。
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import login from '@/components/login' Vue.use(Router) const router = new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/login', name: 'login', component: login } ] }) const isLogin = localStorage.getItem('token') || '' router.beforeEach((to, from, next) => { // 先判断路由要跳转到哪?跳转登录页面且是登录状态 if (to.name === 'login' && !isLogin) { next() } // 不先判断会报错 :Maximum call stack size exceeded /* 分析报错原因: next()表示路由成功,直接进入to路由,不会再次调用route.beforeEach() next('/login')表示路由拦截成功,重定向值login,会再次调用route.beforeEach() */ if (isLogin) { next() } else { next('/login') } }) export default router
然后跳转login对应的页面就可以开心的开发页面了。
<template> <div class="login_bg"> <div class="container"> <div class="left"> <h1>夜跑记录管理系统</h1> <h2>study hard and make progress every day</h2> </div> <div class="right"> <div class="right_content"> <Form ref="formInline" :model="formInline" :rules="ruleInline"> <FormItem prop="user"> <Input type="text" size="large" clearable v-model="formInline.user" placeholder="用户名"> <Icon type="ios-person-outline" slot="prepend"></Icon> </Input> </FormItem> <FormItem prop="password"> <Input type="password" size="large" clearable v-model="formInline.password" placeholder="密码"> <Icon type="ios-lock-outline" slot="prepend"></Icon> </Input> </FormItem> <FormItem> <Button long type="default" ghost @click="handleSubmit('formInline')">登 录</Button> </FormItem> </Form> </div> </div> </div> </div> </template> <script> export default { data () { return { formInline: { user: '', password: '' }, ruleInline: { user: [ { required: true, message: '请填写用户名', trigger: 'blur' } ], password: [ { required: true, message: '请填写密码', trigger: 'blur' }, { type: 'string', min: 6, message: '密码长度不能小于6位', trigger: 'blur' } ] } } }, methods: { handleSubmit (name) { this.$refs[name].validate((valid) => { if (valid) { this.$Message.success('Success!') } else { this.$Message.error('Fail!') } }) } } } </script> <style scoped> .login_bg { min- 1200px; position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 10; background: url("../../static/img/login_bg.jpg") center center no-repeat; } .container { display: flex; align-items: center; } .left { text-align: center; 50%; color: #ffffff; } .right { background-color: rgb(0 0 0 / 40%); height: 100vh; 350px; z-index: 11; 30%; display: flex; align-items: center; } .right_content{ 75%; vertical-align: middle; margin: 0 auto; } </style>
开心的完成login页面,接下来要登录了。登录调接口之前思考一个问题:请求接口怎么封装?请求和响应拦截要怎么处理?那就开始一步步封装模块。
6、封装axios
参考链接: https://juejin.im/post/5b55c118f265da0f6f1aa354 掘金的网址(很好)
在vue项目中,和后台交互获取数据这块,我们通常使用的是axios库,它是基于promise的http库,可运行在浏览器端和node.js中。他有很多优秀的特性,例如拦截请求和响应、取消请求、转换json、客户端防御cSRF等。所以我们的尤大大也是果断放弃了对其官方库vue-resource的维护,直接推荐我们使用axios库。如果还对axios不了解的,可以移步axios文档。
npm install axios; // 安装axios
目录结构
axios里面是对请求超时、请求头、请求和响应拦截、环境的切换等的处理。
http.js里面封装了两个请求get、post。
Api文件里面是定义对应页面的请求。
话不多说,代码统统奉上:
axios.js:
import axios from 'axios'// 引入axios import router from '../router' // 设置 replace 属性(默认值: false)的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。即使点击返回按钮也不会回到这个页面。 const toLogin = () => { router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath// 携带当前页面路由,以期在登录页面完成登录后返回当前页面 } }) } var instance = axios.create({timeout: 1000 * 12}) // 环境的切换 if (process.env.NODE_ENV === 'development') { instance.defaults.baseURL = 'https://www.baidu.com' } else if (process.env.NODE_ENV === 'debug') { instance.defaults.baseURL = 'https://www.ceshi.com' } else if (process.env.NODE_ENV === 'production') { instance.defaults.baseURL = 'https://www.production.com' } // post请求头的设置 instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' // 请求拦截 instance.interceptors.request.use( config => { // 每次发送请求之前判断localStore是否存在token // 如果存在,则统一在http请求的header中加上token,这样后台根据token判断你的登录情况 // 即使本地存在token,也有可能是过期的,所以在相应拦截器中要对返回状态进行判断。 const token = localStorage.getItem('token') || '' token && (config.headers.token = token) return config }, error => { return Promise.error(error) } ) // 响应的拦截 instance.interceptors.response.use( response => { const code = response.data.code // 对状态码进行对应的处理 if (code === 0) { return Promise.resolve(response) } else if (code === 20000 || code === 20001 || code === 20002) { // 20000:用户token为空 20001:用户信息为空 20002:登录失效,请重新登录 // 清除token localStorage.removeItem('token') toLogin() return Promise.reject(response.data.msg) } else { if (response.data.msg) { return Promise.reject(response.data.msg) } } }, error => { return Promise.reject(error) } ) export default instance
http.js
import axios from './axios.js' import {Notice} from 'view-design' export function httpGet (url, params) { return new Promise((resolve, reject) => { axios.get(url, params).then(res => { resolve(res.data) }).catch(err => { Notice.error({ title: '错误', desc: err }) console.warn(err) reject(err) }) }) } export function httpPost (url, params) { return new Promise((resolve, reject) => { axios.post(url, params).then(res => { resolve(res.data) }).catch(err => { Notice.error({ title: '错误', desc: err }) console.warn(err) reject(err) }) }) }
login.js:
import {httpPost} from '../http.js' export function login (params) { return httpPost('/sys/user/login', params) }
封装好axios之后就开始写登录方法了,因为管理系统页面较多,所以考虑到数据状态的管理,需要vuex来对数据进行管理。
那就开始愉快的封装vuex模块对应的一些东东吧。
7、封装vuex模块。
安装vuex:
npm install --save vuex
新建一个store文件夹用来管理vuex模块。
import Vue from 'vue' import Vuex from 'vuex' import user from './modules/user' import products from './modules/products' Vue.use(Vuex) export default new Vuex.Store({ modules: { user, products } })
user.js
import {login} from '../../request/Api/login' import {Message} from 'view-design' // state // state提供数据源,所有的共享数据都要放到store的state中进行存储。 const state = { token: '', user: {}, menuList: [] } /** mutations用于变更store中的数据。 * 1)只能通过mutations变更store中的数据,不可以直接操作store中的数据。 * 2)通过这个方式操作操作起来稍微有点繁琐,但是可以集中监控所有数据的变化。 * */ const mutations = { setToken (state, token) { state.token = token }, setUserInfo (state, info) { state.user = info }, setMenuList (state, menu) { state.menuList = menu } } /** * Action用于处理异步任务 * 如果通过异步操作数据必须使用Action,不能使用mutations,但是在Action中还是通过出发Mutation的方式间接变更数据。 */ const actions = { loginHandle (content, params) { return new Promise((resolve, reject) => { login(params).then(res => { const result = res.result localStorage.setItem('token', result.user.token) localStorage.setItem('user', JSON.stringify(result.user)) localStorage.setItem('menuList', JSON.stringify(result.menus)) content.commit('setToken', result.user.token) content.commit('setUserInfo', JSON.stringify(result.user)) content.commit('setMenuList', JSON.stringify(result.menus)) debugger Message.success('登录' + res.msg) resolve(result) }).catch(error => { reject(error) }) }) } } const getters = { } export default{ state, mutations, actions, getters }
main.js里面要引入、挂载、处理store
import store from './store/index.js' import setStore from './store/setStore.js' new Vue({ el: '#app', router, store, created () { setStore() }, components: { App }, template: '<App/>' })
注意这个setStore,这个方法挂载在文件入口里面的原因是:登录之后将user信息储存到localStore中,登录之后进入页面之后store中的数据都置空了,所以在入口文件的created 的方法中set数据到store中。这样保证每个页面都能共享到stroe中的数据。
setStore.js
import store from './index' export default function setStore () { store.commit('setToken', localStorage.getItem('token')) store.commit('setUserInfo', localStorage.getItem('user')) store.commit('setMenuList', localStorage.getItem('menuList')) }
登录页面对应的修改:
import {mapActions} from 'vuex' methods: { ...mapActions(['loginHandle']), handleSubmit (name) { this.$refs[name].validate((valid) => { if (valid) { let params = { userName: this.formInline.user, password: md5(this.formInline.password) } this.loginHandle(params).then(res => { if (this.toPath) { this.$router.push(this.toPath) } else { this.$router.push({ name: 'Home' }) } }) .catch(error => { console.log(error) }) .finally((msg) => { console.log(msg) }) } else { return false } }) } }
8、要搭建页面的公共组件了(header、menu、view)。
先优化下登录页面的样式吧。有亿点丑。
调整完毕的页面,还是一丑,没办法不是搞ui的。先这样吧!!!
![](https://img2020.cnblogs.com/blog/1267018/202008/1267018-20200820152552853-1225775904.png)
github地址:
https://github.com/wenreq/basicsSys.git