vue-cli搭建项目

☼ 注:笔者的文章是根据自己当前项目做的笔记,具体应用请参照自己实际项目情况

1、创建应用
npm install -g @vue/cli-service-global
vue create my-vue-project
cd my-vue-project
npm run serve
2、配置axios及proxy跨域代理

⑴ 安装http-proxy-middleware

npm install http-proxy-middleware --save

⑵ 在根目录新建一个vue.config.js文件

module.exports = {
    devServer: {
        proxy: {
            '/c': {
                target: 'https://10.8.20.25',
                changeOrigin: true,
                secure: false
            },
            '/v1': {
                target: 'https://10.8.20.25',
                changeOrigin: true,
                secure: false
            }
        }
    }
}

⑶ 安装axios

npm install axios --save

⑷ 在main.js中引用

import axios from 'axios'

Vue.prototype.axios = axios.create({
  baseURL: window.location.origin
})

⑸ 在业务中使用

// 开发环境或预发布环境
const apiUrl = window.location.origin.includes('cms') ? 'v1/web/estatewebadmin' : 'clife-estate-api-web-admin'
this.url = `/${apiUrl}/estate/merchant/detail/${this.id}.do`
axios.post(this.url, { carNo: this.carNo }).then(res => console.log(res)).catch(err => console.log(err))
3、配置基本路径,解决打包首页空白问题

在vue.config.js文件中,添加以下配置

module.exports = {
    publicPath: './', //基本路径,解决打包空白问题
}
4、配置rem方案

⑴ 在src目录下新建一个utils目录(用来放置工具函数),在utils目录下新建一个rem.js文件

/*设置REM方案*/
remFont()
window.addEventListener('resize', function () {
    remFont();
    // console.log(window.innerWidth)
});
function remFont() { 
    var html = document.getElementsByTagName('html')[0];
    var width = window.innerWidth;
    var font_Size = 0;
    if(width >= 320 && width <= 1024){
      font_Size = 100/375 * width;
    }else if(width<320){
      font_Size = 100/375 * 320;
    }else{
      font_Size = 100/375 * 1024;
    }
    html.style.fontSize = font_Size + 'px';
}

⑵ 在main.js文件中,引入rem.js

import './utils/rem'

⑶ 安装postcss-px2rem

npm i postcss-px2rem --save

⑷ 在vue.config.js中配置

const px2rem = require('postcss-px2rem')
const postcss = px2rem({
    remUnit: 100   //基准大小 baseSize,需要和rem.js中相同
})
module.exports = {
    css: {
        loaderOptions: {
            postcss: {
                plugins: [
                    postcss
                ]
            }
        }
    }
}
5、引入element-ui,配置按需加载

⑴ 安装element-ui

npm i element-ui --save

⑵ 在babel.config.js中配置

module.exports = {
  presets: [
    '@vue/app'
  ],
  plugins: [["component",
    {
      "libraryName": "element-ui",
      "styleLibraryName": "theme-chalk"
    }
  ]]
}

⑶ 在main.js中引入

import { Button, Message } from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(Button)
Vue.component(Message.name, Message)
Vue.prototype.$message = Message
6、引入阿里iocn

⑴ 在src文件夹下新建一个assets文件夹,再新建一个iconfont文件夹,把阿里图库生成的文件放到文件夹下
⑵ 在main.js中引入

import '@/assets/iconfont/iconfont.css'
7、引入vue-echarts图表库

⑴ 安装vue-echarts

npm install echarts vue-echarts --save

⑵ 在vue.config.js中配置

module.exports = {
    transpileDependencies: [
        'vue-echarts',
        'resize-detector'
    ]
}

⑶ 在main.js中引入

import ECharts from 'vue-echarts'
import chinaJson from 'echarts/map/json/china.json'
import 'echarts/lib/chart/map'
import 'echarts/lib/component/geo'

