简单记录一下最近工作中遇到的关于循环依赖的问题

先上简化后的代码

html 复制代码
<!-- /index.html -->
<html lang="en">
  <body>
    <script type="module" src="./src/main.js"></script>
  </body>
</html>
js 复制代码
// /src/main.js Main组件
import A from './a.js'

export const ENUMS = {
  X: 1,
  Y: 2,
}

export function fn() {
  console.log('这是Main组件的一个函数')
}

console.log(A, '渲染A组件')
js 复制代码
// /src/a.js A组件
import { ENUMS, fn } from './main.js'

fn()
console.log(ENUMS, '使用枚举值')

export default 'A'

场景说明

html 是测试文件,这个不用说。我们这里有两个组件,Main 组件和 A 组件。A 组件是 Main 组件的子功能模块,所以 在 Main 组件中用到了并渲染了 A 组件。A 组件同时又用到了 Main 组件提供的公共静态数据(动态公共数据通过属性传),比如枚举数据。因为这些数据将来可能会在其它的子功能组件中用到,所以把枚举这样的公共数据就维护在了父组件中。

父组件需要子组件来渲染 UI,子组件需要使用到父组件维护的公共静态数据,这样一来就出现了循环依赖

由于模块加载的策略是深度优先遍历,所以在子模块的加载过程中,父模块的ENUMS还没有加载完成,所以console.log(ENUMS, '使用枚举值')会报错。如下:

为什么函数可以成功执行?

报错倒是没什么问题,很好理解。但是神奇的是同样的导入导出,为什么函数却执行成功了?

我立马想到的猜测是:可能是变量提升,于是我将 const 改成了 var。

js 复制代码
// /src/main.js Main组件
import A from './a.js'

export var ENUMS = {
  X: 1,
  Y: 2,
}

export function fn() {
  console.log('这是Main组件的一个函数')
}

console.log(A, '渲染A组件')

果不其然,测试结果如下:

问题到这里就很清楚了,就是函数之所以可以执行是因为函数提升。

函数提升与变量提升

都到这里我们就顺便复习一下函数(function 声明的函数 )提升和变量(var 声明的变量)提升。

  • 函数提升的是实现 ;变量提升的是声明
  • 函数比变量提升的更早

解决方案

以下是我目前能立刻想到的两个比较简单的方案

方案一:单独抽取文件

比如都提取到 utils.js

js 复制代码
// /src/a.js A组件
import { ENUMS, fn } from './utils.js'

fn()
console.log(ENUMS, '使用枚举值')

export default 'A'

大家可以根据具体实际场景再细化

方案二:延迟使用

js 复制代码
// /src/a.js A组件
import { ENUMS, fn } from './utils.js'

setTimeout(() => {
  fn()
  console.log(ENUMS, '使用枚举值')
})

export default 'A'

这里的 setTimeout 就好比我们在组件中使用,因为组件不可能是我们文件一加载就立即实例化(这也是我们平时遇上循环依赖也基本不会出问题的原因,因为基本上都是在组件中使用的)。

但是我今天遇到的场景又特殊一点,就是我想用枚举数据来做一个组件 Map,而很显然组件 Map 这样的数据也是静态的,所以我就把它提升到组件外部,进而就遇到了这个问题。大概是这样:

js 复制代码
// /src/a.js A组件
import { ENUMS } from './main.js'
import X from './x.js'
import Y from './y.js'

const CompMap = {
  [ENUMS.X]: X,
  [ENUMS.Y]: Y,
}
相关推荐
懒大王952731 分钟前
uni-app + Vue3 + EZUIKit.js 播放视频流
开发语言·javascript·uni-app
xkroy1 小时前
ajax
前端·javascript·ajax
Yvonne爱编码1 小时前
AJAX入门-URL、参数查询、案例查询
前端·javascript·ajax
Swift社区1 小时前
如何解决 Vue2 前端项目为何无法访问本地资源(chunk.js 加载一直 pending/转圈)
开发语言·前端·javascript
清风细雨_林木木2 小时前
Vue加载资源‘如图片’的“直接引入“方式和“request()“的区别
前端·javascript·vue.js
BillKu2 小时前
Vue3应用执行流程详解
前端·javascript·vue.js
欧阳天风3 小时前
链表运用到响应式中
javascript·数据结构·链表
前端农民工ws3 小时前
Vue 框架的 markdown 渲染组件,针对 AI 的 markdown 流式传输场景
前端·javascript·vue.js·ai
百思可瑞教育4 小时前
Vue 生命周期详解:从初始化到销毁的全过程剖析
前端·javascript·vue.js·前端框架·uni-app·北京百思可瑞教育·百思可瑞教育
星语卿5 小时前
Vuetify:构建优雅Vue应用的Material Design组件库
前端·javascript·vue.js