Vue:vue2.0全家桶搭建element-ui+axios+vuex+mockjs

作为一名前端人员,并且作为一名使用过vue框架的前端人员,相信都听说过vue全家桶(1.项目构建工具vue-cli、2.路由vue-router:http://router.vuejs.org、3.状态管理vuex:http://vuex.vuejs.org、4.http请求工具axios:http://www.axios-js.com/zh-cn/docs/、5.样式element-ui:https://element.eleme.cn/#/zh-CN/component/installation、6.以及有时候后台没有提供接口需要自己模拟数据请求,我经常使用的mockjs)。为了方便与大家共同交流,特将自己搭建项目的方法记录下来。

  • 初始化vue2.0项目
  • 使用elment-ui
  • 使用axios
  • 使用mockjs
  • 使用vuex

一、初始化项目

之前已经分享过如何进行vue-cli 2.0安装及项目搭建,如果忘了,则可以去查看之前博客,在这里我就直接使用脚手架安装项目;

vue init webpack vue_all  //默认安装即可,vue-router就已经安装整合到项目中
cd vue_all
npm run dev  //运行项目即可

若自己想封装组件然后注册成全局组件,在components下创建base文件夹,存放需要注册至全局的组件,有mian.js文件中写如下代码:

// 引用公共组件
let componentFiles = require.context('./components/base', false, /\.vue$/)
componentFiles.keys().map((item, index) => {
  let componentFile = item.replace(/^\.\/(.*)\.\w+$/, '$1');
  let value = componentFiles(item)
  Vue.component(`cui${componentFile}`, value.default)
})

二、element-ui

1.	npm i element-ui –save   //安装element-ui插件
2.	在main.js文件中输入以下代码:
	import ElementUI from 'element-ui'
	import 'element-ui/lib/theme-chalk/index.css'
	Vue.use(ElementUI)
3. 若想按需引入组件,则可以按照element-ui官网进行相关插件安装,官网地址:https://element.eleme.cn/#/zh-CN/component/quickstart
4. 这里只是介绍简单项目搭建,若想更加深入的了解可去官网查看

在这里插入图片描述
以上即完成element-ui的安装,参考官网给出的组件与使用方法,在页面中需要的地方调用即可。
在这里插入图片描述

三、Axios

axios是promise实现的,提到promise,首先应该想到IE不支持,所以应该先加个垫片,给IE做下兼容性处理:

npm install --save babel-polyfill  //安装es6转译组件
然后再main.js中引入 :
import 'babel-polyfill'
  1. 安装axios
npm i axios --save
  1. 为了方便项目当中对于接口的管理,我常会对axios进行二次封装:
    封装目录结构是:
    在这里插入图片描述
    index.js中的代码如下:
const context = require.context('./modules', false, /\.js$/);
const path=require("path")
let Api = {}
context.keys().map((m, k) => {
  let strFileName = m.replace(/(.*\/)*([^.]+).*/ig,"$2");
  let data=context(m).default;
  Api[strFileName]=data
}, {})

export default Api;

config.js中的代码如下:

import axios from 'axios';
// 使用element-ui Message做消息提醒
import {Message} from 'element-ui';

// 创建实例时设置配置的默认值

/**
 * 自定义实例默认值
 */
var instance = axios.create({
//   baseURL: "/api", // 因为我本地做了反向代理
  timeout: 10000,
  // responseType: "json",
  // withCredentials: true, // 是否允许带cookie这些
  // headers: {
  //   "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
  // }
});
// /api/getUserById


// 请求拦截器, 进行一个全局loading  加载,这种情况下所有的接口请求前 都会加载一个loading

/**
 * 添加请求拦截器 ,意思就是发起请求接口之前做什么事,一般都会发起加载一个loading
 * */

//  如果不想每个接口都加载loading ,就注释掉请求前拦截器,在http这个类中处理

instance.interceptors.request.use(
  config => {
    // 在发送请求之前做些什么(... 这里写你的展示loading的逻辑代码 )
    isShowLoading(false);
    // 获取token,配置请求头
    // const TOKEN = localStorage.getItem('Token')
    // 演示的token(注意配置请求头,需要后端做cros跨域处理,我这里自己前端配的跨域)
    const TOKEN = '1fd399bdd9774831baf555ae5979c66b'
    if (TOKEN) {
      // 配置请求头 token
      config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
      config.headers['Authorization'] = TOKEN;
    }
    return config;
  },
  error => {
    // 对请求错误做些什么,处理这个错误

    // 可以直接处理或者展示出去,toast show()
    console.warn(error);
    // Message({
    //     //  饿了么的消息弹窗组件,类似toast
    //     showClose: true,
    //     message: error && error.data.error.message,
    //     type: 'error'
    //   });
    Message.error(err.message)
    return Promise.reject(error);
  }
);

/**
 * 添加响应拦截器,意思就是发起接口请求之后做什么事,此时只有两种情况,
 * 要么成功,要么失败,但是不管成功,还是失败,我们都需要关闭请求之前的
 * 发起的loading,那既然要处理loading,就把loading做成全局的了,
 * 这里自定义一个处理加载loding 和关闭loading的方法,而且这个loading
 * 要不要加载,会根据外部传入的布尔值来决定,默认是false:不展示
 * */

instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    isShowLoading(false);
    console.log(response)
    // 根据你们家的后端定义请求过期后返回的参数,处理token过期问题
    // 我这个接口木有token啊,这里演示下
    // 判断
    const {
      status
    } = response.data;
    // 判断状态码401或者其它条件,不知道判断哪个的去问你家后台
    // if (Object.is(status, 401)) {
    // token过期后处理
    // 1.删除你本地存储的那个过期的token

    // 2. 跳转到登陆页(因为没有装路由,不写了,重新登陆赋值)

    //  todo...
    // }
    // 根据后端接口code执行操作
    // switch(response.data.code) {
    //处理共有的操作
    // }
    return response.data;
  },
  function (error) {
    // 对响应错误做点什么
    isShowLoading(false);
    if (error && err.response) {
      switch (err.response.status) {
        case 400:
          err.message = '错误请求'
          break;
        case 401:
          err.message = '未授权,请重新登录'
          break;
        case 403:
          err.message = '拒绝访问'
          break;
        case 404:
          err.message = '请求错误,未找到该资源'
          break;
        case 405:
          err.message = '请求方法未允许'
          break;
        case 408:
          err.message = '请求超时'
          break;
        case 500:
          err.message = '服务器端出错'
          break;
        case 501:
          err.message = '网络未实现'
          break;
        case 502:
          err.message = '网络错误'
          break;
        case 503:
          err.message = '服务不可用'
          break;
        case 504:
          err.message = '网络超时'
          break;
        case 505:
          err.message = 'http版本不支持该请求'
          break;
        default:
          err.message = `连接错误${err.response.status}`
      }
    } else {
      err.message = "连接到服务器失败"
    }
    Message.error(err.message)
    return Promise.reject(error);
  }
);

