Vue3 用 rollup 打包组件后 组件 setup 中的 onMounted 不生效

我用 rollup 打包了一个 vue3 组件,组件代码:

// main.vue
<template>
  <div>
    <div @click="clickDiv">{{ 1 }}</div>
    <div ref="divRef"></div>
  </div>
</template>
<script>
import { onMounted, ref, defineComponent } from 'vue'
export default defineComponent({
  name: 'Vue3Component',
  mounted () {
    console.log('component mounted') // it works well
  },
  setup() {
    const divRef = ref()
    const clickDiv = () => {
      console.log('divRef', divRef) // it causes some warnings
    }
    onMounted(() => {
      console.log('component onMounted') // it causes some warnings
    })
    return {
      a: ref(1),
      clickDiv,
      divRef
    }
  },
})
</script>

入口文件:

// index.js
import Vue3Component from './main.vue'
Vue3Component.install = (app) => {
  app.component(Vue3Component.name, Vue3Component)
}

export {
  Vue3Component
}

rollup 配置文件:

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import pkg from './package.json'
import external from 'rollup-plugin-peer-deps-external'
import vuePlugin from 'rollup-plugin-vue'

const extensions = ['.vue', '.js']

const globals = {
  vue: 'Vue',
  'highlight.js': 'hljs',
  'marked': 'marked'
}

export default [
  {
    input: 'src/index.js',
    output: [
      {
        name: 'VueNextMEditor',
        file: pkg.main,
        format: 'umd',
        globals
      },
      {
        file: pkg.module,
        format: 'es'
      },
      {
        name: 'VueNextMEditor',
        file: pkg.unpkg,
        format: 'umd',
        plugins: [terser()],
        globals
      }
    ],
    plugins: [
      external(),
      vuePlugin(),
      resolve(),
      commonjs({ extensions })
    ]
  }
]

当我在组件根目录下用 vue-cli 生成了一个 example 项目调试这个组件时,我发现 setup 中的 onMounted 方法没有生效,产生了如下警告:

[Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup(). If you are using async setup(), make sure to register lifecycle hooks before the first await statement.

ref 也产生了警告:

[Vue warn]: Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function. 
  at <Vue3Component> 
  at <App>

但是 setup 外面的 mounted 函数是可以正常执行的,就很奇怪。
不知道是我打包出现了问题还是组件引用产生了问题。项目完整地址:
项目地址

阅读 11.3k
4 个回答

找到原因了。因为我在组件和example中安装了两个vue依赖。解决方法是我只在根目录下安装vue,然后在example中用 pnpm link ../node_modules/vue 就可以。

vue3有2种写法:components apioptions api
mountedoptions apisetup 内的onMountedcomponents api,不要混写。

新手上路,请多包涵

我也遇到这问题了,全网找了一遍都没人能回答,换成vite打包就可以了,还不需要配那么多乱七八糟的东西

import { resolve } from 'path';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
export default defineConfig({
  server: {
    host: true,
    port: 9527,
  },
  plugins: [vue(), vueJsx()],
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
      },
    },
  },
  build: {
    lib: {
      entry: resolve(__dirname, 'components/index.ts'), // 设置入口文件
      name: 'vue-component', // 起个名字,安装、引入用
      fileName: (format) => `vue-component.${format}.js`,
    },
    rollupOptions: {
      external: ['vue'],
      output: {
        globals: {
          vue: 'Vue',
        },
      },
    },
  },
});
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题