同学醒醒!还有个Bug没有改呢
open被拦截-已修复
故事背景
2022-06-27:wan支付业务的一个api授权。点击授权按钮,先通过ajax获取授权链接,再打开新窗口。chorme是正常的,但是Firefox就没有打开,需要用户手动授权,允许。这里不得不 夸 它一句,安全机制够好呀!测试了在ajax之前是可以正常打开的,await 后面 或者.then里面都是跳不过去的。
let res = await axios.get('xxxx')
// 正常浏览器下是能打开的如chorme
// 但是 火狐浏览器就被拦截了
window.open('https://www.baidu.com', '_blank')
火狐浏览器拦截
// 先获取url
let url = await axios.get('xxxx')
// 方案1 动态生成 a标签,通过a标签进行跳转
const a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('style', 'display:none');
a.setAttribute('target', '_blank');
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
// 方案2 动态创建 form 通过表单提交的方式
const form = document.createElement('form')
form.setAttribute('action', url);
form.setAttribute('style', 'display:none');
form.setAttribute('target', '_blank');
form.method = 'POST'
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
// 方案3 直接调window.open
window.open(url, '_blank')
let res = await axios.get('xxxx')
// 放在setTimeout 里面就能正常打开了
setTimeout(function() {
window.open('https://www.baidu.com', '_blank')
},0)
全局样式、样式穿透=》已修复
故事背景
2022-07-06:开发模块的时候,用到element ui 的组件;需要对滚动组件进行样式穿透,写在了 style中:导致。下拉框用到了这个类型造成,下拉框没有正常展示
// 错误写法
<style>
.el-scrollbar__wrap {
overflow-x: hidden;
}
// </style>
//改造
<style scoped>
::v-deep .el-scrollbar__wrap {
overflow-x: hidden;
}
</style>
vue3使用eventBus=》未修复
故事背景
2022-07-06: 需求场景,点击 tab 标签页的时候,重新做数据请求,el-tabs;
开始:通过发布订阅 eventBus 来实现,点击切换的时候进行 emit 触发,各个子组件之间的刷新、重新请求。使用方式,在main.js 通过 provide 注入,在子组件 直接 inject 引入 使用。结果导致页面一直在加载,具体原因未知。所以改变了其它实现方式。v-if 通过变量去控制(真香)
class EventBus {
constructor () {
this.events = Object.create(null)
}
$emit (eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach(function (fn) {
fn(data)
})
}
}
$on (eventName, fn) {
this.events[eventName] = this.events[eventName] || []
this.events[eventName].push(fn)
}
$off (eventName, fn) {
if (this.events[eventName]) {
for (var i = 0; i < this.events[eventName].length; i++) {
if (this.events[eventName][i] === fn) {
this.events[eventName].splice(i, 1)
break
}
};
}
}
}
const eventBus = new EventBus()
export default eventBus
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="店铺" name="first">
<ShopList v-if="activeName === 'first'" />
</el-tab-pane>
<el-tab-pane label="订单" name="second">
<OrderList v-if="activeName === 'second'" />
</el-tab-pane>
</el-tabs>
vue3 provide 和 inject
故事背景
2022-08-08:需求场景:游戏站里面使用了自己封装的倒计时组件,2个页面、四个地方。
方案1:vuex 来进行data 共享
方案2:provide 和 inject (这里采用的是2)
在首页通过ajax请求拿到 时间,然后注入;问题是:孙子组件中拿不到 时间。
可能因素:异步、生命构子,嵌套的组件生命周期先后执行顺序
解决:把注入的数据设置成响应式,ajax拿到数据 之后,改响应式数据,即可
// index.vue 注入依赖的地方
getCuntDownTime({}).then(res => {
let endTime = +new Date(res)
console.log(endTime)
provide("cuntDownTime", endTime)
}).catch(err => {
provide("cuntDownTime", 0)
})
// /pc/index.vue mobile/index.vue 孙子组件
import { ref, inject } from "vue";
const cuntDownTime = inject('cuntDownTime') || 0
const endTime = ref(cuntDownTime); // 1658923195025
const isShow = ref(cuntDownTime - +new Date() > 0)
// index.vue 注入依赖的地方
// 使用的地方不需要改变
import { provide, ref } from 'vue'
const endTime = ref(0)
provide("cuntDownTime", endTime)
getCuntDownTime({}).then(res => {
endTime.value = +new Date(res) || 0
}).catch(err => {
provide("cuntDownTime", 0)
console.log(err)
})
element-plus按需打包,弹出框报错
故事背景
2022-09-07: 手上的开发的游戏站即将上线【vite3 +vue3】,产品突然说,网站首页加载太慢,确实挺慢的,挂了梯子13s ^_^,无奈的前端开发[wo]只能硬着头皮去优化
优化点:
1.图片懒加载,使用自定义指令的形式
2.路由懒加载(先前就做了的
3.代码gzip压缩vite-plugin-compression
4.图片压缩 vite-plugin-imagemin
5.element-plus 按需打包 (然后弹出框就开始报错了)
解决方案: 网上查,官方暂未给出解决方案,,所以就放弃了
export default (app) => {
// 图片懒加载指令
app.directive('lazyload', {
mounted(el, binding) { // vue2.0 inserted vue3.0 mounted
const observer = new IntersectionObserver(([{ isIntersecting }]) => {
if (isIntersecting) { // isIntersecting判断是否进入视图
observer.unobserve(el) // 进入视图后,停止监听
el.onerror = () => { // 加载失败显示默认图片
// el.src = '/img/a.jpg'
}
el.src = binding.value // 进入视图后,把指令绑定的值赋值给src属性,显示图片
}
}, {
rootMargin: '0px 0px 100px 0px',
// threshold: 0.01 // 当图片img元素占比视图0.01时 el.src = binding.value
})
observer.observe(el) //观察指令绑定的dom
}
})
}
//注册 main.js
lozyLoad(app)
// 使用 index.vue
// v-lazyload 替换原来的src 属性
<img v-lazyload='src' />
// vite.config.js
import viteImagemin from "vite-plugin-imagemin";
import viteCompression from "vite-plugin-compression";
plugins: [
viteImagemin({
gifsicle: {
optimizationLevel: 7,
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
mozjpeg: {
quality: 20,
},
pngquant: {
quality: [0.8, 0.9],
speed: 4,
},
svgo: {
plugins: [
{
name: "removeViewBox",
},
{
name: "removeEmptyAttrs",
active: false,
},
],
},
}),
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: "gzip",
ext: "gz",
}),
]
vue项目中class不生效
故事背景
2022-10-12:孝鑫同学在开发弹幕组件,弹幕是动态删除和创建的
问题描述:弹幕动态生成,在添加上类名,页面上dom有class但是没有生效
根本原因:style 标签上有scoped,原先class带有前缀隔离。动态生成的class匹配不到style中的类名
vue key慎用 随机数
背景
2022-12-27:静明同学在开发记忆卡牌游戏,历尽千辛万苦,终于把游戏逻辑开发完成:点击一张卡片,卡片翻过来,过1s翻回去,连续点击两种花色一样的卡牌,则两张一起翻过来,并且不能再点击...
问题描述: 翻卡牌的动画是css写的3d翻转,transition却怎么也不生效
根本原因:v-for 出来的卡牌 key=“index + Math.random()”每次点击,整个v-for 的dom都重新渲染了,导致不生效;
解决办法:key 正常写就好了
获取当日零点时间戳
const timeStamp = +new Date(new Date(new Date()、getTime()).setHours(0, 0, 0, 0)) // 当天0点时间戳
数组打乱顺序
背景
2022-12-27:静明同学,有个打乱数组顺序的需求
问题描述:打乱顺序后的数据 和 通过v-for渲染的数组数据不一致;是在setup 构子中构建的数组数据,数组是同一个,并且是在打乱顺序后才给赋值的。。。
根本问题:未解之谜
解决办法:我把打乱顺序的方法放到 onMounted 构子中执行就好了
const shuffle = (array: CardItem[]) => {
const arr = []
const nums = array.slice(0)
const len = nums.length
for (let i = 0; i < len; i++) {
const index = Math.floor(Math.random() * nums.length)
arr[i] = nums[index]
nums.splice(index, 1)
}
return arr
}
vuerouter 懒加载
背景
2023-02-16:静明同学,优化项目
问题描述:该项目原本是没有vue的路由懒加载的,因为最近在处理项目的优化工作,一看就发现可以把懒加载加上,才引发了多页面跳回vue页面 报错的问题。
TypeError: Cannot read properties of undefined (reading '__asyncLoader')
在一顿操作下,终于找到了解决方法:defineAsyncComponent
解决办法如下:
import { createApp, defineAsyncComponent } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
const payAccount = defineAsyncComponent(() => import('../pages/index.vue'));
// 报错的写法如下 注:也只有在多页跳回单元遇到了这种情况
// const payAccount = () => import('../pages/index.vue')
user-agent
背景
20223/02/27: 静明同学 进行 super....官网的开发
项目: Nuxt3 + vite 搭建的,PC 和移动端 使用的postcss pxToRem 实现的适配
引了一个 '@nuxt/device' 的库用来区分是PC 还是移动端
运维同学在部署服务器的时候,ng 代理的请求 user-agent 给我整丢了,,结果一直判断不正确
各种排查,,甚至怀疑了库的源码
获取url参数
背景
2023/03/14:静明同学 publis...后台项目
项目:ant design Pro 搭建的后台
单点登录功能:token的读取 (从主admin 通过token 进行伪登录)
问题: 读取url 参数 token的值 由多个 “=” 组成,,解析后给后端传过去的token ,
后端: 我给你的token不是你传给我的这个,第一反应是从 admin 跳过来的时候带的token不对,然后经过 几分钟排查:跳转携带的参数没有问题!!!
结论: 我自己解析url的时候 搞丢了
心里:copy 的那个吊毛的代码,获取url都能搞错【诶,问问G老师去gpt】
一顿操作下来终于找到了个能用的欣慰。。。
export function getParamsKey(href: string) {
let encodeStr = href.split('?')[1];
let decodeStr = decodeURIComponent(encodeStr);
if (decodeStr.includes('&')) {
let paramsArr = decodeStr.split('&');
let obj = {};
paramsArr.forEach((el) => {
let [key, value] = el.split('=');
obj[key] = value;
});
return obj;
} else {
let [key, value] = decodeStr.split('=');
return {
[key]: value,
};
}
}
export function getParamByKey(name: string, url: string) {
let start = url.indexOf('?');
if (start === -1) {
return null;
}
let params = url.substring(start + 1).split('&');
for (let i = 0; i < params.length; i++) {
let param = params[i].split('=');
if (param[0] === name) {
let value = '';
for (let j = 1; j < param.length; j++) {
if (j > 1) {
value += '=';
}
value += param[j];
}
return decodeURIComponent(value);
}
}
return null;
}
jquery dataTables
背景
2023/03/30: 静明同学突然发现 自己维护的adin 有bug
项目: jq + Vue + vben + ant-design-vue 搭建的后台
问题:分页器展示了两个
心里暗示:你已经是一个成熟的程序员
对于这个问题:debugger log 看家本领都拿出来了
- $('#dataTable').DataTable会不会实例了两次
- js 文件是否重复加载
- 分页器是否写了两个
一顿操作下来:已上猜想都不是《》《》《》
看来是想逼我出绝招:删代码
还别说,,真管用 这不就找到了
const table = $('#dataTable').DataTable({
dom: 'Bprtip',
...
})
在心中暗自 问候了几句之后就改好了,,
我真机智
新旧版本之间 缓存逻辑复用问题
localStorage
背景:2023.05.29 小明同学接到个 推荐弹窗 在原生弹起的需求
项目:yowin-cp vue3+vant3
问题:app内嵌套了 h5(webview),推荐弹窗逻辑是用缓存判断的,然后一顿操作下来条件都没有问题,为什么弹窗没有弹出来呢?
app的内置h5是就版本,旧版本去跟新了缓存,新版h5判断到的是旧版h5设置的缓存 直接忌了
const recommendPopFn = (e: { data: any })=>{
const { data } = e
const now = new Date()
const before = new Date(now.getTime() - 1000 * 60 * 60 * 24)
const date = now.getFullYear()+"-"+now.getMonth()+"-"+now.getDate()
const beforeDate = before.getFullYear()+"-"+before.getMonth()+"-"+before.getDate()
const hours = now.getHours()
const current = (hours >=0 && hours<12) ? '1' : '2'
const heavenlyRedEnvelopeDataShow = localStorage.getItem(date+"_heavenlyRe3")
//兼容
const oldheavenlyRedEnvelopeDataShow = localStorage.getItem(date+"_heavenlyRed")
if(!heavenlyRedEnvelopeDataShow){
//把昨天的key删除
localStorage.removeItem(beforeDate+"_heavenlyRe3")
}
if(store.state.task.taskList?.recommendPopTask.length
&& ( !heavenlyRedEnvelopeDataShow || heavenlyRedEnvelopeDataShow != current )
&& store.state.riskResult == 'pass'
&& !oldheavenlyRedEnvelopeDataShow
&& (!mapPop.get(date) || new Date().getTime() - mapPop.get(date) > 1 * 1000)
){
time = setInterval(() => {
if (remcommCanPop && hasRecommTask) { // && hasRecommTask
mapPop.set(date, new Date().getTime());
localStorage.setItem(date+"_heavenlyRe3",current)
localStorage.setItem('recommendPopData', JSON.stringify(recommendPop.value))
// window.trackEvent({ pageTitle: "taskPage", ev: "showNewuserTaskPop"});
window.trackEvent({ pageTitle: "taskPage", ev: "recommendPopShow",remarks:JSON.stringify(data|| {}) });
console.log('recommonPop 11111222', store.state.task.taskList?.recommendPopTask)
console.log('能弹了', hasRecommTask)
window.webView.create('/recommonPop?name='+data?.name+'&isWebView=true'+'&t='+new Date().getTime(),'',getEcId(),false,"full", 0.3)
clearInterval(time)
}
}, 500)
return
}
}
断电导致vue项目git不显示分支
.git
背景:2023.06.02 小明同学早上打开 cp 项目
项目:yowin-cp vue3+vants+ts
问题:项目分支没有了,提示需要初始化git
wtf? 难道是昨天断了3次电,自动重启 导致的?
解决:
- 先是把项目跑起来,没有报错,正常,那说明只是 .git文件夹坏了
- 重新克隆了远程的仓库 一切正常,吧新拉的.git文件替换 坏的. git 也坏了
- 先是百度、chatgpt了一波,没有啥收获
- 后面发现 是 HEAD 文件乱码了 下面有贴图
// HEAD:指向当前活动分支的引用,也可以是指向某个提交(commit)的引用。
// config:存储Git仓库的配置信息,包括用户信息、远程仓库设置等。
// objects:存储Git对象的目录,包括提交、树(tree)和文件(blob)等。
// refs:存储引用(references)的目录,包括分支、标签和远程跟踪分支等。
// index:暂存区(stage)的索引文件,记录了当前工作目录中已经修改的文件和将要提交的文件。
// logs:存储分支和引用的日志信息,包括提交历史、分支移动等。
// hooks:存储自定义钩子脚本的目录,可以在特定的Git操作事件触发时执行脚本。
url判断是否包含某个子串
const sceneObj = {}
if (!url || !url.includes('http')) return sceneObj
let newUrl = url.toLowerCase()
// 广告存在
const isNeedAd = store.state.model?.mediationAdList?.some((item:any) => {
if (newUrl.includes(item.scene)) { // 就是这里,判断子串,没有判空
sceneObj.scene = item.scene
return true
}
})
不要喷啦,我自己喷过几次啦!!!! 我判断了url非空,,但是没有判断item.scene 真是服了,,大聪明
顶层awite 报错
背景:admin后台 新增 功能 项目:admin: vue3+vben(antdv) 时间:2023.12.21周四
问题描述:下拉选择组件,选项从接口获取。然后本地是vite项目,本地开发是没有进行编译打包的。结果再上线的时候就报错了,
// 原来代码
let res = await getXXXList({})
// 改造后
const getXXXListFn = async () => {
return await getXXXList({})
}
getXXXListFn()
public 的js 问价报错
背景:202312.25测试同学发现有个手机打开的活动页全部有问题
项目:vue3,脚手架搭建的
问题描述:通过app内部打开了活动webview,结果白屏。其它手机正常的,只有这一台异常。然后定位到,?. 可选链问题。。。我的真感谢!!!!!
解决办法:
- 把public 下的js问价,做降级处理,转成es5的写法,利用在线babel转码工具。
问题复盘:
- 当时没有做降级处理,导致报错。
- 也忽略了public文件不参与打包与编译,也就没有做babel降级处理。