二蛋个人 Vue CLI3搭建项目初始

435 阅读3分钟

Vue CLI3搭建项目初始

1.安装Vue CLI3

​ 1.在cmd中执行:npm install -g @vue/cli

​ 2.安装完成后,输入命令vue --version,查看Vue CLI的版本号是否是3.0以上,是代表安装成功。

2.创建项目

​ 1.在cmd中执行:vue create xxx, xx为项目名称

​ 2.选择,anually select features(手动选择功能)项或者default (babel, eslint)(默认安装);这里我选择anually

​ 3.选择的有babel、router、vuex、css.路由选择历史模式,css预处理器为less语言选择In dedicated config files,将Babel、PostCSS等配置独立在package.json文件外。是否保存本次安装配置。选择不。

3.清理初始化脚手架项目。

1.package.json文件

​ 原本代码块:

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

​ 改为:

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

2.清洁public文件下的index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
</head>
<body>
    <div id="app"></div>
</body>
</html>

3.清洁router.js文件

import Vue from 'vue'
import Router from 'vue-router';
Vue.use(Router) 

function load(component) {  (这个函数会问题可以屏蔽)
    return resolve => require([`./views/${component}`], resolve);
}

export default new Router({
    mode: 'history',
    base: process.env.BASE_URL,
    routes: [
        {
            path: '/',
            name: 'home',
            component: load('home')
        },
    ]
})

4、清洁App.vue文件

<template>
  <div>
    <router-view/>
  </div>
</template>

5、清洁views文件夹

删除views文件夹中的About.vue和Home.vue文件,

新建home.vue文件.内容如下:

<template>
    <div>
        欢迎使用Vue项目
    </div>
</template>

6、清洁components文件夹

删除components文件夹中的HelloWorld.vue文件。

7、清洁assets文件夹

删除assets文件夹夹中的logo.png文。

8、清洁完毕

重新执行npm run dev,执行成功后在浏览器打开 http://localhost:8080/ ,页面展示<欢迎使用vue项目>,说明Vue项目已经清洁成功。

4、配置Vue项目

1、新建api文件夹和utils文件夹

npm i axios -save

utils内的axios封装的优化

/**
 * axios封装
 * 请求拦截、响应拦截、错误统一处理
 */
import axios from 'axios';
import router from '../router';
import store from '../store/index';
import { Toast } from 'vant'; //不安装vant就屏蔽

/** 
 * 提示函数 
 * 禁止点击蒙层、显示一秒后关闭
 */
const tip = msg => {    
    Toast({        
        message: msg,        
        duration: 1000,        
        forbidClick: true    
    });
}

/** 
 * 跳转登录页
 * 携带当前页面路由,以期在登录页面完成登录后返回当前页面
 */
const toLogin = () => {
    router.replace({
        path: '/login',        
        query: {
            redirect: router.currentRoute.fullPath
        }
    });
}

/** 
 * 请求失败后的错误统一处理 
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status, other) => {
    // 状态码判断
    switch (status) {
        // 401: 未登录状态,跳转登录页
        case 401:
            toLogin();
            break;
        // 403 token过期
        // 清除token并跳转登录页
        case 403:
            tip('登录过期,请重新登录');
            localStorage.removeItem('token');
            store.commit('loginSuccess', null);
            setTimeout(() => {
                toLogin();
            }, 1000);
            break;
        // 404请求不存在
        case 404:
            tip('请求的资源不存在'); 
            break;
        default:
            console.log(other);   
        }}

// 创建axios实例
var instance = axios.create({    timeout: 1000 * 12});
// 设置post请求头
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
/** 
 * 请求拦截器 
 * 每次请求前,如果存在token则在请求头中携带token 
 */ 
instance.interceptors.request.use(    
    config => {        
        // 登录流程控制中,根据本地是否存在token判断用户的登录情况        
        // 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token        
        // 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码        
        // 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。        
        const token = store.state.token;        
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => Promise.error(error))

// 响应拦截器
instance.interceptors.response.use(    
    // 请求成功
    res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),    
    // 请求失败
    error => {
        const { response } = error;
        if (response) {
            // 请求已发出,但是不在2xx的范围 
            errorHandle(response.status, response.data.message);
            return Promise.reject(response);
        } else {
            // 处理断网的情况
            // eg:请求超时或断网时,更新state的network状态
            // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
            // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
            if (!window.navigator.onLine) {
               store.commit('changeNetwork', false);
            } else {
                return Promise.reject(error);
            }
        }
    });

export default instance;

api文件夹的index.js

/**
 * api接口的统一出口
 */
// 模块接口
import test from '@/api/test'
// 其他模块的接口……

// 导出接口
export default {
  test,
  // ……
}

对应test模块的接口

import axios from '@/utils/http' // 导入http中创建的axios实例

const test = {
  // 新闻列表
  test() {
    return axios.post(`/api/demo1`).then((res) => {
      return res.data
    })
  },
}

export default test


demo.vue
  this.$api.test.test().then(res => {
      console.log(res);
    })

最后,为了方便api的调用,我们需要将其挂载到vue的原型上。在main.js中:

import api from './api' // 导入api接口
Vue.prototype.$api = api; // 将api挂载到vue的原型上

2、新建mixins文件夹

在src文件夹下新建mixins文件夹,主要放置Vue混入文件。

在minxins文件夹下,新建index.js文件,主要放置全局混入的内容,

