vue2.0从0开发项目管理系统

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

参考链接: 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模块。

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
  1、应用层级的状态应该集中到单个 store 对象中。
  2、提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  3、异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
store
    ├── index.js          # 我们组装模块并导出 store 的地方
    └── modules
        ├── user.js       # 个人信息模块
        └── products.js   # 产品模块
 ├── setStore.js          # 设置store 存储数据的地方
b站一个很哇塞的vuex教程:
代码奉上
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的。先这样吧!!!

 
翻转--------------------------------------------------------------------------------------------------------------------------------------->>>>>>
因为要开始封装菜单才想到忘记实现用户权限了。。。
有兴趣的看源码吧,不继续更了。OVER!!!!

 github地址:

https://github.com/wenreq/basicsSys.git

 

 

posted @ 2020-08-18 10:34  温少昌  阅读(760)  评论(0编辑  收藏  举报