使用vue-cli4手把手搭建一个完整的vue(vue+vuex+vue-router+scss+es6+antD+axios)项目

一、安装依赖

  • 全局安装vue-cli
npm install -g @vue/cli
  • 查看是否安装成功

键入vue --version ,出现以下版本号,则代表成功

如果使用poweshellr提示无法加载文件 D:\nvm\nodejs\vue.ps1,因为在此系统上禁止运行脚本,请点击我查看解决办法

二、创建项目

  • vue create vue-test // vue-test为项目名称,不支持驼峰
? Please pick a preset:
  default (babel, eslint) // 默认
> Manually select features // 手动选择,我选这个

接下来的选择可看红色圈出的部分部分

分别代表的是:

  1. 选择模式:手动选择配置
  2. 选择需要的配置:babel(es6编译)、vue-router(路由)、vuex(状态机)、css pre-porcessors(css预编译器,我后面选择的scss)、linter(语法、拼写等错误检查)
  3. 是否选择history路由模式:否
  4. 选择css预编译器:dart-sass编译,即scss
  5. 使用的错误检查机制:formatter config:Prettier
  6. 检查错误的条件:保存的时候
  7. 配置项放置位置:package.json
  8. 是否保存以上配置在以后项目中使用:否
  • 切换到vue-test文件夹,执行npm run serve启动项目

三、高阶配置

(一)引入axios

  • 安装axios
cnpm install --save axios vue-axios
  • 在根目录创建三个文件,以供不一样的环境使用

分别是.env,.env.development,.env.release,对应的变量

NODE_ENV=production    // 对应的启动环境
VUE_APP_API_BASE_URL=/api  // 请求的路径,根据自身情况更改

  • 创建token存储文件
    • 安装js-cookie,用来存储token
      cnpm install js-cookie --save
    • 在util下创建auth.js,编写读写token方法
      import Cookie from "js-cookie";
      const AccessTokenKey = "Admin-Token"; // 属性名,自行修改
      
      export function getAccessToken() {
        return Cookie.get(AccessTokenKey);
      }
      
      export function setAccessToken(token) {
        return Cookie.set(AccessTokenKey, token);
      }
      
      export function removeAccessToken() {
        return Cookie.remove(AccessTokenKey);
      }

  • 在util文件夹下创建request.js用于拦截配置
import axios from "axios";
// import store from "@/store";
import { getAccessToken } from "@/util/auth";
import { notification } from "ant-design-vue";

// 创建 axios 实例
const request = axios.create({
  // API 请求的默认前缀
  baseURL: process.env.VUE_APP_API_BASE_URL,
  timeout: 10000 // 请求超时时间,10s
});

// 异常拦截处理器
const errorHandler = errorRep => {
  if (errorRep.response) {
    const {
        data: { error },
        status
      } = errorRep.response,
      // 从 coockie 获取 token
      token = getAccessToken();
    // 身份验证失败
    if (status === 401) {
      notification.error({
        message: "身份验证",
        description: "登录过期,需要重新验证身份"
      });
      // 如果登录了,则退出登录
      if (token) {
        // store.dispatch("Logout").then(() => {
        //   setTimeout(() => {
        //     window.location.reload();
        //   }, 1500);
        // });
      }
    }

    if (status === 403) {
      notification.error({
        message: "拒绝访问",
        description: error.message
      });
    } else {
      notification.error({
        message: "错误消息",
        description: error.message
      });
    }
    return Promise.reject(error);
  }
  return Promise.reject(errorRep);
};

// 请求前拦截
request.interceptors.request.use(config => {
  const token = getAccessToken();
  // 如果 token 存在
  // 让每个请求携带自定义 token 请根据实际情况自行修改
  if (token) {
    config.headers["authorization"] = `Bearer ${token}`;
  }
  return config;
}, errorHandler);

// 请求后拦截
request.interceptors.response.use(response => {
  return response.data;
}, errorHandler);

export default request;
  • 在src下建api文件夹,再建一个js用于接口测试

(二)vuex常用设置

  • 在store创建一个module文件夹,再创建一个user.js用于存放用户信息。如果状态变量少,则无须建文件夹
import { login, getUserInfo, logout } from "@/api/user";
import { setAccessToken, removeAccessToken } from "@/util/auth";
const state = {
  token: null, // token
  name: null, // 用户名
  avatar: null, // 头像
  role: null // 角色
};

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token;
  },
  SET_NAME: (state, name) => {
    state.name = name;
  },
  SET_AVATER: (state, avatar) => {
    state.avatar = avatar;
  },
  SET_ROLE: (state, role) => {
    state.role = role;
  }
};

