一些vue实用小技巧总结
每天不断的coding,缺少业务总结,感觉得自己的成长缓慢,就是现在,静下心来总结一下一些常用的vue 使用小技巧吧
1. hookEvent在可视化图表中用于监听生命周期
常规处理是在 beforeDestroy 生命周期增加销毁监听的事件,但是还可以通过 hook 监听生命周期函数。 在Vue
组件中,可以用过$on
, $once
去监听生命周期钩子函数,如监听组件的updated
钩子函数可以写成 this.$on('hook:updated', () => {})
<template>
<div class="echarts"></div>
</template>
<script>
export default {
mounted() {
this.chart = echarts.init(this.$el)
// 监听窗口缩放事件,调用相关方法:
window.addEventListener('resize', this.$_handleResizeChart)
// 通过hook监听组件销毁钩子函数,并取消监听事件
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', this.$_handleResizeChart)
})
},
updated() {},
created() {},
methods: {
$_handleResizeChart() {
this.chart.resize()
}
}
}
</script>
2. 点击列表数据进入其详情页面的传参问题
在商品列表页面点击进入某个商品的详情界面,需要传一个商品ID。vue 的路由传参有两种方式:query传参 和 params动态路由传参,两者之间用法区别:
- query通过path切换路由;params通过name切换路由
// query通过path切换路由
<router-link :to="{path: 'Detail', query: { id: 1 }}">前往Detail页面</router-link>
// params通过name切换路由
<router-link :to="{name: 'Detail', params: { id: 1 }}">前往Detail页面</router-link>
- query通过
this.$route.query
接收参数;params通过this.$route.params
接收参数
// query通过this.$route.query接收参数
created () {
const id = this.$route.query.id;
}
// params通过this.$route.params来接收参数
created () {
const id = this.$route.params.id;
}
- 传参url展示不一样
query传参的url展现方式:/detail?id=1&user=123&identity=1
params动态路由的url方式:/detail/123
需要注意的是 params 动态路由传参一定要在路由中定义参数,然后在路由跳转时候必须加上参数。例如:
// 定义的路由中,只定义一个id参数
{
path: 'detail/:id',
name: 'Detail',
components: Detail
}
// 穿了参数 id 和 token; id是在路由中已经定义的参数,而token没有定义
<router-link :to="{name: 'Detail', params: { id: 1, token: '123456' }}">前往Detail页面</router-link>
// 在详情页接收
created () {
// 以下都可以正常获取到, 但是页面刷新后,id依然可以获取,而token此时就不存在了
const id = this.$route.params.id;
const token = this.$route.params.token;
}
3. 小项目中可以用 Vue.observable 代替 Vuex 做状态管理
Vuex 适用于大型项目的开发,我们可以用 Vue.observable 来替代 Vuex,打造一个简单的 Vuex 状态管理,其实本质上核心思想都是对观察者模式的实现。
// 创建文件 store.js
import Vue from 'vue'
export const store = Vue.observable({
userInfo: {},
roleIds: []
})
// 定义 mutations, 提供修改属性的功能:
export const mutations = {
setUserInfo(userInfo) {
store.userInfo = userInfo
},
setRoleIds(roleIds) {
store.roleIds = roleIds
}
}
// 在组件中引用 store.js 文件
<template>
<div>
{{ userInfo.name }}
</div>
</template>
<script>
import { store, mutations } from '../store'
export default {
computed: {
userInfo() {
return store.userInfo
}
},
created() {
mutations.setUserInfo({
name: '子君'
})
}
}
</script>
4. axios 的应用和封装
在src 目录下我们新建 request 文件夹,新建 http.js 和 api.js 文件,用 http.js 来封装我们的axios。 通过node 环境变量来匹配默认的接口 URL 前缀。axios.defaults.baseURL设置axios的默认请求地址,设置请求头相关信息:
import axios from 'axios';
import router from '../router';
import {MessageBox, Message} from 'element-ui';
import store from '@/store/index'; // 引入Vuex状态管理
// 环境选择
if (process.env.NODE_ENV == 'development') {
axios.defaults.baseURL = 'https://www.development.com';
} else if (process.env.NODE_ENV == 'production') {
axios.defaults.baseURL = 'https://www.production.com';
}
// 设置请求超时时间:
axios.defaults.timeout = 10000;
// post 请求头设置:
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
请求拦截 —— 在登录完成之后,将用户的token通过localStorage或者cookie存在本地,然后用户每次在进入页面的时候(即在main.js中),会首先从本地存储中读取token,如果token存在说明用户已经登陆过,则更新vuex中的token状态。然后,在每次请求接口的时候,都会在请求的header中携带token,后台人员就可以根据你携带的token来判断你的登录是否过期,如果没有携带,则说明没有登录过。
axios.interceptors.request.use(
config => {
const token = store.state.token;
token && (config.headers.Authorization = token); // token 塞入请求头
return config;
},
error => {
Message.warning(error);
return Promise.error(error);
})
响应拦截 —— 就是服务器返回给我们的数据,我们在拿到之前可以对他进行一些处理。Toast()方法,是我引入的vant库中的toast轻提示组件。
axios.interceptors.response.use(
response => {
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 错误状态码可以自己扩展
error => {
if (error.response.status) {
switch (error.response.status) {
// 401: 未登录
case 401:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token过期
case 403:
Toast({
message: '登录过期,请重新登录',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404请求不存在
case 404:
Toast({
message: '网络请求不存在',
duration: 1500,
forbidClick: true
});
break;
// 其他错误,直接抛出错误提示
default:
Toast({
message: error.response.data.message,
duration: 1500,
forbidClick: true
});
}
return Promise.reject(error.response);
}
}
});
5. 定时器的清理问题 —— 两种实现方法
- 常规操作就是在data 函数定义一个定时器,最后在 beforeDestroy() 里面销毁;
data() {
return {
timer: null // 定时器名称
}
}
this.timer = (() => {
// 某些操作
}, 1000)
// 销毁定时器
beforeDestroy() {
clearInterval(this.timer);
this.timer = null;
}
- 通过$once这个事件侦听器器在定义完定时器之后的位置来清除定时器
const timer = setInterval(() =>{
// 某些定时器操作
}, 500);
// 通过$once来监听定时器,在beforeDestroy钩子可以被清除。
this.$once('hook:beforeDestroy', () => {
clearInterval(timer);
})
转载自:https://juejin.cn/post/6986984977233608718