lerna使用npm link引用本地的vue3组件时,onMounted的instance对象丢失

344 阅读2分钟

问题

我使用lerna创建了两个vue3项目manage和client,manage项目使用npm link引入client项目,manage项目的APP组件引入client项目的HelloWorld组件,如果在HelloWorld中使用onMounted时,会提示onMounted内部使用了异步操作,但是onMounted仅仅运行了console.log()。

说一下我具体操作。

1.manage项目使用npm link client将client项目以包的形式引入其中

2.manager项目App组件使用client项目的组件HelloWorld App组件

<template>
  <div>
    <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
    <HelloWorld />
  </div>
</template>

<script lang="ts">
import { HelloWorld } from 'client';
import { defineComponent } from 'vue';

// console.log('HelloWorld', HelloWorld.setup({msg: 'aaaa'}, {}));

export default defineComponent({
  name: 'App',
  components: {
    HelloWorld
  }
})
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

3.client项目的组件HelloWorld加入onMounted

HelloWrold组件代码

<template>
  <div>
    1111
  </div>
</template>

<script lang="ts">
import { onMounted, defineComponent } from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup() {
    onMounted(() => {
      console.log('client');
    });
    return {}
  }
})
</script>

client项目中的hellorWorld组件的onMounted会丢失组件对象,并爆出以下错误

image.png 我onMounted内部仅仅只行了console操作

问题复现

项目地址为github.com/thecoolbb/l…

  1. 从上述仓库拉取代码
  2. 进入client和manage项目运行npm i
  3. 在client项目中运行sudo npm link
  4. 在manage项目中运行npm link client
  5. 在manage项目中运行npm run serve 上述操作完成即可看到上述错误,上述错误是因为在client项目中的HelloWorld中使用onMounted方法,导致解析时上下文环境丢失,instance对象为空。

已有调查

在onMounted前进行debugger

import { onMounted, defineComponent, getCurrentInstance } from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup() {
    debugger
    const instance = getCurrentInstance();
    console.log('instance', instance);
    onMounted(() => {
      console.log('client');
    });
    return {}
  }
})

getCuttentInstance函数运行时的文件如下,并且currentInstance对象为空

image.png 而setup运行完毕时对instance对象进行释放时的文件如下,并且currentInstance对象不为空 image.png 大家是否遇到过这个问题,如何解决的?

解决办法

从上述分析上来看,原因可能是因为HelloWorld进行解析时,内部使用的onMounted和getCuttentInstance相当于闭包,使用的是clien项目中的vue模块。

HelloWorld组件被引入manage项目使用,编译采用的是manage项目中的vue模块,所以编译和内部onMonted的vue模块环境不同,clien项目中的vue模块其实没有对应的instance。

解决思路就是借助lerna的模块可以共用主模块的node_modules,所以client和manage项目可以共用主模块node_modules下的vue包,此时问题解决完毕。