// 如果与你配合的ui中,有loading组件的话,你直接用它的就可以了

// to do...
/**
 * 是否开启loading
 * @param {*} payload { type:Boolean }
 */

function isShowLoading(payload) {
  // 获取dom节点
  const loading = document.getElementById('loading');
  payload ? loading.style.display = 'block' : loading.style.display = 'none';

}

/**
 * 使用es6中的类,进行简单封装
 */

let http = {
  // 使用async ... await
  //   static async get(url, params, isShow = false) {
  //     console.log(params)
  //     isShowLoading(isShow)
  //     return await instance.get(url, {
  //       params
  //     })
  //   }
  //   static async post(url, params, isShow = false) {
  //     console.log(params)
  //     isShowLoading(isShow)
  //     return await instance.post(url, params);
  //   }
  // get请求
  get(url, param = {}, isShow = false) {
    isShowLoading(isShow)
    return new Promise((resolve, reject) => {
      instance.get(url, {
          params: param
        })
        .then(res => {
          resolve(res)
        }, err => {
          reject(err)
        })
    })
  },
  // post请求
  post(url, param = {}, isShow = false) {
    isShowLoading(isShow)
    return new Promise((resolve, reject) => {
      instance.post(
        url,
        param
      ).then(res => {
        resolve(res)
      }, err => {
        reject(err)
      })
    })
  },
  // put请求
  put(url, param = {}, isShow = false) {
    isShowLoading(isShow)
    return new Promise((resolve, reject) => {
      instance.put(url, param)
        .then(response => {
          resolve(response)
        }, err => {
          reject(err)
        })
    })
  },
  // delete
  delete(url, param = {}, isShow = false) {
    isShowLoading(isShow)
    return new Promise((resolve, reject) => {
      instance.delete(url, param)
        .then(response => {
          resolve(response)
        }, err => {
          reject(err)
        })
    })
  }
}


