# Vue知识

# 组件版本

用的node版本比较老,对应的一些组件版本如下

名称 版本
node 13.14.0
npm 6.14.4
sass-loader 7.0.1
node-sass 4.13.0
svg-sprite-loader 6.0.11
vue 2.5.2
vuex 3.0.1
vue-router 3.0.1
element-ui 2.15.13
axios 1.3.3
echarts 5.4.1

# 项目搭建

# 1.创建项目

vue init webpack vue-mall

选择vue-router

# 2.集成vue-router

创建src/router/index.js、src/permission.js

import Vue from "vue";
import Router from "vue-router";
import Layout from "@/views/layout/Layout";

Vue.use(Router);

export const asyncRoutes = [{}];

export const currencyRoutes = [
  {
    path: "/404",
    name: "404",
    hidden: true,
    meta: {
      title: "404"
    },
    component: () => import("@/views/404")
  },
  {
    path: "/login",
    name: "Login",
    hidden: true,
    meta: {
      title: "login"
    },
    component: () => import("@/views/login/index")
  },
  {
    path: "/",
    component: Layout,
    redirect: "/dashboard",
    meta : {},
    children: [
      {
        path: "/dashboard",
        name: "Dashboard",
        component: () => import("@/views/Dashboard"),
        meta: {
          title: "看板",
          icon: "el-icon-data-line"
        }
      },
      {
        path: "/personal",
        name: "Personal",
        hidden: true,
        component: () => import("@/views/Personal/index"),
        meta: {
          title: "我的主页"
        }
      }
    ]
  }
];

const creatRouter = () => {
  return new Router({
    routes: currencyRoutes,
    scrollBehavior() {
      return { x: 0, y: 0 };
    }
  });
};

const router = creatRouter();

// 解决addRoute不能删除动态路由问题
export function resetRouter() {
  const reset = creatRouter();
  router.matcher = reset.matcher;
}

export default router;

import router from "./router";
import { getToken } from "./utils/auth";

const whiteList = ["/login"];
router.beforeEach((to, from, next) => {
  const hasToken = getToken();
  if (hasToken) {
    if (to.path === "/login") {
      next({
        path: "/"
      });
    } else {
      next();
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next();
    } else {
      next({
        path: "/login"
      });
    }
  }
});

可基于router的子路由,创建全局的layout样式。 具体可查看demo项目

# 2.集成element-ui

 npm i element-ui -S

修改main.js,加入

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

# 3.集成axios

npm install -S axios

调整dev.env.js

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"http://localhost:9797"'
})

创建src/api,将接口路由创建到对应文件,如下login.js

import request from "@/utils/request";

export function login(data) {
  return request({
    url: "/login",
    method: "post",
    data
  });
}


export function getUserInfo(token) {
  return request({
    url: "/login/getUserFromToken?token=" + token,
    method: "get"
  });
}

编写request.js,做拦截器

import axios from "axios";
import { Message, MessageBox } from "element-ui";
import store from "@/store";
import { getToken } from "@/utils/auth";

// 创建axios实例
const service = axios.create({ 
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 120000 // 请求超时时间
});

// request拦截器
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers["token"] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    return config;
  },
  error => {
    // Do something with request error
    console.log(error); // for debug
    Promise.reject(error);
  }
);

// respone拦截器
service.interceptors.response.use(
  response => {
    /**
     * code为非200是抛错 可结合自己业务进行修改
     */
    const res = response.data;
    if (res.code !== 200) {
      Message({
        message: res.message,
        type: "error",
        duration: 3 * 1000
      });

      // 403:未登录;
      if (res.code === 403) {
        MessageBox.confirm(
          "你已被登出,可以取消继续留在该页面,或者重新登录",
          "确定登出",
          {
            confirmButtonText: "重新登录",
            cancelButtonText: "取消",
            type: "warning"
          }
        ).then(() => {
          store.dispatch("user/LoginOut").then(() => {
            // location.reload(); // 为了重新实例化vue-router对象 避免bug
          });
        });
      }
      return Promise.reject("error");
    } else {
      return response.data;
    }
  },
  error => {
    console.log("err" + error); // for debug
    Message({
      message: error.message,
      type: "error",
      duration: 3 * 1000
    });
    return Promise.reject(error);
  }
);

