vue真实项目开发从0到1

项目环境

node : 12.10.0

npm : 6.10.3

vue-cli : 2.x

  • 1、使用normalize.css统一浏览器标签样式

    npm i -S normalize.css

    main.js中引用:import 'normalize.css'

  • 2、使用reset-css重置默认样式

    npm i -S reset-css

    main.js中引用:import 'reset-css'

  • 3、引入iconfont图标库

    这里我将阿里图标库放入到static/font目录下

    main.js中引入:import '../static/font/iconfont.css'

    即可在vue中通过class="iconfont iconxxx"进行使用

  • 4、使用vue-cookies管理cookies

    npm i vue-cookies -S

    main.js中

    import vueCookies from 'vue-cookies';

    Vue.use(vueCookies );

  • 5、使用vue-router(cli已引入)

    router目录下我的结构如下:

    index.js // 路由入口文件

    map // 路由

    hooks // 路由钩子函数,用来鉴权

    // index.js 路由入口文件,用于挂载路由和钩子
    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import routesMap from './map/'; // 路由映射(index.js)
    import hooks from './hooks/'; // 路由钩子(index.js)
    
    Vue.use(VueRouter);
    
    const router = new VueRouter({
      mode: 'hash',
      routes: routesMap()
    });
    hooks(router);
    
    export default router;

    map/index.js

    // map/index.js
    import home from './home';
    
    // 删除没有权限的路由
    function deleteNoAuth(arr) {
      // 自定义函数去遍历并删除没有权限的路由
    }
    
    let routes = () => {
      let routes = [
        ...home(),
      // 更多自己的路由
        {
          path: "*",
          redirect: "/home/"
        }
      ];
      deleteNoAuth(routes);
      return routes;
    };
    export default routes;

    map/home.js

    // map/home.js
    // 懒加载(异步加载组件)
    const home = () => import('@/views/home/home.vue');
    const routes = () => {
      return [
        {
          path: '/home',
          name: 'home',
          flg: true,      // 我自定义的权限命名
          component: home,
          meta: {
            des: "首页"    // 后续钩子函数动态改变title
          }
        }
      ];
    };
    export default routes;

    hooks/index.js

    hooks有以下文件及文件夹(beforeEach/afterEach/index.js)

    hooks/index.js

    import titleInterceptor from './beforeEach/titleInterceptor';
    import authorization from './beforeEach/authorization';
    // 这里仅介绍一下鉴权和动态改变title
    export default (router) => {
      router.beforeEach(titleInterceptor(router));
      router.beforeEach(authorization(router));
    };

    hooks/beforeEach/authorization

    // 登录权限
    const authorization = (router) => (to, from, next) => {
      if (to.path == '/login') {
        next()
      } else {
        // 此处使用了vue-cookies,已经通过vue.use使用,所以可以直接使用,登录时设置了token字段
        if (!router.app.$cookies.get('token')) {
          // 此处使用了element-ui中的message组件(element-ui使用这里省略)
          router.app.$message({
            message: '登录身份过期,请重新登录!',
            type: 'warning'
          })
          // 如无权限则回到login页面(请求权限将通过axios进行封装!)
          next('/login');
        } else {
          next()
        }
        next()
      }
    };
    
    export default authorization;

    hooks/beforeEach/titleInterceptor

    const titleInterceptor = (router) => (to, from, next) => {
      // 在路由中我使用meta.des设置title信息
      const { meta, path } = to;
      document.title = to.meta.des || '今后宜喜。';
      next();
    };
    
    export default titleInterceptor;
  • 5、引入axios并封装请求

    // 同样通过 npm i -S axios
    // 我在/src/http/index.js目录封装请求
    import axios from 'axios';
    import cookie from 'vue-cookies';
    
    // axios全局配置
    axios.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
    
    // 添加请求拦截
    axios.interceptors.request.use(function (config) {
      // 添加授权(通过vue-cookies在登录后设置token,这里将在后续请求中使用鉴权)
      if (cookie.get('token')) {
        config.headers['X-Authorization'] = "xxx " + cookie.get('token');
      }
      return config;
    }, function (error) {
      return Promise.reject(error);
    });
    
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
      return response.data;
    }, function (error) {
      if (error.response.status == 401) {
        // 授权不通过时,移除token并返回登录页
        cookie.remove('token');
        Router.push({ path: '/login' });
      }
      return Promise.reject(error);
    });
    
    export default axios;

    前后端协同开发接口调用跨域问题,vue-cli可以方便的配置代理从而解决该问题:

    在项目config/index.js目录中添加代理服务器地址,配置baseUrl:

    // 在 dev对象下添加
        proxyTable: {
          "/api": {
            target: "http://x.x.x.x:xxxx", // 设置你调用的接口域名和端口号
            changeOrigin: true,
            pathRewrite: {
              "^/api": ""         // 调用时使用url使用api/xxx即为http:x.x.x.x:xxxx/api/xxx
            }
          }
        },
  • vuex管理公共状态

    npm i -s vuex

    在src目录下创建store目录

    store/index.js

    import Vue from 'vue';
    import Vuex from 'vuex';
    // 引入定义的modules , 当然你可以定义单独的getters,mutations,state,这里仅定义modules/user用户信息用于说明
    import user from './modules/user';
    
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
      modules: {
        user
      }
    });
    
    export default store;

    store/modules/user.js

    // 将vuex状态与localStorage结合从而实现状态持久化!
    var currentUser = localStorage.getItem("currentUser") && JSON.parse(localStorage.getItem("currentUser"));
    
    const state = {
      userInfo: currentUser ? currentUser : {}
    }
    
    const getters = {
      getUserInfo: state => {
        return state.userInfo
      }
    }
    // 这里通过localStorage将mutations数据做持久化处理,当然这里只是粗糙处理,可以单独封装函数用于统一将state保存到localStorage中(如果你的业务需要将state状态做持久化处理的话)
    const mutations = {
      setUserInfo(state, userInfo) {
        localStorage.setItem("currentUser", JSON.stringify(userInfo));
        state.userInfo = userInfo
      },
      clearUserInfo(state) {
        localStorage.removeItem("currentUser");
        state.userInfo = {}
      }
    }
    
    const actions = {
      setUserInfoAsync({
        commit
      }, user) {
        localStorage.setItem("currentUser", JSON.stringify(user));
        commit('setUserInfo', user)
      }
    }
    export default {
      state,
      getters,
      mutations,
      actions
    }

    main.js中:

    import store from './store';
    // ...
    new Vue({
      el: '#app',
      router: router,
      store,
      components: { App },
      template: '<App/>',
    })
  • 总结

    ### 样式相关,使用了一下库统一浏览器样式,并使用iconfont
    normalize.css
    reset-css
    iconfont
    ### vue-cookies的使用
    方便对cookies的操作,并且结合vue-router对路由进行鉴权,同时结合axios对请求进行鉴权
    ### vue-router
    钩子函数处理
    ### axios的使用
    对请求做统一处理,结合vue-cookies,vue-router进行鉴权。通过config/index.js设置proxyTable代理实现跨域请求。
    ### vuex的使用
    保存公共状态
    
    # 具体依赖的使用可看npm下的readme进行实现

猜你喜欢

转载自www.cnblogs.com/turboni/p/11731241.html