面试题答案
一键面试实现思路
- 基于Vue Router:
- 在定义路由时,使用
import()
语法进行动态导入组件。例如,在router/index.js
中,原本可能是import Home from '@/views/Home.vue';
,现在改为const Home = () => import('@/views/Home.vue');
。这样当路由匹配到Home
组件时才会加载该组件,而不是在应用启动时就加载所有组件。 - Webpack会将动态导入的组件分割成单独的chunk文件,在需要时通过HTTP请求加载。
- 在定义路由时,使用
- 基于React Router:
- 在使用
React.lazy
和Suspense
配合实现按需加载。例如,在路由配置组件中,const Home = React.lazy(() => import('./Home'));
。然后在渲染Home
组件的地方包裹<Suspense>
组件,以处理加载状态。
- 在使用
处理动态导入过程中的错误
- 基于Vue Router:
- 使用
Promise.catch
来捕获动态导入过程中的错误。在路由配置中,可以这样处理:
const Home = () => import('@/views/Home.vue') .catch((error) => { // 这里可以记录错误日志,或者显示一个通用的错误页面 console.error('Error loading Home component:', error); // 返回一个替代组件,例如错误提示组件 return import('@/views/Error.vue'); });
- 使用
- 基于React Router:
- 在
Suspense
组件中,可以使用fallback
属性来显示加载过程中的加载状态,并且在ErrorBoundary
组件中捕获动态导入组件渲染过程中的错误。例如:
import React, { Suspense, ErrorBoundary } from'react'; const Home = React.lazy(() => import('./Home')); const ErrorFallback = () => { return <div>Error loading component</div>; }; const App = () => { return ( <ErrorBoundary fallback={<ErrorFallback />}> <Suspense fallback={<div>Loading...</div>}> <Home /> </Suspense> </ErrorBoundary> ); };
- 在
对动态导入的模块进行预加载以优化用户体验
- 基于Vue Router:
- 在路由导航守卫中使用
router.beforeEach
,当路由即将切换时,提前加载下一个路由组件。例如:
router.beforeEach((to, from, next) => { const matched = router.getMatchedComponents(to); const prevMatched = router.getMatchedComponents(from); let diffed = false; const activated = matched.filter((c, i) => { return diffed || (diffed = (prevMatched[i]!== c)); }); if (!activated.length) { return next(); } Promise.all(activated.map((c) => { if (typeof c === 'function') { return c(); } })).then(() => { next(); }).catch(next); });
- 在路由导航守卫中使用
- 基于React Router:
- 可以使用
React.lazy
配合preload
指令。在Webpack 4.6+版本中,可以通过在output.publicPath
中设置[contenthash]
,然后在HTML模板中添加<link rel="preload" href="path/to/your/chunk.js" as="script">
,这里path/to/your/chunk.js
是动态导入组件生成的chunk文件路径。在React中,可以在路由组件渲染前通过import()
进行预加载,例如:
const preloadHome = () => import('./Home'); const App = () => { useEffect(() => { preloadHome(); }, []); const Home = React.lazy(() => import('./Home')); return ( <Suspense fallback={<div>Loading...</div>}> <Home /> </Suspense> ); };
- 可以使用
关键代码示例
- Vue Router动态导入
router/index.js
import Vue from 'vue'; import Router from 'vue-router'; const Home = () => import('@/views/Home.vue'); const About = () => import('@/views/About.vue'); Vue.use(Router); export default new Router({ routes: [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', component: About } ] });
- React Router动态导入
App.js
import React, { Suspense, lazy } from'react'; import { BrowserRouter as Router, Routes, Route } from'react-router-dom'; const Home = lazy(() => import('./Home')); const About = lazy(() => import('./About')); const App = () => { return ( <Router> <Routes> <Route path="/" element={ <Suspense fallback={<div>Loading...</div>}> <Home /> </Suspense> } /> <Route path="/about" element={ <Suspense fallback={<div>Loading...</div>}> <About /> </Suspense> } /> </Routes> </Router> ); }; export default App;