本文主要總結了在開發vue項目中的一些實踐經驗和踩過的一些坑,後續會接着更新,便於後期覆盤,但願也對你有所幫助vue
問題描述:webpack
遇到動態路由如:/page/:id
從/page/1 切換到 /page/2 發現頁面組件沒有更新ios
解決方式:
給<router-view :key="key">增長一個不一樣:key值,這樣vue就會識別這是不一樣的
<router-view :key="key"></router-view> ... computed:{ key(){ return this.$route.path + Math.random(); } }
問題描述:
在a頁面寫一個定時器,每秒鐘打印一次,而後跳轉到b頁面,此時能夠看到,定時器依然在執行。
推薦的解決方式:
經過$once這個事件偵聽器器在定義完定時器以後的位置來清除定時器。github
const timer = setInterval(() => { // 定時器操做 }, 1000) // 經過$once來監聽定時器,在beforeDestroy鉤子能夠被清除。 this.$once('hook:beforeDestroy', () => { clearInterval(timer); })
1.使用resolve => require(['./ComponentA'], resolve),方法以下:web
const ComponentA = resolve => require(['./ComponentA'], resolve)
const ComponentA = () => import('./ComponentA')
組件之間的通訊方案:vuex
實現細節可參考:https://m.jb51.net/article/167304.htmvue-cli
<button @click = 「fun($event)」>點擊</button> ... methods: { fun(e) { // e.target 是你當前點擊的元素 // e.currentTarget 是你綁定事件的元素 #得到點擊元素的前一個元素 e.currentTarget.previousElementSibling.innerHTML #得到點擊元素的第一個子元素 e.currentTarget.firstElementChild # 得到點擊元素的下一個元素 e.currentTarget.nextElementSibling # 得到點擊元素中id爲string的元素 e.currentTarget.getElementById("string") # 得到點擊元素的string屬性 e.currentTarget.getAttributeNode('string') # 得到點擊元素的父級元素 e.currentTarget.parentElement # 得到點擊元素的前一個元素的第一個子元素的HTML值 e.currentTarget.previousElementSibling.firstElementChild.innerHTML } },
/* 日期相關 dateFormater:格式化時間 timestampToTime * */ function dateFormater(formater, t){ let date = t ? new Date(t) : new Date(), Y = date.getFullYear() + '', M = date.getMonth() + 1, D = date.getDate(), H = date.getHours(), m = date.getMinutes(), s = date.getSeconds(); return formater.replace(/YYYY|yyyy/g,Y) .replace(/YY|yy/g,Y.substr(2,2)) .replace(/MM/g,(M<10?'0':'') + M) .replace(/DD/g,(D<10?'0':'') + D) .replace(/HH|hh/g,(H<10?'0':'') + H) .replace(/mm/g,(m<10?'0':'') + m) .replace(/ss/g,(s<10?'0':'') + s) } // dateFormater('YYYY-MM-DD HH:mm', 1580787420000)//==> "2020-02-04 11:37" // dateFormater('YYYYMMDDHHmm', new Date()) //==> 201906261830 /* 獲取Url參數,返回一個對象 * */ function GetUrlParam(){ let url = document.location.toString(); let arrObj = url.split("?"); let params = Object.create(null) if (arrObj.length > 1){ arrObj = arrObj[1].split("&"); arrObj.forEach(item=>{ item = item.split("="); params[item[0]] = item[1] }) } return params; } // ?a=1&b=2&c=3 ==> {a: "1", b: "2", c: "3"} //toFullScreen:全屏 function toFullScreen(){ let elem = document.body; elem.webkitRequestFullScreen ? elem.webkitRequestFullScreen() : elem.mozRequestFullScreen ? elem.mozRequestFullScreen() : elem.msRequestFullscreen ? elem.msRequestFullscreen() : elem.requestFullScreen ? elem.requestFullScreen() : alert("瀏覽器不支持全屏"); } //exitFullscreen:退出全屏 function exitFullscreen(){ let elem = parent.document; elem.webkitCancelFullScreen ? elem.webkitCancelFullScreen() : elem.mozCancelFullScreen ? elem.mozCancelFullScreen() : elem.cancelFullScreen ? elem.cancelFullScreen() : elem.msExitFullscreen ? elem.msExitFullscreen() : elem.exitFullscreen ? elem.exitFullscreen() : alert("切換失敗,可嘗試Esc退出"); }
import axios from 'axios' import router from '@/router' import {removeSessionStorage} from './storage'; import Vue from 'vue' import { Message } from 'element-ui' // 引用element-ui的加載和消息提示組件 // 請求超時時間配置 axios.defaults.timeout = 30000; // api地址配置 axios.defaults.baseURL = ""; // console.log(process.env.VUE_APP_BASE_API) Vue.prototype.$http = axios // 在全局請求和響應攔截器中添加請求狀態 let loading = null // 請求攔截器 axios.interceptors.request.use( config => { config.headers = { 'Content-Type': 'application/json' }; // loading = Loading.service({ text: '拼命加載中' }) let token = sessionStorage.getItem('-_token_-'); if (token) { config.headers['token'] = token; } return config }, error => { return Promise.reject(error) } ) // 響應攔截器 axios.interceptors.response.use( response => { if (loading) { loading.close() } //console.log(response) const code = response.status if ((code >= 200 && code < 300) || code === 304) { let errorCode = response.data.errCode; if(errorCode==='000000'){ return Promise.resolve(response.data) }else { if (errorCode === 'SYS0404') { router.push({ name: 'error', params: { isTimeout: false, path: router.currentRoute.path, desc: '您請求的資源找不到(錯誤碼:404) ', }, }); } else if (errorCode === 'SYS0401') { removeSessionStorage('-_token_-'); router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); } // Message.error(response.data.message) return Promise.resolve(response.data) } // return Promise.resolve(response.data) } else { return Promise.reject(response) } }, error => { if (loading) { loading.close(); } console.log(error); if (error.response) { switch (error.response.status) { case 401: case 403: // 返回401 清除token信息並跳轉到登錄頁面 removeSessionStorage('-_token_-'); router.replace({ path: '/login', query: { redirect: router.currentRoute.fullPath } }); break; case 404: Message.error('網絡請求不存在'); console.log('錯誤碼:404 路由跳轉 currentRoute %o ', router.currentRoute.path); router.push({ name: 'error', params: { isTimeout: false, path: router.currentRoute.path, desc: '您請求的資源找不到(錯誤碼:404) ', }, }); break; case 502: router.push({ name: 'error', params: { isTimeout: false, path: router.currentRoute.path, desc: '網關錯誤(錯誤碼:502),請聯繫系統管理員 ', }, }); break; default: Message.error(error.response.data.message ||'系統出錯,請聯繫系統管理員(錯誤碼:'+error.response.status+')!'); } } else { let controlParam = { desc: '', path: router.currentRoute.path, isTimeout: false, }; // 請求超時或者網絡有問題 if (error.message.includes('timeout')) { Message.error('請求超時!請檢查網絡是否正常'); controlParam.desc = '網絡斷開,請檢查您的網絡 '; controlParam.isTimeout = true; } else { Message.error('請求失敗,請檢查網絡是否已鏈接'); controlParam.desc = '頁面加載失敗 '; } router.push({ name: 'error', params: controlParam, }); } return Promise.reject(error); } );
2.1.1element-UI的操做步驟steps每一項添加事件,好比click,hoverelement-ui
<el-steps :space="200" :active="1" finish-status="success"> <el-step @click.native="on_click(1)" title="已完成"></el-step> <el-step @click.native="on_click(2)" title="進行中"></el-step> <el-step @click.native="on_click(3)" title="步驟 3"></el-step> </el-steps>
2.1.2 具體業務交互
https://blog.csdn.net/weixin_40098371/article/details/88027949
2.1.3 改變文字方向
變爲
調整css,設置magin和background
.el-step__main { white-space: normal; text-align: left; margin-top: -31px; margin-left: 25px; } } i .el-step__title { font-size: 16px; line-height: 38px; background: #FFF; width: 50px; position: relative; z-index: 1; }
//解決菜單雙擊報錯 const originalPush = VueRouter.prototype.push VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) }
注意環境變量的前綴必須是VUE_APP
在其餘文件中經過process.env.VUE_APP_BASE_API來訪問,例如在接口文件代碼中
import axios from 'axios' import router from '@/router' // 請求超時時間配置 axios.defaults.timeout = 30000; // api地址配置 axios.defaults.baseURL = "process.env.VUE_APP_BASE_API";
對應的package.json配置爲
"scripts": { "serve": "vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "test": "vue-cli-service build --mode test", },
爲了應對這樣的跨域場景,在代碼開發時,devServer要代理到本地後端,測試時,又要去修改代理到測試環境,上線後,調試新問題有可能代理到線上環境
對vue.config.js的進行配置
const Timestamp = new Date().getTime(); //當前時間爲了防止打包緩存不刷新,因此給每一個js文件都加一個時間戳 const proxyTargetMap = { prod: 'https://xxx.xxx.com/', dev: 'http://192.168.200.230:6379', test: 'http://test.xxx.com', local: 'http://localhost:8080/' } let proxyTarget = proxyTargetMap[process.env.API_TYPE] || proxyTargetMap.local module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/' : '/', outputDir: 'dist', assetsDir: 'static', lintOnSave: false, // 是否開啓eslint保存檢測 productionSourceMap: false, // 是否在構建生產包時生成sourcdeMap // 調整內部的 webpack 配置。 // 查閱 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/webpack.md chainWebpack: () => { }, //configureWebpack 這部分打包文件添加時間戳,防止緩存不更新 configureWebpack: { output: { // 輸出重構 打包編譯後的 文件名稱 【模塊名稱.版本號.時間戳】 filename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`, chunkFilename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js` }, }, devServer : { proxy: { '/api' : { target: proxyTarget, changeOrigin: true, pathRewrite: { '^/api' : '' } } } } };
對應的package.json配置爲
"scripts": { "serve": "vue-cli-service serve --mode development", + "serve:dev": "cross-env API_TYPE=dev vue-cli-service serve --mode development", + "serve:test": "cross-env API_TYPE=test vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "test": "vue-cli-service build --mode test", },