从 0 搭建vue项目中配置各种文件

64 阅读6分钟

先去官网查看安装@vue/cli教程 cli.vuejs.org/zh/guide/in…

image.png

使用如下命令进行安装
npm install -g @vue/cli

安装完毕后可以使用

vue --version 进行查看当前的vue版本

如需升级全局的 Vue CLI 包,请运行

npm update -g @vue/cli 

使用vue-cli来创建一个基础的项目

vue create hello-world  表示创建一个名为hello-world的项目

安装创建的命令提示一步步安装即可 cli脚手架提供的服务

在一个 Vue CLI 项目中,@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。

{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
  }
}

你可以通过 npm 或 Yarn 调用这些 script:

npm run serve
# OR
yarn serve

如果你可以使用 npx (最新版的 npm 应该已经自带),也可以直接这样调用命令:

npx vue-cli-service serve

一些命令

## vue-cli-service serve
用法:
vue-cli-service serve [options] [entry] 选项:
--open 在服务器启动时打开浏览器
--copy 在服务器启动时将 URL 复制到剪切版
--mode 指定环境模式 (默认值:development)
--host 指定 host (默认值:0.0.0.0) 
--port 指定 port (默认值:8080) 
--https 使用 https (默认值:false)

## vue-cli-service build
用法:
 
 --mode        指定环境模式 (默认值:production)
  --dest        指定输出目录 (默认值:dist)
  --modern      面向现代浏览器带自动回退地构建应用
  --target      app | lib | wc | wc-async (默认值:app)
  --name        库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
  --no-clean    在构建项目之前不清除目标目录的内容
  --report      生成 report.html 以帮助分析包内容
  --report-json 生成 report.json 以帮助分析包内容
  --watch       监听文件变化
 

Vue CLI 项目天生支持 PostCSSCSS Modules 和包含 SassLessStylus 在内的预处理器。

你可以在创建项目的时候选择预处理器 (Sass/Less/Stylus)。如果当时没有选好,内置的 webpack 仍然会被预配置为可以完成所有的处理。你也可以手动安装相应的 webpack loader:

# Sass
npm install -D sass-loader sass

# Less
npm install -D less-loader less

# Stylus
npm install -D stylus-loader stylus

然后你就可以导入相应的文件类型,或在 *.vue 文件中这样来使用:

<style lang="scss">
$color: red;
</style>

基本上到这里就已经初步完成了一个项目的构建了,但是其中仍然有一些文件需要详细的配置一下以便于更好的开发

如果你在使用vue-cli的过程中并没有安装任何的css预处理器与route以及element-ui等等。那么就需要手动配置

一:配置route 进入官网 router.vuejs.org/zh/ 查看教程 安装

npm install vue-router

在main.js中引入

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

但是官网中给出解释,如果是使用的vue CLI创建的项目,则可以以项目插件的形式添加 Vue Router,CLI可以生成上述代码以及两个路由,它也会覆盖你的App.vue ,因此执行这个命令前请先复制你的App.vue

vue add router

在src下创建route文件夹 如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {
  return originalPush.call(this, location).catch(err => { })
};

