楔子
在每日的例行会议上,空气中弥漫着紧张的气息。一位实习组员语速略急地说道:“昨天我主要的工作是排查一个线上bug
,目前还没有得到解决,今天我得继续排查。”。
组长眉头微皱,冷冷地盯了他一眼:“你小子,一个bug
排查一整天,怕是在摸鱼吧!到底是什么问题?说来听听,我稍后看看。”。
组员无奈地摊了摊手,耸了耸肩,长叹一口气:“前两天,订单表格新增定制信息匹配失败情况的展示。自己没有经过仔细的测试,就直接发布上线了,导致现在整个订单列表渲染缓慢。这个bug
超出了我的能力范围,我排查了一天也排查不出来,摸鱼是404
的。”。
组长深吸一口气,眼神中露出几分聪慧:“那不就是你编写的组件有问题吗?你最好没有摸鱼!不然你就等着吃鱼吧!”。
组员按捺不住心中的窃喜:“我如果不说一天,又怎么能请动你这尊大神呢?”。
排查
果不其然,控制台果真报错了。组长看了眼报错信息,摇了摇头,面色凝重:“你小子,居然都不看控制台的报错信息?这bug怎么排查的?”。组员下意识地捏紧了拳头,声音也不自觉地低了几分,结结巴巴道:“我、我真的不知道控制台还有这操作!学废了。”。
组长怀着忐忑不安的心情打开vsCode
, 只见一大串代码赫然映入眼帘:
<template>
<div class="design-wrapper">
<designProducts v-if="showBtn" btnText="设计" class="mr10" :data="data" @success="success" />
<el-tooltip v-if="showStatus" trigger="click" placement="right" :disabled="disabled">
<baseTable1 class="hide-tabs" :data="tableData" :option="option">
<template #content="{ row }">
<defaultImg v-if="imageType(row)" :src="image(row)" :size="100" />
<span v-else>{{ text(row) }}span>
template>
<template #mapping="{ row }">
<i :class="icon(row)">i>
template>
<template #importLabelCode="{ row }">
<span v-if="!row.hide">{{ row.importLabelCode }}span>
template>
<template #matchStatus="{ row }">
{{ matchSuccess(row) ? '已匹配' : '未匹配' }}
template>
<template #design="{ row }">
<defaultImg
v-if="!row.hide && imageType(row)"
:disabled="row.disabled"
:src="row.importContent"
:size="100"
@error="error(row)"
>
<template #defaultImg>
<div class="flex-middle">{{ row.importContent || '无' }}div>
template>
defaultImg>
<div v-else-if="!row.hide && !imageType(row)">{{ row.importContent || '无' }}div>
template>
baseTable1>
<color-text-btn slot="reference" @click="toDesign">{{ status }}color-text-btn>
el-tooltip>
<span v-else>span>
div>
template>
当扫到el-tooltip (文字提示), 组长拍案而起,额头上暴起的青筋在不断颤抖。急切的声音,仿佛要撕裂虚空:“你小子,短短几十行代码,至少犯了2个致命错误!”。
问题分析
1. 从代码源头分析el-tooltip
(控制台报错的原因)
-
el-tooltip
组件主要是针对文字提示,而el-popover
才是针对组件进行展示。这两者是截然不同的,不然element
也不会分出两套组件,去分别处理这两种情况。 -
我们的项目之所以能正常使用
vueX
和router
,是因为我们在main.js
中引入并挂载了同理,分析
el-tooltip
组件的代码实现,它只挂载了data
属性。因此,当强行在el-tooltip
组件中使用自定义组件:如果组件内部使用的是非国际语言(i18n
)的纯文本,控制台不会报错;如果在该组件中使用了诸如vueX
、路由跳转等在内的变量或者方法时,控制台就会疯狂报错,因为这些并没有在初始化时注入到el-tooltip
组件中。
2. 如何在el-tooltip
中使用i18n
?
假定有一个非常执拗的人,他看到el-tooltip
组件描述的功能是文字提示。他就不想在el-popover
中使用$t
, 而想在el-tooltip
组件中使用i18n
。那么可以做到吗?答案是肯定的。
我们可以直接通过继承法则:封装一个base-tooltip
组件,继承el-tooltip
组件。并根据继承规则:先执行el-tooltip
组件的生命周期钩子方法,再执行base-tooltip
组件里面的生命周期钩子方法。通过这种方式,我们成功挂载了i18n
。此时,在base-tooltip
组件中使用$t
,就不会报错了。
3. el-tooltip
的局限性(订单列表渲染缓慢的原因)
前文提及,我们可以继承el-tooltip
组件。那么,我们如果通过按需引入的方式,将所需要的资源全部挂载到vue
中。这样,就算在base-tooltip
组件中使用vueX
和$route
变量,也不会在控制台上报错。的确如此,但是我们需要注意到el-tooltip
和el-popover
的局限性: 悬浮框内容是直接渲染的,不是等你打开悬浮框才渲染。
这也就意味着,如果我们在表格的每一行都应用了el-tooltip
或el-popover
组件,而且在el-tooltip
或el-popover
的生命周期钩子函数中请求了异步数据。就会导致页面初始化渲染数据的同时,会请求N
个接口(其中,N
为当前表格的数据条数)。一次性请求大于N + 1
个接口,你就说页面会不会卡顿就完事了!
但是,el-popover
这个组件不一样。在它的组件内部,提供了一个show
方法,这个方法在trigger
触发后才执行。于是,我们可以在show
方法中,去请求我们需要的异步数据。 同时注意一个优化点:在悬浮框打开之后,才渲染Popover内嵌的html文本
,避免页面加载时就渲染数据。
由于el-popover
的内容是在弹窗打开后才异步加载的,弹窗可能会在内容完全加载之前就开始计算和渲染位置,导致弹出的位置不对。但是我们遇到事情不要慌,el-popover
组件的混入中提供了一个方法updatePopper
,用于矫正popover
的偏移量,以期获取正确的popover
布局。
解决方法
将上述所有思路结合在一起,我们就能够封装一个公共组件,兼容工作中的大多数场景。
<el-popover
ref="popover"
@show="onShow"
v-bind="$attrs"
v-on="$listeners"
>
<template v-if="isOpened">
<slot>slot>
template>
<template slot="reference">
<slot name="reference">slot>
template>
el-popover>
<script>
import agentMixin from '@/mixins/component/agentMixin'
export default {
mixins: [agentMixin({ ref: 'popover', methods: ['updatePopper', 'doClose'] })],
props: {
beforeOpen: Function
},
data() {
return {
isOpened: false
}
},
methods: {
async onShow() {
if(!this.beforeOpen) {
return this.isOpened = true
}
const res = await this.beforeOpen()
if(!res) return this.isOpened = false
this.isOpened = true
await this.$nextTick()
this.updatePopper()
}
}
}
script>
import { isArray, isPlainObject } from 'lodash'
export default function ({ ref, methods } = {}) {
if (isArray(methods)) {
methods = methods.map(name => [name, name])
} else if (isPlainObject(methods)) {
methods = Object.entries(methods)
}
return {
methods: {
...methods.reduce((prev, [name, alias]) => {
prev[alias] = function (...args) {
return this.$refs[ref][name](...args)
}
return prev
}, {})
}
}
}
<div class="design-wrapper">
<designProducts v-if="showBtn" btnText="设计" class="mr10" :data="data" @success="success" />
<basePopover v-if="showStatus" trigger="click" placement="right" :beforeOpen="beforeOpen" :disabled="disabled">
<baseTable1 class="hide-tabs" :data="tableData" :option="option">
<template #content="{ row }">
<defaultImg v-if="imageType(row)" :src="image(row)" :size="100" />
<span v-else>{{ text(row) }}span>
template>
<template #mapping="{ row }">
<i :class="icon(row)">i>
template>
<template #importLabelCode="{ row }">
<span v-if="!row.hide">{{ row.importLabelCode }}span>
template>
<template #matchStatus="{ row }">
{{ matchSuccess(row) ? '已匹配' : '未匹配' }}
template>
<template #design="{ row }">
<defaultImg
v-if="!row.hide && imageType(row)"
:disabled="row.disabled"
:src="row.importContent"
:size="100"
@error="error(row)"
>
<template #defaultImg>
<div class="flex-middle">{{ row.importContent || '无' }}div>
template>
defaultImg>
<div v-else-if="!row.hide && !imageType(row)">{{ row.importContent || '无' }}div>
template>
baseTable1>
<color-text-btn slot="reference" @click="toDesign">{{ status }}color-text-btn>
basePopover>
<span v-else>span>
div>
<script>
methods: {
async beforeOpen() {
const res = await awaitResolveDetailLoading(
microApi.getMatchInfo({
id: this.data.id
})
)
if (!res) return false
this.tableData = res
return true
}
}
script>
反思
在组长的悉心指导下,组员逐渐揭开了问题的真相。回想起自己在面对bug
时的轻率和慌乱,他不禁感到一阵羞愧。组长平静而富有耐心的声音再次在耳边响起:“排查问题并非一朝一夕之功。急于上线而忽视测试,只会让问题愈加复杂。”这一番话如同醍醐灌顶,瞬间点醒了他,意识到自己的错误不仅在于代码的疏漏,更在于对整个工作流程的轻视。
“编写代码不是一场竞赛,速度永远无法替代质量。”组长边调试代码,边语重心长地说道。组长的语气虽然平淡,却蕴含着深邃的力量。组员心中的敬佩之意油然而生,细细回味着这番话,顿时明白了面对复杂bug
时,耐心与细致才是解决问题的最强利器。组长的话语简洁而富有哲理,令他意识到,曾经追求的“快速上线”与开发中的严谨要求完全背道而驰。
不久之后,组员陷入了沉思,轻声开口:“起初,我还真觉得自己运气不好,偏偏遇上如此棘手的bug
。但现在看来,这更像是一场深刻的教训。若能在上线前认真测试,这个问题本是可以避免的。”他的声音中透出几分懊悔,眼中闪烁着反思的光芒。
组长微微一笑,点头示意:“每一个bug
都是一次学习的契机,能意识到问题的根源,已是进步。”他稍作停顿,眼神愈加坚定:“编程的速度固然重要,但若未经过深思熟虑的测试与分析,那无疑只是纸上谈兵。写代码不仅需要实现功能,更需要经得起时间的考验。”这番话语透着无可辩驳的真理,给予了组员莫大的启迪。
组员感慨道:“今天的排查让我真正领悟到耐心与细致的重要性。排查bug
就像走出迷宫,急躁只会迷失方向,而冷静思考才能找到出路。”他不禁回忆起自己曾经的粗心大意,心中暗自发誓,今后在每一次提交前都要更加谨慎,绝不再犯同样的错误。
“你小子,倒也不算愚钝。”组长调侃道,嘴角勾起一丝轻松的笑意,“但记住,遇到问题时要先冷静分析错误信息,找出原因再行动。不要盲目修改,开发不仅仅是写代码,更需要学会深思熟虑。”他轻轻拍了拍组员的肩膀,那一拍似乎传达着无限的关心与期望。
这一拍虽轻,却如雷霆般震动着组员的心灵。他明白,这不仅是组长对他的鼓励,更是一份期待与责任的传递。心中顿时涌起一股暖流,他暗自立誓:今后的每一次开发,必将怀揣严谨的态度,赋予每一行代码以深刻的责任感,而不再仅仅是为了完成任务。
在回家的路上,组员默默在心中念道:“这次bug
排查,不仅修复了代码,更矫正了我对待开发工作的态度。感谢组长,给予我如此宝贵的经验和鼓励。”他深知,从这次经历中所学到的,绝不仅是技术层面的知识,更需要以一种成熟与稳重的心态,来面对未来的每一个挑战。
怀着这样的领悟,组员的内心充满了期待。他坚信,这必将成为他在开发道路上迈向更高境界的起点。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21394,转载请注明出处。
评论0