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-width: 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;
width: 50%;
color: #ffffff;
}
.right {
background-color: rgb(0 0 0 / 40%);
height: 100vh;
width: 350px;
z-index: 11;
width: 30%;
display: flex;
align-items: center;
}
.right_content{
width: 75%;
vertical-align: middle;
margin: 0 auto;
}
</style>
开心的完成login页面,接下来要登录了。登录调接口之前思考一个问题:请求接口怎么封装?请求和响应拦截要怎么处理?那就开始一步步封装模块。
6、封装axios
参考链接: 掘金的网址(很好)
在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模块。
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
1、应用层级的状态应该集中到单个 store 对象中。
2、提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
3、异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
store
├── index.js # 我们组装模块并导出 store 的地方
└── modules
├── user.js # 个人信息模块
└── products.js # 产品模块
├── setStore.js # 设置store 存储数据的地方
代码奉上
index.js
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的。先这样吧!!!
翻转--------------------------------------------------------------------------------------------------------------------------------------->>>>>>