迁移至Webpack/ES6时Angular依赖注入失败问题排查
解决Error: [$injector:unpr] Unknown provider: $mdPanel问题
你完全猜对了!问题的根源就是你把factory服务当成Angular模块依赖引入了,这完全不符合Angular 1.x的模块依赖规则。让我一步步拆解问题并给出修复方案:
问题核心分析
- 当你用
<script>标签引入库时,库的自执行函数会直接注册mdColorMenu模块(包含它的所有依赖:ngAria、ngAnimate、ngMaterial),同时声明mdPickerColors工厂服务。 - 但在Webpack环境下,你导入的
mdPickerColors是库导出的工厂函数本身,而不是mdColorMenu模块。你把这个函数放到模块依赖数组里,Angular根本不知道这是啥,自然不会加载mdColorMenu模块及其依赖的ngMaterial(也就是$mdPanel的来源),所以才会报错找不到$mdPanel。
修复步骤
1. 修正index.js的模块引入方式
你不需要导入工厂函数,只需要导入库本身(让它执行注册mdColorMenu模块的代码),然后在模块依赖中使用模块名称字符串'mdColorMenu':
import angular from 'angular'; import myService from './myService'; // 只需要导入库,执行其注册模块的代码,不需要接收导出值 import 'md-color-menu'; export default angular.module('myModule', ['mdColorMenu']) .service('myService', myService) .name;
2. 保留myService.js的注入逻辑
你的myService.js注入mdPickerColors是完全正确的,因为mdColorMenu模块已经被作为依赖加载,Angular可以正常找到这个工厂服务:
import angular from 'angular'; export default function myService(mdPickerColors, /*...*/) { // 这里可以正常使用mdPickerColors服务 } // 别忘了显式声明依赖(如果开启严格注入模式的话) myService.$inject = ['mdPickerColors', /*...*/];
3. 可选:优化库的UMD导出(最小修改)
如果想让库在Webpack下更直观,可以稍微调整库的导出,同时支持模块名称导出,但这不是必须的:
(function() { // only added part to the library if (typeof module === 'object' && module.exports) { // 同时导出服务和模块名称,方便用户选择 module.exports = { mdPickerColors: mdPickerColors, moduleName: 'mdColorMenu' }; } // end of added part angular .module('mdColorMenu', ['ngAria', 'ngAnimate', 'ngMaterial']) .factory('mdPickerColors', ['$mdColorPalette', '$mdPanel', mdPickerColors]) .directive('mdColorMenu', mdColorMenuDirective); function mdPickerColors($mdColorPalette, $mdPanel) { //... } //... })();
之后在index.js里可以这么用:
import { moduleName as mdColorMenuModule } from 'md-color-menu'; export default angular.module('myModule', [mdColorMenuModule]) // ... 其余代码不变
为什么$mdColorPalette看起来正常?
巧合而已——$mdColorPalette是Angular Material的核心服务,可能你的项目中其他地方已经间接引入了ngMaterial模块,所以它能被找到,但$mdPanel是属于mdColorMenu模块直接依赖的部分,没有加载模块自然找不到。
内容的提问来源于stack exchange,提问作者Stilltorik
相关产品推荐
相关产品推荐

