AngularJS集成Vue2切换路由时离开组件created/mounted异常触发
AngularJS集成Vue2组件切换时生命周期重复触发问题
环境说明
- 项目基于AngularJS实现导航栏,在Home/Support等导航选项间切换时,会加载对应关联的Vue 2组件
- Vue侧项目通过
npm run build-lib命令构建产出名为myVueApp的库,通过npm link关联到AngularJS应用,集成方案使用ngVue库
现有实现代码
AngularJS侧Vue组件注册逻辑
(function() { 'use strict'; if (typeof myVueApp !== 'undefined') { var VueContainer = myVueApp.components.VueContainer, plugins = myVueApp.plugins; } angular .module('my.vue.config', ['ngVue', 'ngVue.plugins']) .config(function($ngVueProvider) { $ngVueProvider.setRootVueInstanceProps(plugins); }) // 注册Vue组件 .value('VueContainer', VueContainer); })();
HTML侧组件加载示例(AngularJS项目Home.html)
<div> <vue-component name="VueContainer"></vue-component> </div>
AngularJS路由配置
var ngModule = angular.module('home.content', ['ui.router']); ngModule.config(function ($stateProvider) { $stateProvider .state('home.content', { url: '?home&t', controller: 'HomeCtrl as HomeCtrl ', templateUrl: '/views/home.html', resolve: { }, onEnter: function(){ } });
示例Vue组件代码
HomeComponent.vue:
async created() { // 切换到其他组件时该钩子会被异常触发 await this.getHomeData(); this.loading = false; }
SupportComponent.vue:
created() { // 切换到其他组件时该钩子会被异常触发 this.$store.dispatch('getAllSupportProp'); this.loadDetails(); }
问题表现
在AngularJS应用内从HomeComponent.vue切换到SupportComponent.vue,或做反向切换时,离开的原组件、待加载的目标组件的created/mounted生命周期事件都会触发。
预期表现:仅触发当前待加载目标组件的
created事件
对照验证:单独运行Vue应用(不集成AngularJS)时无该问题,离开的组件不会触发创建、挂载类生命周期钩子。
根因分析
该问题由两个原因共同导致:
- ngVue默认没有绑定AngularJS作用域的销毁事件,AngularJS路由切换移除旧页面DOM时,对应挂载的Vue实例不会被自动调用
$destroy()方法销毁,旧实例残留在内存中会异常触发生命周期 - 不同路由页面使用了同名的
<vue-component>标签且未设置独立key,Vue和AngularJS在路由切换时会错误复用DOM节点,导致新旧组件逻辑同时执行
修复方案
- 新增全局指令统一处理Vue实例销毁逻辑,在AngularJS作用域销毁时手动清理关联的Vue实例:
angular.module('my.vue.config') .directive('vueComponent', function() { return { restrict: 'E', link: function(scope, el) { scope.$on('$destroy', function() { const vueInstance = el[0].__vue__; if (vueInstance && !vueInstance._isDestroyed) { vueInstance.$destroy(); } }); } } });
- 给每个路由页面对应的
<vue-component>设置和路由绑定的唯一key,强制框架区分新旧节点,避免错误复用:
Home.html调整后代码:
Support.html对应调整为专属key即可,例如<div> <vue-component name="VueContainer" key="'home-page'"></vue-component> </div>key="'support-page'" - 修复后验证:路由切换时旧组件会正常触发销毁类生命周期钩子,仅新进入的目标组件触发
created/mounted,和独立运行Vue应用的表现完全一致。
内容的提问来源于stack exchange,提问作者Manish Choudhary
相关产品推荐
相关产品推荐

