面试题答案
一键面试路由架构设计
- 基础路由规划
- 使用 SvelteKit,它基于 Svelte 提供了强大的路由系统。按照业务模块划分路由,例如
/dashboard
、/users
、/settings
等,每个模块下可以有子路由,如/users/:id
用于用户详情页。这样的分层结构易于理解和维护,在项目规模扩大时,新增或修改路由都能保持清晰的结构。 - 对于嵌套路由,通过 SvelteKit 的约定式路由方式,在
+page.svelte
文件中使用<svelte:component this={$$route.page} />
来渲染子路由内容,使得页面结构层次分明。
- 使用 SvelteKit,它基于 Svelte 提供了强大的路由系统。按照业务模块划分路由,例如
- 权限控制与路由
- 创建一个权限中间件。在路由进入之前,通过该中间件检查用户的权限。例如,只有管理员权限的用户才能访问
/admin
路由。可以在 SvelteKit 的hooks.server.js
中实现这一逻辑,在handle
函数内检查用户权限:
- 创建一个权限中间件。在路由进入之前,通过该中间件检查用户的权限。例如,只有管理员权限的用户才能访问
import { getSession } from '$lib/utils/auth';
export async function handle({ event, resolve }) {
const session = await getSession(event);
const userPermissions = session?.permissions;
const route = event.url.pathname;
if (route.startsWith('/admin') && (!userPermissions ||!userPermissions.includes('admin'))) {
return new Response(null, {
status: 302,
headers: {
Location: '/forbidden'
}
});
}
return resolve(event);
}
- 动态调整路由状态。当权限不足的用户尝试访问特定路由时,除了重定向到合适的页面(如 `/forbidden`),还需要更新应用的状态,例如在状态管理中标记当前操作因权限不足失败,以便在 UI 上给出相应提示。
3. 多语言支持与路由
- 利用路由参数或查询参数来标识语言。例如,/en/dashboard
或 /dashboard?lang=en
。SvelteKit 可以很方便地在路由中获取这些参数。在 +page.server.js
中:
export function load({ url }) {
const lang = url.searchParams.get('lang') || 'en';
return { lang };
}
- 当语言切换时,通过路由的更新来触发页面内容的重新渲染。可以在 `+page.svelte` 中监听路由参数或查询参数的变化,从而切换语言:
<script>
import { page } from '$app/stores';
import { derived } from 'svelte/store';
const lang = derived(page, ($page) => {
return $page.url.searchParams.get('lang') || 'en';
});
$: console.log('Language changed to:', $lang);
// 根据 $lang 更新语言相关内容
</script>
状态管理架构设计
- 选择合适的状态管理库
- 对于 Svelte 应用,Svelte 自带的响应式系统已经非常强大,但对于大型应用,
mobx - svelte
或pinia
也是不错的选择。以pinia
为例,它提供了一种简单且可扩展的方式来管理状态。 - 创建不同的 store 来管理不同模块的状态。例如,
userStore
用于管理用户相关状态(登录状态、用户信息、权限等),languageStore
用于管理语言相关状态。
- 对于 Svelte 应用,Svelte 自带的响应式系统已经非常强大,但对于大型应用,
import { defineStore } from 'pinia';
export const userStore = defineStore('user', {
state: () => ({
isLoggedIn: false,
userInfo: null,
permissions: []
}),
actions: {
login(user) {
this.isLoggedIn = true;
this.userInfo = user;
this.permissions = user.permissions;
},
logout() {
this.isLoggedIn = false;
this.userInfo = null;
this.permissions = [];
}
}
});
export const languageStore = defineStore('language', {
state: () => ({
currentLang: 'en'
}),
actions: {
setLanguage(lang) {
this.currentLang = lang;
}
}
});
- 状态与路由联动
- 多语言切换:在语言切换时,不仅路由要更新,状态管理中的语言状态也要更新。例如,当通过路由参数切换语言时,在
languageStore
中更新currentLang
状态。同时,其他依赖于语言的组件可以订阅该状态变化,更新自身显示内容。
- 多语言切换:在语言切换时,不仅路由要更新,状态管理中的语言状态也要更新。例如,当通过路由参数切换语言时,在
<script>
import { languageStore } from '$lib/stores';
const langStore = languageStore();
$: console.log('Language in store:', langStore.currentLang);
</script>
- **权限控制**:当用户登录或权限发生变化时,`userStore` 中的权限状态更新。路由中间件依赖于这个状态来进行权限检查。例如,当用户权限更新后,再次访问受限路由时,中间件能基于新的权限状态做出正确的判断,同时更新页面状态(如显示或隐藏某些元素)。
3. 避免状态混乱和路由冲突
- 状态隔离:通过模块化的 store 设计,每个模块的状态相互隔离。例如,用户相关状态在 userStore
中管理,语言相关状态在 languageStore
中管理。这样在大型项目中,不同团队成员在开发不同功能时,不会相互干扰状态。
- 路由命名规范:遵循严格的路由命名规范,避免命名冲突。例如,使用统一的前缀来标识不同模块的路由,如 admin -
前缀用于管理员相关路由,user -
前缀用于普通用户相关路由。同时,在路由定义时,仔细检查是否存在重叠或歧义的路由路径。
- 状态更新跟踪:使用开发工具(如 Pinia 的 Devtools 插件)来跟踪状态的更新。这有助于在状态出现混乱时,快速定位是哪个操作导致了状态的异常变化。同时,在状态更新的方法中添加日志记录,方便排查问题。