1.vue框架使用註意事項和經驗 1.1 解決Vue動態路由參數變化,頁面數據不更新 問題描述: 遇到動態路由如:/page/:id 從/page/1 切換到 /page/2 發現頁面組件沒有更新 解決方式1: 給增加一個不同:key值,這樣vue就會識別這是不同的了。 解決方案2: 在組件內使用v ...
1.vue框架使用註意事項和經驗
1.1 解決Vue動態路由參數變化,頁面數據不更新
問題描述:
遇到動態路由如:/page/:id
從/page/1 切換到 /page/2 發現頁面組件沒有更新
解決方式1:
給<router-view :key="key">增加一個不同:key值,這樣vue就會識別這是不同的了。
<router-view :key="key"></router-view>
...
computed:{
key(){
return this.$route.path + Math.random();
}
}
解決方案2: 在組件內使用v2.2新增的beforeRouteUpdate
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被覆用時調用
// 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由於會渲染同樣的 Foo 組件,因此組件實例會被覆用。而這個鉤子就會在這個情況下被調用。
// 可以訪問組件實例 `this`
},
1.2 vue組件里定時器銷毀問題**
問題描述:
在a頁面寫一個定時器,每秒鐘列印一次,然後跳轉到b頁面,此時可以看到,定時器依然在執行。
推薦的解決方式:
通過$once這個事件偵聽器器在定義完定時器之後的位置來清除定時器。
const timer = setInterval(() => {
// 定時器操作
}, 1000)
// 通過$once來監聽定時器,在beforeDestroy鉤子可以被清除。
this.$once('hook:beforeDestroy', () => {
clearInterval(timer);
})
也可以使用生命周期聲明的方式:
export default {
beforeDestroy(){
clearInterval(timer);
}
}
1.3 vue實現按需載入組件的兩種方式**
1.使用resolve => require(['./ComponentA'], resolve),方法如下:
const ComponentA = resolve => require(['./ComponentA'], resolve)
2 使用 () => import(), 具體代碼如下:
const ComponentA = () => import('./ComponentA')
1.4 組件之間,父子組件之間的通信方案
組件之間的通信方案:
- 通過事件匯流排(bus),即通過發佈訂閱的方式
- vuex
- 父子組件:
- 父組件通過prop向自組件傳遞數據
- 子組件綁定自定義事件,通過this.$emit(event,params) 來調用自定義事件
- 使用vue提供的$parent/$children & $refs方法來通信
- provide/inject
- 深層次組件間的通信 $attrs, $listeners
1.5 vue中 $event 的用法--獲取當前父元素,子元素,兄弟元素
<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
}
}
1.6 axios二次封裝http請求
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()
}
// 自定義錯誤碼,各公司根據約定都不一樣
// 此處省略業務處理代碼
let errorCode = response.data.errCode;
if(errorCode==='000000'){
return Promise.resolve(response.data);
}else {
router.push({
name: 'error',
params: {
isTimeout: false,
path: router.currentRoute.path,
desc: '您請求的資源找不到(錯誤碼:404) ',
},
});
}
},
error => {
if (loading) {
loading.close();
}
// 此處省略業務處理代碼
return Promise.reject(error);
}
);
1.7 開發環境中代理的切換配置
為了應對這樣的跨域場景,在代碼開發時,devServer要代理到本地後端,測試時,又要去修改代理到測試環境,上線後,調試新問題有可能代理到線上環境
該代碼運行環境為node.js,使用process.env可以獲取到系統環境變數,從而區分當前機器是公司的生產機器,還是個人的開發機器
對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配置為
看下麵的cross-env API_TYPE=dev
cross-env是一個全局命令行工具,可以根據不同的平臺更改當前的環境變數,從而實現了可以在開發者的機器上,選擇性的調用開發模式或者生產模式
"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",
},