zoukankan      html  css  js  c++  java
  • 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- 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模块。

    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

  • 相关阅读:
    MySql数据基础之数据表操作
    MySql数据库之数据库基础命令
    MySql数据库基础之数据库简介及安装
    JQuery之Ajax基础
    Ajax简单应用之个人简历页面搭建
    Ajax之处理不同格式的JSON数据
    题解 P2447 【[SDOI2010]外星千足虫】
    题解 P4035 【[JSOI2008]球形空间产生器】
    题解 P2831 【愤怒的小鸟】
    题解 P2827 【蚯蚓】
  • 原文地址:https://www.cnblogs.com/wenshaochang123/p/13522029.html
Copyright © 2011-2022 走看看