skip to content
天真笔录

vue踩坑记录

/ 5 min read

keep-alive

问题描述 设置了keep-alive的组件,watch事件不会销毁

  1. watch route,离开当前页面,还是会watch到路由变化
  2. watch vuex,也是同样的问题

解决

  1. 方式一
watch: {
  test() {
    if (this.$route.name !== 'test') return
  }
}

这种解决方法依赖于当前组件的route name,如果路由比较多,改动起来略麻烦

方式二(mixin)

/* mixin.js */
data() {
  return {
    _currentPage: true
  }
},
deactivated() {
  this._currentPage = false
}
/* page */
watch: {
  test() {
    if (this._currentPage !== true) return
  }
}

注意事项:

  1. mixin定义的变量(_currentPage)有与其他data变量重复的风险
  2. 仍然需要每个页面修改watch

key值重复

key值重复导致数据不更新

  1. 浏览器和安卓并没有此情况
  2. ios存在不更新的情况·

项目难点

1. 菜单联动

  • 现象描述:点击菜单滚动到菜单对应的模块位置;
  • 难点:菜单有一部分是条件渲染的,点击时需要知道当前菜单的位置
  • 旧实现:根据条件动态计算当前索引位置;当有新增删除模块时,需要手动维护索引

改进:

  1. updated中获取已经渲染好的列表
  2. 遍历渲染好的列表为其动态设置data-index绑定索引
  3. 点击时为当前元素添加class: active,移除之前的active

思路:

这里过度依赖vue数据绑定,导致了索引更新变得复杂,反而使用以前的命令式编程更方便

2. unionid重复获取

  • 现象描述:新用户进入时需要调用unionid接口并存储,在其他接口中携带,由于进入时要同时调用很多接口,unionid接口被多次发起,实际只需要发起一次就好了

解决

  1. 在发起ajax时,发现unionid没有时,只发起一次请求
  2. 发起的请求返回一个promise,并存入队列中
const ajaxList = [];
return new Promise((resolve, reject) => {
	ajaxList.push([resolve, args]); // resolve是在unionid获取到时在触发, args是发起ajax时的参数
});
  1. 在unoinid参数响应后,通知更新
getUnionId().then((res) => {
	ajaxList.forEach(([resolve, args]) => {
		resolve(ajax(args)); // 伪代码
	});
});

vant与vue-cropper

  • 现象描述:使用vantpropup做弹窗,使用vue-cropper做裁剪时,会非常卡顿

解决

propup上设置lock-scroll: false

426 Upgrade Required

Status: 426 Upgrade Required

这个问题的原因是nginx中作了反向代理,反向代理默认是http1.0,与被代理http1.1不一致

location /*** {
  proxy_http_version 1.1; // 需要添加这一行
  proxy_pass http://***.com;
}

vue-router记录浏览位置失效

const router = createRouter({
	history: createWebHistory(process.env.BASE_URL),
	routes: [...commonRoute, ...preApply],
	scrollBehavior(to, from, savedPosition) {
		return (
			savedPosition || {
				x: 0,
				y: 0,
			}
		);
	},
});

使用了keep-alive,但路由返回时却回到了顶部,原因可能是因为页面使用了定高

解决

height: auto

watch route

import { useRoute } from "vue";
const $route = useRoute();
watch($route, (to, from) => {
	console.log(to, from);
});

问题描述

  • 在vue2中,to和from返回的是新路由对象和旧路由对象
  • 在vue2.7中,to和from返回的都是同一个路由对象,在vue3中也是一样

解决

import { useRouter } from "vue-router";
const $router = useRouter();
watch(
	() => $router.currentRoute.value,
	(to, from) => {
		console.log(to, from);
	},
);

vant事件参数扩展

// 正常情况下
@change="onChange"
// 自定义参数
@change="(event) => onChange(event, arg)"