const actions = {
  // 登录,true代表登录成功
  login({ commit }, userInfo) {
    const { username, password } = userInfo;
    return login({ username, password }).then(token => {
      commit("SET_TOKEN", token);
      setAccessToken(token);
      return true;
    });
  },

  // 获取用户信息
  getUserInfo({ commit }) {
    return getUserInfo().then(user => {
      const { username, avatar, role } = user;
      commit("SET_NAME", username);
      commit("SET_AVATER", avatar);
      commit("SET_ROLE", role);
      return user;
    });
  },

  // 退出登录
  logout({ commit }) {
    return logout().then(() => {
      commit("SET_NAME", null);
      commit("SET_AVATER", null);
      commit("SET_ROLE", null);
      commit("SET_token", null);
      removeAccessToken();
      return true;
    });
  }
};

export default {
  state,
  mutations,
  actions
};
  • 在store创建一个getters.js文件,用于存放所有的state变量读取
export default {
  token: state => state.user.token,
  username: state => state.user.name,
  avater: state => state.user.avater,
  role: state => state.user.role
};
  • 在store的index.js下引入上述新建的文件
import Vue from "vue";
import Vuex from "vuex";
import getters from "./getters";

Vue.use(Vuex);

// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context("./modules", true, /\.js$/);

//module文件夹下的状态机自动引入
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // 格式化 './user.js' => 'user'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, "$1");
  const value = modulesFiles(modulePath);
  modules[moduleName] = value.default;
  return modules;
}, {});

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

export default store;

(三)route拦截设置

这里只写了判断登录,如果需要页面权限控制,则复杂很多,请参考这里

router.beforeEach((to, from, next) => {
  const token = getAccessToken();

  // 有token
  if (token()) {
    //登录页
    if (to.path === "/login") {
      next("/");
    }
    // 非登录页
    else {
      next();
    }
  }

  //无token
  else {
    //登录页
    if (to.path === "/login") {
      next();
    } else {
      next("/login?redirect=" + to.path);
    }
  }
});

(四)引入antD

1、正常引入

  • 安装antD
cnpm install ant-design-vue --save
cnpm install babel-plugin-import -save-dev

在根目录创建babel.config.js,并加入以下配置

plugins: [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css"}] // 如果需要自定义主题,此处style:true,需要自定义主题看下面描述
  ]
  • 在util文件夹下创建一个cusImportAntD.js引入所需的组件,并在main.js引入创建的js
// cusImportAntD.js,按需引入antD
import Vue from "vue";
import { Button, Input, Menu, Row, Col, Table, Modal, Tag, message, Icon, DatePicker, FormModel, Spin, notification, Result, Layout, Select, Collapse, Popconfirm, Tabs, Empty, Radio, Checkbox, Slider} from "ant-design-vue";
const antd = [ Button, Input, Menu, Row, Col, Table, Modal, Tag, Icon, DatePicker, FormModel, Spin, Result, Layout, Select, Collapse, Popconfirm, Tabs, Empty, Radio, Checkbox, Slider];
antd.forEach(component => {
  Vue.use(component);
});
Vue.prototype.$message = message;
Vue.prototype.$notification = notification;

// main.js引入cusImportAntD.js
// 引入antD,因为已经使用了babel-plugin-import,此处无需引入css
import "@/util/cusImportAntd";
  • 在helloword.vue测试一下

2、自定义主题(不需要则跳过此步骤)

  • 安装less和less-loader
cnpm install less less-loader --save-dev
  • 修改babel.config.jsstyle:true,以加载less

plugins: [
    ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": true}] // `style: true` 会加载 less 文件
  ]
  • vue.config.js添加变量配置项,全部变量点击这里

css: {
    // requireModuleExtension: false,  // 这句话不能要,否则css样式不起效
    loaderOptions: {
      less: {
        // 这里的选项会传递给 less-loader
        lessOptions: {
          modifyVars: { // 这里是自定义的主题颜色,全部变量属性参照官方
            "primary-color": "#1DA57A",
            "link-color": "#1DA57A",
            "border-radius-base": "2px"
          },
          javascriptEnabled: true // 这句话必须要,否则不起效
        }
      }
    }

猜你喜欢

转载自blog.csdn.net/liuxin00020/article/details/106617524