export default service;

# 4.集成vuex

npm install vuex@next --save

新建 src/store src/store/index.js src/store/getter.js src/store/modules/user.js

user.js

import { login, getUserInfo } from "@/api/login";
import { setToken, setUser} from "@/utils/auth";
import router, { resetRouter ,asyncRoutes, currencyRoutes } from "@/router";


const state = {
  token: localStorage.getItem("token") ? localStorage.getItem("token") : "", // 认证凭证'
  user: localStorage.getItem("user") ? localStorage.getItem("user") : "",

};

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token;
  },
  DEL_TOKEN(state) {
    state.token = "";
    state.user = {};
   
    localStorage.removeItem("token");
    localStorage.removeItem("user");
  },

  SET_USER(state, payload) {
    state.user = payload;
  }
};
const actions = {
  Login({ commit }, userInfo) {
    const { userId, password } = userInfo;
    return new Promise((resolve, reject) => {
      login({
        userId: userId.trim(),
        password: password
      })
        .then(response => {
          const token = response.data;
          commit("SET_TOKEN", token);
          setToken(token);
          resolve(token);
        })
        .catch(error => {
          resolve("");
        });
    });
  },
  LoginOut({ commit }) {
    commit("DEL_TOKEN");
    resetRouter();
    router.push({
      path: "/login",
      query: {
        redirect: "/"
      }
    });
  },
  SetUserInfo({ commit }, payload) {
    return new Promise((resolve, reject) => {
      getUserInfo(payload).then(response => {
        const { data } = response;
        commit("SET_USER", data);
        setUser(data);
        resolve(data);
      });
    });
  },
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
};

getters.js

const getters = {
  token: state => state.user.token,
  routes: state => state.permissions.routes,
  user: stat => {
    if (typeof stat.user.user === "string") {
      return JSON.parse(stat.user.user);
    } else {
      return stat.user.user;
    }
  }
};

export default getters;

index.js

import Vue from "vue";
import Vuex from "vuex";
import user from "./modules/user";
import getters from "./getters";

Vue.use(Vuex);

const store = new Vuex.Store({
  modules: {
    user
  },
  getters
});

export default store;

# 5.集成svg

npm i svg-sprite-loader --save

配置webpack解析svg,webpack.base.conf.js修改

{
        test: /\.svg$/,
        loader: 'svg-sprite-loader',
        include: [resolve('src/icons')],
        options: {
          symbolId: 'icon-[name]'
        }
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        exclude: resolve('src/icons'),
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      }

新建src/icons/svg、src/icons/index.js

import Vue from "vue"
import SvgIcon from '@/components/SvgIcon'

Vue.component('svg-icon', SvgIcon);

const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

使用方式

<template>
  <svg :class="svgClass" aria-hidden="true">
    <use :xlink:href="iconName"></use>
  </svg>
</template>

# 6.集成scss

这两个组件编译基于python,先检查本地机器是否有python,并且有环境变量,执行python命令能正常输出 同时他对不同node版本有不同对应关系,查看对应关系 (opens new window) 确保对应版本,不然会install一直报错

 npm  install sass-loader@7.0.1 --save-dev
 npm install node-sass@4.13.0 --sava-dev

创建src/styles 编写全局scss

# demo项目

至此,一个基于vuex、aixos、vue-router支持svg、scss的vue2项目就已经构建完成了。当然,全局的layout还需自己编写。 具体可查看演示项目,已经配置了可供开发的基本配置 演示项目 (opens new window)

参考项目一 (opens new window) 参考项目二 (opens new window)

# 命令

# 安装依赖
npm install

# 本地启动
npm run dev

# 打包
npm run build