ECharts.registerMap('china', chinaJson)
Vue.prototype.$echarts = ECharts
Vue.component('v-chart', ECharts)

⑷ 使用

8、配置路由

⑴ 安装vue-router

npm install vue-router --save

⑵ 在src目录下新建一个router.js文件

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

Vue.use(VueRouter)

const baseUrl = './pages/'
const communityUrl = './pages/community/components/'

const routes = [
    { path: '/', redirect: '/dataCenter' },
    { path: '/dataCenter', component: () => import(`${baseUrl}dataCenter`) },
    { path: '/community', component: () => import(`${baseUrl}community`), children: [
        {
            path: '/',
            component: () => import(`${communityUrl}guardView`)
        }, {
            path: 'parkGuard',
            component: () => import(`${communityUrl}parkGuard`)
        }
    ] }
]

export const router = new VueRouter({
    routes
})
// 登录状态重定向
router.beforeEach((to, from, next) => {
    if (!loginStatus && to.path !== '/login') {
        next('/login')
    } else {
        next()
    }
})

⑶ 在main.js中挂载

import { router } from './routes'

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
9、配置vuex

⑴ 安装vuex

npm i vuex --save

⑵ 在src目录下新建一个store文件夹,再新建一个index.js文件

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
export default new Vuex.Store({
    state: {
        isCollapse: false
    },
    mutations: {
        toCollapse (state, bool) {
            state.isCollapse = bool
        }
    }
})

⑶ 在业务代码中使用



10、结合axios拦截器和vuex模块化封装管理请求
⑴ 在src下新建一个api目录,用来统一管理接口地址

在api目录下新建一个config.js,配置baseURL

const HOST = window.location.origin

const apiUrl = HOST.includes('cms') ? '/v1/web/estatewebadmin' : '/clife-estate-api-web-admin'

export default HOST + apiUrl

再新建一个axios.js配置拦截器

import axios from 'axios'
import qs from 'qs'
import baseURL from './config'
import vm from '@/main'

const Axios = axios.create({
    baseURL,
    withCredentials: true, // 是否允许跨域请求携带cookie
    responseType: 'json', // 服务器响应的数据类型, 默认json
    headers: {
        'Content-Type': 'application/json;charset=UTF-8' // 请求头content-type类型, 默认json
    }
})

let loadingInstance = null

const loadingOn = loading => {
    if (!loadingInstance && loading !== false) {
        loadingInstance = vm.$loading({ target: '.el-main>div' })
    }
}

const loadingOff = () => {
    loadingInstance && setTimeout(() => {
        loadingInstance.close()
        loadingInstance = null
    }, 500)
}

// 请求拦截器
Axios.interceptors.request.use(
    config => {
        // 检测网络
        if (!navigator.onLine){
            vm.$message.error('当前网络已断开,请联网重试!')
            return
        }
        // 针对post请求和get请求处理
        if (config.method === 'post') {
            // 可以把自定义的信息和参数一起传过来,再做统一处理
            const { headers, responseType, param, loading } = config.data || {}
            // 开启loading
            loadingOn(loading)
            // 如果重写了headers, 则替换
            if (headers) {
                config.headers = headers
            }
            // 如果重写了responseType, 则替换
            if (responseType) {
                config.responseType = responseType
            }
            // 如果请求头Content-Type为表单形式,则通过qs插件把参数做相关处理
            config.data = config.headers['Content-Type'] === 'application/x-www-form-urlencoded' ? qs.stringify(param) : param
        } else {
            // 开启loading
            loadingOn(config.loading)
            // 参数
            config.params = config.param
        }
        // 取消请求
        config.cancelToken = vm.$store.state.Root.source.token

        return config
    },
    err => {
        loadingOff()
        return Promise.reject(err)
    }
)