// 在Vue类中加入Vue-router的实例
Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    // 重定向
    redirect: "Home"
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/details',
    name: 'Details',
    component: () => import("../views/Details.vue")
  },
  {
    path: '/goods',
    name: 'Goods',
    component: () => import("../views/Goods.vue")
  },
  {
    path: '/user',
    name: 'User',
    component: () => import("../views/User.vue"),
    redirect: "/user/cart",
    children: [
      // 购物车
      {
        path: "cart",
        component: () => import("../components/user/Cart.vue")
      },
      // 我的订单
      {
        path: "order",
        component: () => import("../components/user/order.vue")
      },
    ],
  },
  {
    path: '/order',
    name: 'Order',
    component: () => import("../views/Order.vue")
  },
  {
    path: '/free',
    name: 'Free',
    component: () => import("../views/Free.vue")
  },
  {
    // 关于404页面的路由配置
    path: '*',
    name: 'Error',
    component: () => import("../views/Error.vue")
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

// // 设置全局路由守卫
// router.beforeEach((to, from, next) => {
//   // console.log('to:', to);
//   // console.log('from:', from);

//   // 判断将要访问的路由为用户中心
//   if (to.name == 'User') {
//     let token = localStorage.getItem('x-auth-token')
//     // 有token就说明用户已经登录,直接放行
//     if (token) {
//       next()
//     } else {
//       alert("你未登录,需要登录后再操作")
//     }

//     return
//   }

//   // 如果进入不是用户中心则直接放行
//   next()
// })

export default router

然后在main.js中引入

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import SlideVerify from 'vue-monoplasty-slide-verify' // 拼图验证码

// 引入公共样式模块
import "reset-css"
import "@/assets/css/public.less"
Vue.prototype.$store = store
Vue.use(SlideVerify)
Vue.config.productionTip = false

// 设置一个公共变量用于保存,图片服务器的地址
Vue.prototype.imgBaseHost = "http://sc.wolfcode.cn"

// console.log(process.env.VUE_TEST);

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

创建request文件夹,封装axios请求


import axios from 'axios'
import {Message} from "element-ui";
import router from '@/router'
const instance = axios.create({
    baseURL:"http://120.27.232.149:81",
    timeout:10000
    
})

instance.interceptors.request.use((config)=>{
    if(!config.url.endsWith("/login") && !config.url.endsWith("/captchaImage")){
      config.headers['Authorization'] ='Bearer '+localStorage.getItem("edn-authorization-token")
    }
    return config
},err=>{
    return Promise.reject(err)
})

instance.interceptors.response.use((res)=>{
    let res_data = res.data;
    // 当我们使用导出接口的时候,我们返回的数据是没有code值的,但是这个却又是正确的数据,所以我们需要放行而不是将其报出为错误
    if(res_data.code && res_data.code!=200){
        Message.error(res_data.msg || "网络请求错误")
        if(res_data.code==401){
            localStorage.removeItem("edn-authorization-token");
            router.push("/login")
        }
        
        return false
    }
    return res.data
},err=>{
    return Promise.reject(err)
})

export default instance;


或者
/*
 * @Author: iou2008 25844550@qq.com
 * @Date: 2022-09-03 23:47:37
 * @LastEditors: iou2008 25844550@qq.com
 * @LastEditTime: 2022-09-08 11:40:46
 * @FilePath: \01代码e:\项目\狼\成都6期\0904Vue项目实战——用户登录\01代码\code-shop\src\request\index.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// index.js  用于封装管理AIP的提交
// 引入模块
import axios from "axios";

// 创建个axios的对象axios.create(配置)
const instance = axios.create({
  // 因为接口服务器是有可以有更改的,所以我们在AXIOS对象上创建一个数据用于记录接口服务器。
  // baseURL: "http://kumanxuan1.f3322.net:8881/cms", // baseURL:当请求地址不是完整时,对象会自动使用该值进行补全
  // baseURL:"http://192.168.113.249:8081/cms",
  baseURL: "/api",
  timeout: 5000, // 设置请求超时的时间。
});

// 所有请求之前需要执行的方法(请求拦截器)
instance.interceptors.request.use(
  (config) => {
    console.log("每一次发起请求前,都会先执行这里的代码");
    console.log(config); //config本次请求的配置信息
    // 对于某些特殊的接口请求进行头信息的处理
    if (config.url == "/sendSMS") {
      config.headers["Content-Type"] = "application/x-www-form-urlencoded";
    }

    // 由于Token是后端验证用户的唯一作证,所以我们可以让只要有Token时所有的请求都带上Token。
    const token = localStorage.getItem("x-auth-token");
    if (token) {
      // 如果token有值,则在请求的头信息中带上token
      config.headers["x-auth-token"] = token;
    }
    return config;
  },
  (err) => {
    return Promise.reject(err);
  }
);

// 所有获取到响应的时个之前也可以需要执行的方法(响应拦截器)
instance.interceptors.response.use(
  (res) => {
    console.log(
      "每一次接收到响应,都会先执行这里的代码,再去执行成功的那个回调函数then"
    );
    // 由于我们接口统一正常执行下都会返回code的值为0,所以我们对所有code值不为0的进行处理
    let data = res.data;
    // 所有code不为0,说明接口有问题,直接输出错误信息就可以了。
    if (data.code != 0 && data.code != 400 && data.code != 407) {
      alert(data.message);
      return false;
    }
    return data;
  },
  (err) => {
    return Promise.reject(err);
  }
);

export default instance; 

如果要使用的话

import request from "./index";
import qs from "qs";
引入即可使用


// 商品详细数据接口
export const GoodsInfoAPI = function (id) {
  return request.get("/products/" + id);
};

// 手机号登录的接口
export const PhoneLoginAPI = (params) =>
  request.post("/phoneRegin", qs.stringify(params));

在vue.config.js里面配置代理服务器

 devServer: {
    proxy: {
      // 如果访问的路径中包含/api就会执行代理服务
      "/api": {
        target: "http://kumanxuan1.f3322.net:8881/cms",
        // target: process.env.VUE_APP_BASE_URL,
        // 相当于页面转发的地址多了/api所以需要删除掉/api进行转发才是真正的地址
        pathRewrite: {
          "^/api": "",
        },
      },
    },
  },

配置store 打开官网: v3.vuex.vuejs.org/zh/installa…

以上的所有的插件都是在vue2官网的生态系统的核心插件下能找到 安装:

npm install vuex --save 
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: { 
       increment (state, payload) {
         state.count += payload.amount
       } 
  }, 
  actions: {
    increment (context) {
      context.commit('increment')
    },  
  checkout ({ commit, state }, products) {
        // 把当前购物车的物品备份起来
        const savedCartItems = [...state.cart.added]
        // 发出结账请求,然后乐观地清空购物车
        commit(types.CHECKOUT_REQUEST)
        // 购物 API 接受一个成功回调和一个失败回调
        shop.buyProducts(
          products,
          // 成功操作
          () => commit(types.CHECKOUT_SUCCESS),
          // 失败操作
          () => commit(types.CHECKOUT_FAILURE, savedCartItems)
       )
    } 
  } ,
  
}) 
export default store

store 分模块

image.png

image.png

/**
 * 提示消息框的状态控制模块。
*/
/**
   * 提示组件需要有的内容:
   * 1. 提示的信息
   * 2. 提示需要不同的类型
  */
export default {
    namespaced:true,
    state:{
        isShowToast:false, //是否显示提示信息框
        toastMsg: "小明好帅",  // 当前提示框的信息内容
        toastType: "success",  // 当前提示框的类型(success, danger, info, warning)
    },
    mutations:{
        changeIsShowToast(state,payload){
            // console.log(payload);
            state.isShowToast = payload.isShow;

            // 如果本次操作为显示提示时,才更新提示的信息与类型
            if(state.isShowToast){
                state.toastMsg = payload.msg;
                state.toastType = payload.type;
            }

            // 由于mutations不应该写异步的内容,所以setTimeout不写在这里
            // setTimeout(()=>{
            //     state.isShowToast = false     
            // },1500)
        }
    },
    actions:{
        // 修改消息提示框数据的方法,包含自动关闭
        asyncIsShowToast(context, payload){
            context.commit("changeIsShowToast", payload)

            setTimeout(()=>{
                context.commit("changeIsShowToast", {
                    isShow:false
                })
            },1500)
        },

        asyncIsShowToast2({state}, payload){
            // console.log(payload);
            state.isShowToast = payload.isShow;

            // 如果本次操作为显示提示时,才更新提示的信息与类型
            if(state.isShowToast){
                state.toastMsg = payload.msg;
                state.toastType = payload.type;
            }

            setTimeout(()=>{
                state.isShowToast = false
            },1500)
        }
    }
}
import Vue from 'vue'
import Vuex from 'vuex'
import showModal from './showModal'
import loginStatus from './loginStatus'
import showToast from './showToast'
import userInfo from './userInfo'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
    showModal,
    loginStatus,
    showToast,
    userInfo
  }
})

ok 项目完成了