记录Vue开发过程中遇到的问题,测试环境以及本地显示都没有问题,但是一上线就出现问题,于是对于这个问题进行排查,在此记录排查问题的步骤以及方法,希望对大家有帮助。
错误信息:Uncaught TypeError: Cannot read properties of undefined(reading ‘refs’)
更新:我觉得
devlopment
环境下报警告而
production
环境之间报错的处理不够友好
于是我给
Vue
提了一个
issue
,希望能做些优化,具体的问题读完全文后不懂的话可以去看这个issue
此项目是基于naive-ui+vite进行开发的
线上报错信息以及显示如下:
测试环境和本地显示如下:
如何查找问题?
- 先确定问题出在哪里,尽管这是线上环境,但是我们依旧可以从报错信息里找到对应的错误文件。- 打开错误的更多信息进行文件查看,这里一看全是打包后的文件,根本不知道是哪个文件。- 所以我们可以利用
sourcemap
来重新打包,附上vite
的配置export default defineConfig({ plugins: [vue(), vueJsx()], build: { // 开启sourcemap sourcemap: true, },})
- 利用http-server进行本地打包,然后在浏览器上查看打包的问题,因为是线上问题,所以利用库打包并进行 debug。这里我们看到了错误的相关文件,只需要顺着相关文件去查找问题就行。 - 先利用现有的信息去谷歌搜索,因为很多时候这样的问题已经有人遇到过了,所以检索获取结果是最快的问题解决方案
通过谷歌搜索我们可以看出有很多条问题,那些相关的问题都可以点击去看看,是否有符合你的解决方案。(比较好的答案有
GitHub
的
issue
和
stackoverflow
以及掘金上的答案)
我直接点进去上图中框选的那条信息
根据问题结果去反查错误的相关文件,如果是相关问题就直接解决,**
推荐大家多用 vscode 的全局搜索比较方便
,文件内的话多用
ctrl+f
搜索**
- 如果网上的答案都不能解决你的问题,那么就需要开始自己
debug
了- 首先我根据错误点进去查看,看看是什么引发的错误发现是在owner context
上取refs
时无法取到,也就是说owner
是undefined
了在往上看,发现这是个production
上会报的错误,但是其实本地也会报,于是可以转为本地debug
了当然本地无法调试的情况,那么就根据文件报错的地方进行debugger
,然后重新打包调试。 - 在本地服务上进行调试
可以看到确实有警告信息了,通过源码就知道了为啥只有
production
上会有问题了,而其他环境则不会有问题。
当然这也侧面印证了我们在开发过程中也需要多多注意警告⚠️
发现在
Test
文件,上面都是一些
naive-ui
的组件,并且还是某一条
row
造成的,于是去查看对应的
row
的数据以及
columns
数据的构造。
通过
debugger
发现构造的
cell
数据的
ref
是
false
继续往下进行
debugger
, 发现走入到
setRef
里面了,并且把
ref
为
false
传入了。
到了这里就发现问题了,就是因为这个
cell
的
ref
被编译成了
false
了。
- 发现问题后开始解决问题,如果有简单的编译原理知识是更好的,没有也不重要,只要顺着调试线继续走下去就能解开一团乱线。从上面我门知道
patch
的是两个vnode
(类型也是很重要的,它让你不需要有那么多的背景知识可以快速解),那么我们就需要从vnode
下手。找到生成vnode
的ref
的地方。// vnode.tsfunction createBaseVNode( type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT, props: (Data & VNodeProps) | null = null, children: unknown = null, patchFlag = 0, dynamicProps: string[] | null = null, shapeFlag = type === Fragment ? 0 : ShapeFlags.ELEMENT, isBlockNode = false, needFullChildrenNormalization = false) { const vnode = { __v_isVNode: true, __v_skip: true, type, props, key: props && normalizeKey(props), // ref为false是因为props传入了false。。。 ref: props && normalizeRef(props), scopeId: currentScopeId, slotScopeIds: null, children, component: null, suspense: null, ssContent: null, ssFallback: null, dirs: null, transition: null, el: null, anchor: null, target: null, targetAnchor: null, staticCount: 0, shapeFlag, patchFlag, dynamicProps, dynamicChildren: null, appContext: null, ctx: currentRenderingInstance } as VNode // ... }
于是回到Test
的代码里面检查const columns = [ // .... { title: 'Address', key: 'address', width: 100, ellipsis: { tooltip: true } }, { title: 'Another Address', key: 'anotherAddress', width: 100, render(row) { // 当age大于40是会传入false,于是就G了 const ellipsisProps = row.age < 40 && { tooltip: true } // debugger; return h(NEllipsis, ellipsisProps, () => row.anotherAddress) } }]
总结
通过这次
debugger
,确实有一些问题值得总结
- 写代码还是要细心啊,如果可能多补补脑子,少犯一些低级错误。
- 调试真的不难,开启
sourcemap
打上debugger
,一步一步调试,总能找到解决的线头。
版权归原作者 cyg_l02 所有, 如有侵权,请联系我们删除。