Axios.interceptors.response.use(
    response => {
        loadingOff()
        const { data, config } = response || {}
        // code为0,返回响应数据
        if (+data.code === 0) {
            return data
        }
        // 文件流格式
        if (config.responseType === 'blob') {
            // message提示后台返回json格式的错误信息
            if (data.type === 'application/json') {
                let reader = new FileReader()
                reader.onload = e => JSON.parse(e.target.result).msg
                reader.readAsText(data)
                return
            }
            // 需要针对IE做兼容,所以直接返回blob对象,再针对不同浏览器做url转化处理
            return  new Blob([data], { type: data.type })
        }

        // 后台返回用户未登录或用户不存在
        if (+data.code === 100010110 || +data.code === 100021401) {

            return
        }

        // code非0
        vm.$message(data.msg)
        return Promise.reject(data)


    },
    err => {
        loadingOff()
        if (!err.response) {
            // 如果是取消请求导致的错误,则不做msg提示
            return Promise.reject(err)
        }
        vm.$message.warning('服务调用失败,请稍后重试!')
        return Promise.reject(err)
    }
)

export default Axios

然后按模块划分接口,比如 /api/setting/basic/project.js

import axios from '@/api/axios'

export default {
    queryProject: data => axios.post('/estate/project/queryProject.do', data)
}
⑵ 在src目录下新建一个store目录, 把接口请求方法和数据处理统一放在vuex里完成

store目录下新建一个root.js,用来处理全局方法和数据,比如取消axios请求或收缩菜单等

export default {
    namespaced: true,
    state: {
        isCollapse: false,
        source: { token: null, cancel: null }
    },
    mutations: {
        // 改变侧边菜单伸缩状态
        toCollapse: (state, bool) => {
            state.isCollapse = bool
        },
        // 取消axios请求
        soureToken: (state, source) => {
            state.source = source
        }
    }
}

再按模块划分不同的modules,和api下的模块保持一致,比如store/setting/basic/project.js

import Project from '@/api/setting/basic/project'

export default {
    namespaced: true,
    state: {
        projectRecord: [],
        totalRows: 0
    },
    actions: {
        queryProject: async ({ state }, params) => {
            const data = await Project.queryProject(params)
            try {
                state.projectRecord = data.data.record
                state.totalRows = data.data.totalRows
            } catch (err) {
                return Promise.reject(err)
            }
        }
    },
    getters: {
        projectList: state => {
            return state.projectRecord.map(item => ({
                id: item.projectId,
                name: item.projectName
            }))
        }
    }
}

然后在setting下新建一个index.js引入各个小模块的modules

import Project from './basic/project'

export default {
    namespaced: true,
    modules: {
        Project
    }
}

最后在store下新建一个index.js引入各个大模块的modules

import Vue from 'vue'
import Vuex from 'vuex'

import Root from './root'
import Setting from './setting'

Vue.use(Vuex)

export default new Vuex.Store({
    modules: {
       Root, Setting
   }
})
⑶ 在页面调用请求,获取处理后的数据结果
import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
    computed: {
        ...mapState('Root', ['source']),
        ...mapState('Setting/Project', ['projectRecord']),
        ...mapGetters('Setting/Project', ['projectList']),
    },
    methods: {
        ...mapMutations('Root', ['soureToken']),
        handleClick() {
            this.source.cancel && this.source.cancel()
            this.soureToken(this.$axios.CancelToken.source())
            this.queryProject()
        },
        queryProject() {
            this.$store.dispatch('Setting/Project/queryProject', {
                param: {
                    data: {
                        project: {
                            projStatus: 1,
                            ...this.formValue
                        },
                        pager: {
                            pageRows: 10,
                            pageIndex: 1,
                            paged: true
                        },
                        orderBy: {
                            orderColumn: 'createTime',
                            orderType: 'desc'
                        }
                    }
                },
                // loading: false
            }).then(() => {
                console.log(this.projectRecord)
            })
        }
    },
    created() {
        this.queryProject()
    }
}

你可能感兴趣的:(vue-cli搭建项目)