export default http;

modules文件夹下是各个模块的接口文件,goods.js文件是我写的一个demo文件,内容如下:

import http from "../config";
export default {
    getGoods(params={}){
        return http.get("/goods/getGoods",params)  
    }
}

二次封装完成后,在main.js文件中引入,将接口挂载到vue的原型方法上:

在这里插入图片描述
在需要发送请求的页面调用vue的原型方法即可:
在这里插入图片描述

四、MockJs

  1. npm install mockjs --save-dev //安装mock;
  2. src文件夹下创建一个mock文件夹,创建index.js文件,文件内容如下:
const Mock = require('mockjs');
Mock.mock('/goods/getGoods', 'get', () => {
  return {
    status: '0',
    msg: '',
    data: [{
      _id:1,
      productId: "201710003",
      productName: "平衡车",
      salePrice: 1999,
      productImage: "pingheng.jpg",
      productUrl: ""
    }]
  }
});

  1. main.js文件中引入
    在这里插入图片描述

五、vuex

vuex是使用vue中必不可少的一部分,基于父子、兄弟组件,我们传值可能会很方便,但是如果是没有关联的组件之间要使用同一组数据,就显得很无能为力,那么vuex就很好的解决了我们这种问题,它相当于一个公共仓库,保存着所有组件都能共用的数据。一般情况下,vuex写在一个文件当中,但是当项目比较大的时候,容易造成数据耦合,为了方便维护,就需要将数据模块化。这里我介绍的模块化的封装:

目录结构如下:
在这里插入图片描述
index.js文件内容如下:

import Vue from 'vue';
import Vuex from 'vuex';
import getters from './getters'

Vue.use(Vuex);

const modulesFiles = require.context('./modules', false, /\.js$/)

const modules = modulesFiles.keys().reduce((modules, modulePath) => {
 
  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;

getters.js文件内容如下:

const getters = {
    //getters 文件为导出state里面的数据,导出格式state => state.Login.userCode ,
    //表示store/modules/Login/Login.js里面的state里的变量userCode
    //如果不是很懂,下面会介绍在state存数据
    goodsList : state => state.goods.goodsList ,
  }
  export default getters

mutations_type.js文件内容如下:


export const GOODS_GET = 'GOODS_GET';
export const GOODS_ADD = 'GOODS_ADD';

modules文件夹是vuex存放的各个模块的相关状态:

import * as mutationTypes from "../mutation_types.js"
const state={
    goodsLength:0,
    goodsList:[],  //初始化一个userCode变量
};
// 赋值方法    
const mutations={
     [mutationTypes.GOODS_GET]: (state, device) => {//如何变化userCode,插入device
        state.goodsList = device;
        state.goodsLength=device.length?device.length:0;
      },
 };
 //调用方法
const actions={
    getGoods({ commit }, {$net,params}) {//触发mutations里面的userCodeChang ,传入数据形参device 对应到device
        return new Promise((resolve,reject)=>{
            $net(params).then(res=>{
                commit(mutationTypes.GOODS_GET, res.data)
                resolve(res)
            }).catch(err=>{
                reject(err)
            })
        })
      },
};
export default {
     namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名
     state,
     mutations,
     actions
}

mian.js文件中引入

// vuex的引入
import store from './store'
new Vue({
  el: '#app',
  router,
  store,
  components: {
    App
  },
  template: '<App/>'
})

在页面当中需要调用的地方,进行调用:

this.$store
      .dispatch("goods/getGoods", {
        $net: this.$api.goods.getGoods,
        params: []
      })
      .then(res => {
        debugger;
      });

注意:
ie浏览器下[vuex] vuex requires a Promise polyfill in this browser.报这个错
需要安装babel-polyfill,
然后在webpack.base.conf.js中的entry配置[‘babel-polyfill’,’./src/main.js’]

以上只是将vue全家桶统一整合,方便开发vue项目使用,一人技短,众人技长,欢迎大家共同交流,后面遇到问题了,我也会不断修改此文档!

猜你喜欢

转载自blog.csdn.net/weixin_44599809/article/details/104145173