在setup中,用插件的方式调用组件且使用了生命周期时,会得到一个警告
Vue version
@3.2.24
Link to minimal reproduction
https://codepen.io/mgsod/pen/ZExjYWx?editors=0000
Steps to reproduce
- 在生命周期钩子函数前以插件的方式调用组件
createApp({
setup() {
vant.Dialog.alert();
onMounted(() => {
console.log();
});
return {
message: "Hello Vue"
};
}
}).mount("#app");
上述代码执行时,控制台会得到如下警告
[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. at <App>
通过调试发现,vant以插件形式调用组件时,是通过createApp
实例化后调用mount()
挂载到body上。问题就在这个mount()
,如果不执行mount()
则不会发出警告.下面是vant插件调用组件的部分代码 https://github.com/vant-ui/vant/blob/dev/packages/vant/src/utils/mount-component.ts#L41
export function mountComponent(RootComponent: Component) {
const app = createApp(RootComponent);
const root = document.createElement('div');
document.body.appendChild(root);
return {
instance: app.mount(root),
unmount() {
app.unmount();
document.body.removeChild(root);
},
};
}
目前有以下两种方式可以解决这个问题:
- 将生命周期函数提前,根据警告提示,只需要把生命周期函数提前即可
const { createApp, onMounted } = Vue;
createApp({
setup() {
+ onMounted(() => {
+ console.log();
+ });
vant.Dialog.alert();
- onMounted(() => {
- console.log();
- });
return {
message: "Hello Vue"
};
}
}).mount("#app");
- 给生命周期函数传入第二个参数,
currentInstance
- const { createApp, onMounted } = Vue;
+ const { createApp, onMounted ,getCurrentInstance} = Vue;
createApp({
setup() {
+ const currentInstance = getCurrentInstance()
vant.Dialog.alert();
onMounted(() => {
console.log();
- });
+ },currentInstance);
return {
message: "Hello Vue"
};
}
}).mount("#app");
What is expected?
期望:
- 不希望得到该警告(虽然生产环境下不会发出该警告),因为我并没有使用
async
的setup
What is actually happening?
实际上:
- 控制台得到一个警告
[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.
System Info
System:
OS: macOS 11.2.3
CPU: (8) arm64 Apple M1
Memory: 237.22 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 14.17.0 - ~/.nvm/versions/node/v14.17.0/bin/node
Yarn: 1.22.17 - ~/.nvm/versions/node/v14.17.0/bin/yarn
npm: 6.14.13 - ~/.nvm/versions/node/v14.17.0/bin/npm
Browsers:
Chrome: 104.0.5112.79
Safari: 14.0.3
npmPackages:
vue: ^3.2.24 => 3.2.24
Any additional comments?
No response
Hi, thanks for your interest but Github issues are for bug reports and feature requests only. You can ask questions on the forum, the Discord server or StackOverflow.
You likely need to move the alert to an onMounted()
hook:
onMounted(() => {
console.log();
vant.Dialog.alert();
});
Hi, thanks for your interest but Github issues are for bug reports and feature requests only. You can ask questions on the forum, the Discord server or StackOverflow.
You likely need to move the alert to an
onMounted()
hook:onMounted(() => { console.log(); vant.Dialog.alert(); });
实际上的情况要比这个稍微复杂一点,比如在http请求中统一管理loading状态,请求前打开loading,请求结束后关闭loading
function httpGet() {
Loading.show()
return new Promise(resolve => {
// some code...
Loading.hide()
})
}
export default {
setup() {
httpGet()
onMounted(() => {})
}
}
这样也会得到上面的警告
我也遇到了这个问题,我自己封装了一个vue组件上传到了npm,当在项目中引入时也会有类似的警告,导致加载组件挂载不成功。 我调试vite打包后的dist
目录文件,发现setup
方法内的 onMounted
方法并未执行。