React项目引入Morris.js遇模块未找到及类型问题求助
解决React+TypeScript项目中Morris.js的模块导入与类型问题
1. 安装所有必要依赖
Morris.js依赖jQuery和Raphael,必须同时安装核心包及类型定义:
npm install morris.js jquery raphael npm install @types/morris.js @types/jquery @types/raphael --save-dev
2. 修正模块导入逻辑
Morris.js采用UMD模块结构,直接ES模块导入可能失效,改用全局挂载依赖后导入的方式:
import React, { useEffect } from 'react'; import 'morris.js/morris.css'; // 先导入依赖并挂载到全局 import $ from 'jquery'; import Raphael from 'raphael'; window.$ = $; window.Raphael = Raphael; // 再导入Morris import Morris from 'morris.js';
3. 完善类型声明文件
如果@types/morris.js仍无法覆盖需求,或自定义类型未生效,确保morris.js.d.ts放在src目录下,补充完整类型:
declare module 'morris.js' { interface BaseChartOptions { element: string | HTMLElement; data: Array<Record<string, string | number>>; xkey: string; ykeys: string[]; labels: string[]; hideHover?: 'auto' | boolean; resize?: boolean; } interface MorrisAreaOptions extends BaseChartOptions { behaveLikeLine?: boolean; pointFillColors?: string[]; lineColors?: string[]; fillOpacity?: number; } interface MorrisStatic { Area(options: MorrisAreaOptions): void; Line(options: BaseChartOptions): void; Bar(options: BaseChartOptions): void; } const Morris: MorrisStatic; export default Morris; }
同时在tsconfig.json中确保类型目录被识别:
{ "compilerOptions": { "typeRoots": ["./node_modules/@types", "./src"] } }
4. 解决ESLint路径解析错误
在.eslintrc.js中添加配置,让ESLint识别Morris.js模块:
module.exports = { settings: { 'import/resolver': { node: { extensions: ['.js', '.jsx', '.ts', '.tsx'], moduleDirectory: ['node_modules', 'src/'] } } } };
5. 优化组件代码(含内存泄漏处理)
修改后的组件代码示例:
import React, { useEffect } from 'react'; import 'morris.js/morris.css'; import $ from 'jquery'; import Raphael from 'raphael'; import Morris from 'morris.js'; const CustomChart: React.FC = () => { useEffect(() => { const chartElement = document.getElementById('area-chart'); if (!chartElement) return; Morris.Area({ element: chartElement, data: [ { y: '2014', a: 150, b: 150 }, { y: '2015', a: 135, b: 120 }, { y: '2016', a: 135, b: 140 }, { y: '2017', a: 120, b: 125 }, { y: '2018', a: 105, b: 110 }, { y: '2019', a: 90, b: 105 }, { y: '2020', a: 75, b: 60 }, { y: '2021', a: 60, b: 45 }, { y: '2022', a: 45, b: 35 }, { y: '2023', a: 30, b: 25 }, { y: '2024', a: 15, b: 10 }, { y: '2025', a: 0, b: 10 }, ], xkey: 'y', ykeys: ['a', 'b'], labels: ['Total Income', 'Total Outcome'], hideHover: 'auto', behaveLikeLine: true, resize: true, pointFillColors: ['#1B7837', '#800026'], lineColors: ['#5AAE61', '#800026'], fillOpacity: 0.2, }); // 组件卸载时清理图表,避免内存泄漏 return () => { $(chartElement).empty(); }; }, []); return ( <div> <h3 className='text-primary text-center'>Sprint Chart</h3> <div className='row'> <div className='col-sm-6 text-center'> <label className='label label-success'>Area Chart</label> <div id='area-chart' style={{ minHeight: '450px' }} /> </div> </div> </div> ); }; export default CustomChart;
内容的提问来源于stack exchange,提问作者Nguyễn Mạnh Cường
相关产品推荐
相关产品推荐