import { mapGetters } from 'vuex';
export default {
    data() {
        return {
        }
    },
    computed: {
        ...mapGetters(['tip','moduleTip'])
    },
    mounted(){
    },
    methods: {
    }
}

在main.js 引入全局混入,

import mixins from './mixins';
Vue.mixin(mixins);

3、配置assets文件夹

  1. 在assets文件夹下新建css文件夹,主要放置样式文件;
  2. 在assets文件夹下新建images文件夹,主要放置可以编译的图片文件。

4、新建router文件夹

​ 在src文件夹下新建router文件夹,

​ 删除src文件夹下的router.js文件,

​ 在router文件夹中,新建index.js和routes.js文件,

​ index.js内容:

import Vue from 'vue';
import Router from 'vue-router';
import routes from './routes';
Vue.use(Router);

// 路由配置
const router = new Router({
   mode: 'history',
   base: process.env.BASE_URL,
   routes,
   scrollBehavior(to, from, savedPosition) {
      if (savedPosition) {
         return savedPosition;
      } else {
         return {x: 0, y: 0};
      }
   }
});

router.beforeEach((to, from, next) => {
   next();
});

router.afterEach((to, from, next) => {
   window.scrollTo(0, 0);
});

export default router;

routes.js内容:

function load(component) {  //懒加载写到
    return resolve => require([`views/${component}`], resolve);
}

const routes = [
    {
        path: '/',
        name: 'home',
        component: load('home'),
        meta: {
            title: '首页'
        }
    },
    {
        path: '*',
        redirect: {
            path: '/'
        }
    }
];
export default routes;

5、新建store文件夹

​ 在src文件夹下新建store文件夹,放置Vuex的内容,

​ 删除src文件夹下的store.js文件,

​ 在store文件夹下新建module文件夹,

​ 在module文件夹下新建demo.js文件,

​ demo.js:

const state = {
    moduleTip: '欢迎使用Vuex模块',
};

const getters = {
    moduleTip: state => state.moduleTip,
};

const mutations = {
    SET_MODULETIP(state, data) {
        state.moduleTip = data;
    },
};

const actions = {};

export default {
    state,
    getters,
    mutations,
    actions
}

在store文件夹下新建index.js文件,

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production';

import demo from './module/demo';
const store = new Vuex.Store({
    strict: debug,
    state: {
        tip: '欢迎使用Vuex',
    },
    getters: {
        tip: state => state.tip,
    },
    mutations: {
        SET_TIP(state, data) {
            state.tip = data;
        },
    },
    actions: {

    },
    modules: {
        demo,
    }
});

export default store;

在minxins/index.js文件写入,

import { mapGetters } from 'vuex';
export default {
    data() {
        return {
        }
    },
    computed: {
        ...mapGetters(['tip','moduleTip'])
    },
    mounted(){
    },
    methods: {
    }
}

//在view/home.uve 
//引用
<template>
    <div>
        欢迎使用Vue项目
        {{tip}}
        {{moduleTip}}
    </div>
</template>

页面展示 "欢迎使用Vue项目 欢迎使用Vuex 欢迎使用Vuex模块".

6、Reset CSS样式

在src/assets/css文件夹下新建reset .less文件,网上找一个初始化样式文件

在main.js文件写入

import 'css/base/reset.css';

7、配置文件别名

在vue.config.js文件中配置内容如下:

const path = require('path');
function resolve(dir) {
    return path.resolve(__dirname, dir)
}
module.exports = {
    configureWebpack: {
        resolve: {
            extensions: ['.js', '.vue', '.json'],
            alias: {
                '@': resolve('src'),
                'assets': resolve('src/assets'),
                'css':resolve('src/assets/css'),
                'images':resolve('src/assets/images'),
                'views': resolve('src/views'),
                'components':resolve('src/components'),
                'api':resolve('src/api'),
                'mixins':resolve('src/mixins'),
                'store': resolve('src/store'),
                'service':resolve('src/service'),
            }
        }
    },
}
//关闭source map有两个好处

//减少打包编译的时间;
//避免在生产环境中用F12开发者工具在Sources中看到源码。
//在vue.config.js文件中配置内容如下:
module.exports = {
    productionSourceMap: false,
}

//npm i Jquery -save
const webpack = require('webpack')
module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'windows.jQuery': 'jquery',
      }),
    ],
  },
}
 
 //代理 target为接口有ip(域名),api为本地使用时候前缀。
module.exports = {
  devServer: {
    host: 'localhost',
    port: '8083',
    proxy: {
      '/api': {
        // /api 表示拦截以/api开头的请求路径
        target:
          'https://www.fastmock.site/mock/fd7892a0bc009dd928228bb6dba37099/test', // 跨域的域名
        changeOrigin: true, // 是否开启跨域
        secure: false, // 如果是https接口,需要配置这个参数
        pathRewrite: {
          // 重写路径
          '^/api': '', // 把/api变为空字符
        },
      },
    },
  },
}

8.附上main.js文件

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import mixins from './mixins'
import $ from 'jquery'
import api from './api' // 导入api接口
import 'swiper/dist/css/swiper.min.css' //
import 'swiper/dist/js/swiper.min'  //
Vue.mixin(mixins)
Vue.config.productionTip = false
Vue.prototype.$api = api // 将api挂载到vue的原型上
new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app')


集合了以下两篇文章的内容,
作者:红尘炼心
链接:https://juejin.cn/post/6844903912097464334
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
作者:格子熊
链接:https://juejin.cn/post/6844903969152565261
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。