您好,登錄后才能下訂單哦!
新建項目的時候創建合理的目錄結構便于后期的維護是很重要
環境:vue、webpack
目錄結構:
項目子目錄結構
子目錄結構都差不多,主要目錄是在src下面操作
src目錄結構
src/common 目錄
主要用來存放公共的文件
src/components
主要用來存放公共的組件
src/config
用來存放配置文件,文件目錄如下
src/config/index.js 配置目錄入口文件
import api from './website' // 當前平臺 export const HOST_PLATFORM = 'WEB' // 當前環境 export const NODE_ENV = process.env.NODE_ENV || 'prod' // 是否開啟監控 export const MONITOR_ENABLE = true // 路由默認配置 export const ROUTER_DEFAULT_CONFIG = { // mode: 'history', waitForData: true, transitionOnLoad: true } // axios 默認配置 export const AXIOS_DEFAULT_CONFIG = { timeout: 20000, maxContentLength: 2000, headers: {} } // vuex 默認配置 export const VUEX_DEFAULT_CONFIG = { strict: process.env.NODE_ENV !== 'production' } // API 默認配置 export const API_DEFAULT_CONFIG = { baseURL: api, // 圖標地址 imgUrl: `${api}/api/system/icon.do?name=`, // 菜單圖標地址 menuImgUrl: `${api}/`, dicomUrl: `${api}/testDICOM/`, // 請求參數格式 json/form-data isJSON: true, // 請求加載效果, 支持element-ui所有參數配置 loading: { text: '加載中' }, // 是否開啟mock mock: false, // 是否開啟debug debug: false, // 定義全局變量 ippid: 'test' } export const CONSOLE_REQUEST_ENABLE = true // 開啟請求參數打印 export const CONSOLE_RESPONSE_ENABLE = false // 開啟響應參數打印 export const CONSOLE_ROUTER_ENABLE = false // 打印路由信息 export const CONSOLE_MONITOR_ENABLE = true // 監控記錄打印
src/config/website.js 動態配置ip文件
/** * 動態匹配api接口地址 */ const website = [ { web: 'localhost:9000', api: '//192.168.0.170:8080/xhhms', env: 'dev' }, { web: '127.0.0.1:8000', api: '//192.168.0.149:8080/xhhms', env: 'dev' } ] let matchApi = website.filter(item => new RegExp(item.web).test(location.href)) if (matchApi.length > 1) { console.error(`${location.href}: 該站點映射了多個api地址${matchApi.map(item => item.api).join(',')},默認選取第一個匹配項`) } export default matchApi[0].api
src/config/interceptors目錄
攔截器配置
src/config/interceptors/axios.js
import router from 'Plugins/router' import { CONSOLE_REQUEST_ENABLE, CONSOLE_RESPONSE_ENABLE } from '../index.js' import { Toast, Indicator } from 'mint-ui' import store from 'Store' import Qs from 'qs' /** * 請求攔截器(成功) * @param {object} request 請求對象 * @return {object} request 處理后的請求對象 */ export function requestSuccessFunc(request) { CONSOLE_REQUEST_ENABLE && console.info('requestInterceptorFunc', `url: ${request.url}`, request) // 自定義請求攔截邏輯,可以處理權限,請求發送監控等 // console.log(request.url) // if (localStorage.getItem('token') === null && request.url.indexOf('login') === -1) { // console.log('[*] 當前用戶沒有登錄!!') // router.push('/login') // return false // } // 登錄token攜帶 request.headers['X-AUTH-TOKEN'] = localStorage.getItem('token') // 兼容性寫法,如果request里邊沒得site_code 就用全局site_code let publicParams = { orgCode: sessionStorage.getItem('orgCode'), menuId: sessionStorage.getItem('currentMenuId') } /** * @author wucheshi * @time 2018-08-13 * @description 需求變動,網站code從本地siteCodeList 這個字段來 */ let siteCodeList = sessionStorage.getItem('siteCodeList') // !request.data.site_code && (publicParams = Object.assign({ site_code: store.state.currentSite.code }, publicParams)) !request.data.site_code && !request.noSiteCode && (publicParams = Object.assign({ site_code: siteCodeList }, publicParams)) /** * @author wucheshi * @time 2018-08-13 * @description 單表操作接口不需要傳遞sitecode */ // 兼容單表操作傳遞site_code // if (request.data.condition && !request.noSiteCode) { // console.log(siteCodeList, 11111) // if (request.data.condition.findIndex(item => item.name === 'site_code') === -1) { // request.data.condition.push({ name: 'site_code', value: siteCodeList }) // } else { // request.data.condition.find(item => item.name === 'site_code').value = siteCodeList // } // } let newData // 判斷是否是formdata類型 if (Object.prototype.toString.call(request.data) === '[object FormData]') { // 合并formdata格式公共參數 Object.keys(publicParams).forEach(key => { request.data.append(key, publicParams[key]) }) newData = request.data } else { // 合并公共參數 newData = Object.assign(request.data, publicParams) // 判斷是否采用json格式提交參數 !request.isJSON && (newData = Qs.stringify(newData)) } // 不同提交參數方式給不同的字段賦值 if (request.method.toUpperCase() === 'POST') { request.data = newData } else if (request.method.toUpperCase() === 'GET') { request.params = newData } // 加載效果 request.loading && Indicator.open(request.loading) // 輸出請求數據 CONSOLE_REQUEST_ENABLE && console.info(`%c 請求接口地址:${request.url} 請求接口名稱:${request.desc} 請求參數JSON: ${JSON.stringify(request.data, '', 2)} `, 'color: #f60') return request } /** * 請求攔截器(失敗) * @param {object} requestError 請求報錯對象 * @return {object} 返回promise對象 */ export function requestFailFunc(requestError) { // 自定義發送請求失敗邏輯,斷網,請求發送監控等 return Promise.reject(requestError) } // 你就是個sx /** * 響應攔截器(成功) * @param {object} responseObj 響應對象 */ export function responseSuccessFunc(responseObj) { // 自定義響應成功邏輯,全局攔截接口,根據不同業務做不同處理,響應成功監控等 // console.log(typeof (responseObj.data)) // // 判斷string是否包含 java字段 說明error // if (typeof (responseObj.data) === 'string' || responseObj.data.indexOf('java') !== -1) { // console.log('[*] token錯誤') // this.$router.push('/login') // } // 加載效果 Indicator.close() // 響應對象 let resData = typeof responseObj.data === 'object' ? responseObj.data : JSON.parse(responseObj.data) let { status, message } = resData // 輸出響應體 CONSOLE_RESPONSE_ENABLE && console.info(responseObj) // 輸出返回JSON數據 CONSOLE_RESPONSE_ENABLE && console.info(`%c 響應接口地址: ${responseObj.config.url} 響應接口描述: ${responseObj.config.desc} 響應數據JSON: ${JSON.stringify(resData, '', 2)} `, 'color: blue') // 自定義處理業務邏輯 if (responseObj.config.customErrorHandle) { return resData } // 統一邏輯處理 switch (+status) { case 0: // 常規錯誤 Toast(message) break case 1: // 如果業務成功,直接進成功回調 return resData case 401: // 登錄失效 store.commit('DELETE_USER_INFO') router.push({ path: '/login', redirect: router.app._route.fullPath }) Toast(message) break default: // 業務中還會有一些特殊 code 邏輯,我們可以在這里做統一處理,也可以下方它們到業務層 // !responseObj.config.noShowDefaultError && GLOBAL.vbus.$emit('global.$dialog.show', resData.msg); return Promise.reject(resData) } } /** * 響應攔截器(失敗) * @param {object} responseError 響應報錯對象 * @return {object} 返回promise對象 */ export function responseFailFunc(responseError) { // 響應失敗,可根據 responseError.message 和 responseError.response.status 來做監控處理 // ... // 加載效果 Indicator.close() // 錯誤碼處理 // console.log(responseError.response) if (typeof (responseError.response) === 'undefined') { return false } switch (responseError.response.status) { case 401: console.error('401錯誤') store.commit('DELETE_USER_INFO') router.push({ path: '/login', redirect: router.app._route.fullPath }) store.state.user.username && Toast('登錄超時') break case 403: console.error('403錯誤') router.push({ path: '/403' }) break case 500: console.error('500錯誤') router.push({ path: '/500' }) break } return Promise.reject(responseError) }
src/config/interceptors/index.js
import {requestSuccessFunc, requestFailFunc, responseSuccessFunc, responseFailFunc} from './axios' import {routerBeforeEachFunc} from './router' export default { requestSuccessFunc, requestFailFunc, responseSuccessFunc, responseFailFunc, routerBeforeEachFunc }
src/config/interceptors/router.js
/** * 路由beforeach攔截器 */ import {CONSOLE_ROUTER_ENABLE} from '../index' export function routerBeforeEachFunc (to, from, next) { // 打印路由數據 CONSOLE_ROUTER_ENABLE && console.info(`%c 路由to: fullPath: ${to.fullPath}, query: ${JSON.stringify(to.query, '', 2)}, meta: ${JSON.stringify(to.meta, '', 2)} 路由from: fullPath: ${from.fullPath} `, 'color: green;font-weight: bold;') // 登錄狀態驗證 if (to.meta.requireLogin) { (localStorage.getItem('token')) ? next() : next({path: '/login', query: { redirect: to.fullPath }}) return } // 路由重定向 // if (to.query.route) { // let newQuery = Object.assign({}, to.query) // delete newQuery.route // next({ // path: `${to.query.route.indexOf('/') === 0 ? '' : '/'}${to.query.route}`, // query: newQuery // }) // return // } // console.log(to, from) // 防止死循環 if (to.fullPath === from.fullPath) return // 404錯誤 if (!to.name) { next('/404') return } next() }
src/locale目錄
國際化配置,這個百度一下就行
src/mixin目錄
引入配置文件,定義部分全局變量,名字自己定義
src/mixin/index.js
import Vue from 'vue' import { API_DEFAULT_CONFIG } from 'Config' Vue.mixin({ computed: { // 圖片根地址 imgUrl () { return API_DEFAULT_CONFIG.imgUrl }, baseUrl () { return API_DEFAULT_CONFIG.baseURL }, ippid () { return API_DEFAULT_CONFIG.ippid }, dicomUrl () { return API_DEFAULT_CONFIG.dicomUrl } } })
src/pages目錄
主要的頁面文件,目錄結構主要按照層次結構來分。
ex:該頁面主要跟醫生相關,主要包含云搜索(cloud)、個人中心(myCenter)、工作中心(workCenter)、搜索(serach)、同理子層級也同樣區分、目錄結構如下
至于公共頁面可以放在common文件目錄下,也可以擺在文件夾外面。
src/plugins目錄
也是配置文件目錄
src/plugins/api.js
import axios from './axios' import _pick from 'lodash/pick' import _assign from 'lodash/assign' import _isEmpty from 'lodash/isEmpty' import { assert } from 'Utils/tools' import { API_DEFAULT_CONFIG } from 'Config' import API_CONFIG from 'Service/api' class MakeApi { constructor (options) { this.api = {} this.options = Object.assign({}, options) this.apiBuilder(options) } apiBuilder ({ config = {} }) { Object.keys(config).map(namespace => { this._apiSingleBuilder({ namespace, config: config[namespace] }) }) } _apiSingleBuilder ({ namespace, config = {} }) { config.forEach(api => { const { methodsName, desc, params, method, path, mockPath } = api let { mock, mockBaseURL, baseURL, debug, isJSON, loading } = this.options let url = mock ? (mockBaseURL + mockPath) : (baseURL + path) debug && assert(methodsName, `${url} :接口methodsName屬性不能為空`) debug && assert(url.indexOf('/') === 0, `${url} :接口路徑path,首字符應為/`) Object.defineProperty(this.api, methodsName, { value (outerParams, outerOptions) { let allowtParam = (outerOptions && outerOptions.allowParams) || {} let _data = (outerOptions && outerOptions.isFormData) ? outerParams : _isEmpty(outerParams) ? params : _pick(_assign({}, params, outerParams), Object.keys(Object.assign(params, allowtParam))) return axios(_assign({ url, desc, method, isJSON, loading }, outerOptions, { data: _data })) } }) }) } } export default new MakeApi({ config: API_CONFIG, ...API_DEFAULT_CONFIG })['api']
src/plugins/axios.js
import axios from 'axios' import {AXIOS_DEFAULT_CONFIG} from 'Config/index' import {requestSuccessFunc, requestFailFunc, responseSuccessFunc, responseFailFunc} from 'Config/interceptors/axios' let axiosInstance = {} axiosInstance = axios.create(AXIOS_DEFAULT_CONFIG) // 注入請求攔截 axiosInstance .interceptors.request.use(requestSuccessFunc, requestFailFunc) // 注入失敗攔截 axiosInstance .interceptors.response.use(responseSuccessFunc, responseFailFunc) export default axiosInstance
src/plugins/inject.js
import axios from './axios' import api from './api' // GLOBAL.ajax = axios export default { install: (Vue, options) => { Vue.prototype.$api = api Vue.prototype.$ajax = axios // 需要掛載的都放在這里 } }
src/plugins/router.js
import Vue from 'vue' import Router from 'vue-router' import ROUTES from 'Routes' import {ROUTER_DEFAULT_CONFIG} from 'Config/index' import {routerBeforeEachFunc} from 'Config/interceptors/router' Vue.use(Router) // 注入默認配置和路由表 let routerInstance = new Router({ ...ROUTER_DEFAULT_CONFIG, routes: ROUTES }) // 注入攔截器 routerInstance.beforeEach(routerBeforeEachFunc) export default routerInstance
src/router目錄
路由配置文件目錄,同理按照頁面的層次結構來,結構如下
我們來看src/router/index.js 和 src/common/index.js 即可
src/common/index.js
const routes = [ { path: '/login', name: 'Login', component: () => import('Pages/login'), meta: { require: true, title: '登錄' } }, { path: '/register', name: 'register', component: () => import('Pages/register'), meta: { require: true, title: '注冊' } }, { path: '/404', name: '404', component: () => import('Pages/error/404.vue'), meta: { require: true, title: '404' } }, { path: '/500', name: '500', component: () => import('Pages/error/500.vue'), meta: { require: true, title: '500' } }, { path: '/403', name: '403', component: () => import('Pages/error/403.vue'), meta: { require: true, title: '403' } } ] export default routes
src/router/index.js
import common from './common' import doctor from './doctor' import patient from './patient' import test from './test' const route = [ { path: '/', redirect: '/login' }, { path: '/checkrecord', name: 'checkrecord', component: () => import('Pages/checkrecord.vue'), meta: { require: true, title: '檢查記錄' } }, { path: '/report', name: 'report', component: () => import('Pages/report.vue'), meta: { require: true, title: '心電圖報告' } }, { path: '/opinion', name: 'opinion', component: () => import('Pages/opinion.vue'), meta: { require: true, title: '意見' } }, { path: '/bind', name: 'bind', component: () => import('Pages/bind.vue'), meta: { require: true, title: '綁定' } }, ...common, ...doctor, ...patient, ...test ] export default route
把所有的路由文件掛載進去。
src/service 目錄
接口配置文件目錄,根據頁面來定義文件
同理我們只看src/service/api/index.js 和src/service/api/login.js、src/pages/login/index.vue以及頁面如何調用接口即可。
src/service/api/login.js
先定義好login接口
const login = [ { methodsName: 'loginByPhone', // 方法名 method: 'POST', desc: '登錄', path: '/rest/app/login', // 接口路徑 mockPath: '/rest/app/login', params: { // 參數配置 這里需要注意,只有配置的這些參數才能通過接口,所以需要傳遞的參數都要在這里配置 phone: 1, password: 2, code: 3, codeid: '', clientid: '' } }, { methodsName: 'login', method: 'POST', desc: '登錄', path: '/rest/interfacesLoginController/login', mockPath: '/rest/interfacesLoginController/login', params: { username: 1, password: 2, code: 3, codeid: '', clientid: '' } }, { methodsName: 'checkcode', method: 'POST', desc: '驗證提取碼', path: '/rest/app/medical/checksharecode', mockPath: '/rest/app/medical/checksharecode', params: { sharecode: '', id: '' } }, { methodsName: 'getCode', method: 'POST', desc: '獲取驗證碼', path: '/rest/interRandomCodeController/gererateRandomCode', mockPath: '', params: { } }, { methodsName: 'getPublicKey', method: 'POST', desc: '獲取公鑰', path: '/rest/interRandomCodeController/clientIdAndPublicKey', mockPath: '', params: { } } ] export default login
src/service/api/index.js
掛載所有定義的接口文件
import login from './login' import workcenter from './workcenter' import detail from './detail' import register from './register' import doctorpc from './doctorpc' import patientpc from './patientpc' import checklist from './checklist' export default { login, workcenter, detail, register, doctorpc, patientpc, checklist }
src/pages/login/index.vue
this.$api.login( params).then(data => { }) // 這樣調用登陸接口 this.$api.方法名(參數).then(res=>{}) // 方法名定義不能重名
其它目錄
這些目錄還是包含很多東西,用戶的信息保存,主體,工具函數這些,就不多說了。
對于項目的維護還是需要看重,后期維護方便也便于管理。
總結
以上所述是小編給大家帶來的Vue+webpack項目配置便于維護的目錄結構的相關知識,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。