工具链
说一下日常使用 Vue 中涉及那些工具链?
答案
按照项目流程常用工具如下
项目流程 | 工具链 |
---|---|
脚手架 | Vite 涉及 @vitejs/plugin-vue 、 Vue CLI 基于 webpack 涉及 vue-loader 。用来处理 Vue 单文件打包 |
IDE 支持 | Vue officail 提供 IDE 类型等提示、Vue Devtools 调试工具 |
代码规范 | eslint-plugin-vue 提供 Vue 代码规范,prettier 提供代码格式化 |
路由 | Vue Router 提供路由功能 |
状态管理 | Pinia 或 Vuex |
测试 | vitest, jest,mocha 等 |
UI 库 | element-plus, ant-design-vue等, 详见 Vue UI |
工具库 | vueuse、vue-i18n 等 |
文档工具 | vitepress、vuepress 等 |
demo、原型验证 | Vue SFC Playground 提供在线验证 Vue 单文件组件的功能 |
说一下用过 Vue Router 哪些功能 ?
答案
功能 | 说明 |
---|---|
基础使用 | 通过 `` 注册路由,RouterLink、RouterView 设置路由跳转和路由视图。核心的路由配置为 routers 数组,配置每个路由的信息,支持嵌套, { path: '/', component: HomeView, children: [] } history 配置路由模式 |
路由参数 | 支持配置 { path: '/o/:orderId' } 或 { path: '/user-:afterUser(.*)'} 实现复杂的路由匹配,其中 : 表示动态参数,可以通过 $route.params.orderId 或 $route.params.afterUser 的方式访问到 |
导航守卫 | 支持全局和局部的路由守卫,beforeEach、beforeResolve、afterEach 等钩子函数,可以在路由跳转前后做一些处理,比如权限校验、数据预加载等 |
路由原信息 | 支持在路由配置中添加 meta 信息,比如 meta: { title: '首页', requiresAuth: true } ,可以在路由守卫中进行判断 |
路由插槽 | 支持在路由视图中使用插槽,<router-view name="header" /> ,可以实现多个视图的嵌套 |
动态路由 | 支持动态路由的添加和删除,可以通过 router.addRoute() 和 router.removeRoute() 方法来实现 |
Vue Router histroy 和 hash 模式有什么区别?
答案
在 Vue Router 3.x 对应 mode
配置,4.x 叫做 history
对应值如下。
3.x | 4.x | 含义 |
---|---|---|
history | createWebHistory() | 采用 URL path 结合服务端配置实现路由 |
hash | createWebHashHistory() | 采用 URL 规范中的 hash 字段作为路由 |
abstract | createMemoryHistory() | 在内存中存储路由信息 |
路由守卫
路由守卫是 Vue Router 提供的一种机制,用于在路由导航过程中对路由进行拦截和控制。通过使用路由守卫,我们可以在路由导航前、导航后、导航中断等不同的阶段执行相应的逻辑。
Vue Router 提供了三种类型的路由守卫:
-
全局前置守卫(Global Before Guards):在路由切换之前被调用,可以用于进行全局的权限校验或者路由跳转拦截等操作。
-
路由独享守卫(Per-Route Guards):在特定的路由配置中定义的守卫。这些守卫只会在当前路由匹配成功时被调用。
-
组件内的守卫(In-Component Guards):在组件实例内部定义的守卫。这些守卫可以在组件内部对路由的变化进行相应的处理。
- 全局前置守卫
router.beforeEach((to, from, next) => {
// to: 即将进入的目标
// from:当前导航正要离开的路由
return false // 返回false用于取消导航
// return { name: 'Login' } // 返回到对应name的页面
// next({ name: 'Login' }) // 进入到对应的页面
// next() // 放行
})
- 全局解析守卫:类似beforeEach
router.beforeResolve(to => {
if (to.meta.canCopy) {
return false // 也可取消导航
}
})
- 全局后置钩子
router.afterEach((to, from) => {
logInfo(to.fullPath)
})
- 导航错误钩子,导航发生错误调用
router.onError(error => {
logError(error)
})
- 路由独享守卫,beforeEnter可以传入单个函数,也可传入多个函数。
function dealParams (to) {
// ...
}
function dealPermission (to) {
// ...
}
const routes = [
{
path: '/home',
component: Home,
beforeEnter: (to, from) => {
return false // 取消导航
}
// beforeEnter: [dealParams, dealPermission]
}
]
组件内的守卫
const Home = {
template: '...',
beforeRouteEnter (to, from) {
// 此时组件实例还未被创建,不能获取this
},
beforeRouteUpdate (to, from) {
// 当前路由改变,但是组件被复用的时候调用,此时组件已挂载好
},
beforeRouteLeave (to, from) {
// 导航离开渲染组件的对应路由时调用
}
}
vuex 和 Pinia 有什么区别
Vuex 和 Pinia 都是用于 Vue 应用程序的状态管理库,它们有一些相似之处,但也存在一些差异。以下是它们的对比:
一、相似之处
- 集中式状态管理:
- 两者都提供了一种集中式的方式来管理应用程序的状态。这使得状态可以在不同的组件之间共享,并且可以更容易地跟踪和调试状态的变化。
- 例如,在一个电商应用中,用户的购物车状态可以存储在状态管理库中,以便在不同的页面和组件中访问和更新。
- 响应式状态:
- Vuex 和 Pinia 都与 Vue 的响应式系统集成,使得状态的变化可以自动触发相关组件的重新渲染。
- 当购物车中的商品数量发生变化时,相关的组件可以自动更新以反映这个变化。
二、不同之处
- 语法和 API:
-
Pinia:
-
Pinia 提供了一种更加简洁和直观的 API。它使用类似于 Vue 组件的语法来定义状态和操作,使得代码更加易读和易于维护。
-
例如,定义一个 store 可以像这样:
import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
state: () => ({
items: []
}),
actions: {
addItem (item) {
this.items.push(item)
}
}
})
-
Vuex:
-
Vuex 的语法相对较为复杂,需要定义 mutations、actions 和 getters 等不同的概念来管理状态。
-
例如,定义一个 store 可能如下所示:
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
items: []
},
mutations: {
ADD_ITEM (state, item) {
state.items.push(item)
}
},
actions: {
addItem ({ commit }, item) {
commit('ADD_ITEM', item)
}
},
getters: {
cartItems: (state) => state.items
}
})
- 模块系统:
-
Pinia:
-
Pinia 的模块系统更加灵活和易于使用。可以轻松地将 store 拆分为多个模块,并且可以在不同的模块之间共享状态和操作。
-
例如,可以创建一个名为
user
的模块和一个名为cart
的模块,并在它们之间共享一些状态和操作:
import { defineStore } from 'pinia'
const useUserStore = defineStore('user', {
// ...
})
const useCartStore = defineStore('cart', {
state: () => ({
// ...
}),
actions: {
addItem (item) {
// 可以访问 userStore 的状态
if (useUserStore().isLoggedIn) {
// ...
}
}
}
})
- Vuex:
- Vuex 的模块系统也很强大,但相对来说更加复杂。需要使用命名空间来区分不同模块的 actions、mutations 和 getters,并且在模块之间共享状态和操作需要一些额外的配置。
- 类型支持:
-
Pinia:
-
Pinia 对 TypeScript 的支持非常好,可以轻松地为 store 定义类型,并且在开发过程中可以获得更好的类型提示和错误检查。
-
例如,可以使用 TypeScript 来定义一个 store 的类型:
import { defineStore } from 'pinia'
interface CartItem {
id: number;
name: string;
price: number;
}
export const useCartStore = defineStore('cart', {
state: () => ({
items: [] as CartItem[]
})
// ...
})
- Vuex:
- Vuex 也支持 TypeScript,但相对来说需要一些额外的配置和类型定义文件来获得更好的类型支持。
- 开发体验:
- Pinia:
- Pinia 提供了一些开发工具,如 Pinia Devtools,可以方便地调试和检查 store 的状态和操作。它还与 Vue Devtools 集成,使得在开发过程中可以更好地跟踪状态的变化。
- Pinia 的 API 更加简洁,使得开发过程更加高效和愉快。
- Vuex:
- Vuex 也有一些开发工具,如 Vuex Devtools,但相对来说功能可能没有 Pinia Devtools 那么强大。
- Vuex 的语法相对较为复杂,可能需要一些时间来适应和掌握。
总的来说,Pinia 和 Vuex 都是强大的状态管理库,选择哪一个取决于你的具体需求和个人偏好。如果你喜欢简洁和直观的 API,并且对 TypeScript 有较好的支持需求,那么 Pinia 可能是一个更好的选择。如果你已经熟悉 Vuex 并且对其功能和模块系统有特定的需求,那么 Vuex 也是一个可靠的选择。
vuex 原理
针对 Vue 做过哪些性能优化
vue3 相比较于 vue2 在编译阶段有哪些改进
Vue 3 在编译阶段相对于 Vue 2 进行了一些重要的改进,主要包括以下几个方面:
-
静态模板提升(Static Template Hoisting):Vue 3 引入了静态模板提升技术,通过对模板进行分析和优化,将模板编译为更简洁、更高效的渲染函数。这种优化可以减少不必要的运行时开销,并提高组件的渲染性能。
-
Fragments 片段支持:Vue 3 支持使用 Fragments 片段来包裹多个根级元素,而不需要额外的父元素。这样可以避免在编译阶段为每个组件生成额外的包裹元素,减少了虚拟 DOM 树的层级,提高了渲染性能。
-
静态属性提升(Static Props Hoisting):Vue 3 在编译阶段对静态属性进行了优化,将静态属性从渲染函数中提取出来,只在组件初始化时计算一次,并在后续的渲染中重用。这样可以减少不必要的属性计算和传递,提高了组件的渲染性能。
-
事件处理函数的内联化:Vue 3 在编译阶段对事件处理函数进行了内联化,将事件处理函数直接写入模板中,而不是在运行时动态生成。这样可以减少运行时的事件绑定和查找开销,提高了事件处理的性能。
-
静态节点提升(Static Node Hoisting):Vue 3 通过静态节点提升技术,将静态的节点在编译阶段进行处理,避免了在每次渲染时对静态节点的比对和更新操作,提高了渲染性能。
-
缓存事件处理器(Cached Event Handlers):Vue 3 在编译阶段对事件处理器进行了缓存,避免了重复创建事件处理函数的开销。对于相同的事件处理器,只会创建一次,并在组件的生命周期中重复使用,减少了内存占用和运行时开销。
-
更细粒度的组件分割(Fine-Grained Component Splitting):Vue 3 支持更细粒度的组件分割,可以将组件的模板、脚本和样式进行独立的编译和加载,以实现更好的代码拆分和按需加载,提高了应用的加载速度和性能。
这些改进使得 Vue 3 在编译阶段能够生成更优化的代码,减少了不必要的运行时开销,并提高了组件的渲染性能和整体的运行效率。