对MVVM的理解
可以将MVVM理解为一种将应用程序分为三层的设计模式,包括了视图层、数据模型层和ViewModel层。ViewModel层作为桥梁,连接视图和数据模型,负责处理数据的请求和响应,并将获取到的数据传递给视图进行展示。这种设计模式可以让应用程序更易于维护和测试。简单来说,MVVM就是一种分层架构,方便开发者在开发应用程序时分工明确,提升开发效率。
MVC和MVVM的区别
-
MVC的Controller和View是两个独立的组件,而在MVVM中,ViewModel充当Controller和View之间的中介。
-
MVVM在View和Model之间建立了双向绑定关系,当Model中的数据发生变化时,View会自动更新,因此MVVM更容易实现数据的同步,提高了程序的效率。
-
在MVVM中,ViewModel通过把View数据和Model数据绑定在一起来实现解耦,这使得代码更容易编写、理解和维护
vue组件通信的方法
-
父子组件通信(Props and Events):父组件通过props向子组件传递数据,子组件通过$emit方法触发一个自定义事件向父组件传递数据。
-
兄弟组件通信(Event Bus):可以在Vue实例中创建一个空的Vue实例作为事件总线,其他组件通过emit/on事件触发和监听事件实现兄弟组件之间的通信。
-
Vuex状态管理库:Vuex是常用的Vue组件通信方式之一,通过状态仓库存储组件的状态,方便管理和维护。
-
跨级组件通信(Provide/Inject):父组件可以通过provide方法向子孙组件提供数据,子孙组件则可以通过inject直接注入这些数据。
-
插槽(Slot):父组件通过插槽slot将子组件的内容插入到父组件中的指定位置。
-
事件总线(Event Bus):通过事件总线的方式,向事件中心发送事件,从而实现组件之间的通信。
vue的生命周期
-
beforeCreate:实例刚在内存中被创建出来,此时还没有初始化好数据/事件,组件实例的属性均为undefined,不能访问到data、methods等属性和方法。可以在此钩子函数中获取初始化数据并进行一些初始操作。
-
created:实例已经完成了数据的观测和属性的初始化,但是还没有挂载到DOM中去,不能访问到DOM节点。可以在此钩子函数中进行一些数据的操作和异步请求。
-
beforeMount:在挂载之前被调用,此时组件已经完成了编译,但是此时还没有挂载到页面中。
-
mounted:组件已经挂载到页面上,可以访问到DOM节点了,但数据可能还没有更新,可以在此钩子函数中进行DOM操作和数据初始化操作。
-
beforeUpdate:在数据更新之前被调用,此时数据可能已经发生了变化,但是还没有重新渲染页面。
-
updated:数据已经更新,重新渲染页面完成,可以进行以下操作:访问更新后的DOM元素、操作更新后的界面等。
-
beforeDestroy:在实例销毁之前调用,此时实例还可以正常使用,可以进行一些销毁前的操作。
-
destroyed:实例已经销毁,数据绑定和数据监听已经被卸除,可以进行一些善后工作和清理工作。
v-if,v-show的区别
v-if
除了控制元素是否显示外,还能控制是否渲染元素,因此切换时所需时间略长,当需要频繁切换时,性能会稍差,而v-show
只是控制元素的显示/隐藏,切换时所需时间短,当需要频繁切换时,性能会更好。v-if
适用于在运行时条件不大可能改变的情况下使用,比如只在用户登录后才显示用户信息,而v-show
适用于需要频繁切换视图的情况,比如大量使用的按钮、开关等组件- 对于初始渲染时,如果元素初始不需要被渲染出来,而后期需要渲染(比如初始时为
false
,但之后用户登录后变为true
),则应该使用v-if
,因为该元素的渲染是被控制的,不会因为不显示而被渲染掉,从而节省点加载时间。
vuex包含的属性
- state:用于存储应用程序中的数据和状态,是所有组件共享的数据源;
- getters:用于计算 state 中的数据状态,类似于 Vue 的计算属性,提供一些公共的计算逻辑;
- mutations:用于修改 state 中的数据状态,是改变状态的主要方式,且是同步的;
- actions:用于处理异步操作或复杂的业务逻辑,包含多个 mutation。可以包含任何异步操作代码,只不过多数是用来异步调用 mutation;
- modules:由于 Vuex 中 store 的状态是全局的,当应用变得复杂时,store 对象就会变得臃肿,通过模块化的方式将 store 分割为不同的 module,每个 module 此时对应着其下属模块的一部分状态和一些操作,从而使得代码分离、结构清晰。
Vue 2的响应式原理
Vue 2的响应式原理是通过 Object.defineProperty() 方法对对象进行劫持,让 Vue 能够追踪每个对象的变化,并且自动更新DOM。
具体来说,当我们定义一个 data 数据对象时,Vue 会对其进行递归遍历,将数据对象的所有属性都转换为 getter/setter,并且添加到对应的依赖追踪列表中。当被依赖的数据发生改变时,这些监听器会接到通知,并且触发重新渲染视图。
例如,当我们对一个data属性进行修改时,Vue会在依赖追踪列表中寻找这个属性的监听器,一旦找到就会将视图进行更新。
Vue 2的响应式主要有以下特点:
- 对象属性的劫持:Vue会对一个对象的每个属性进行递归遍历,将其转换为getter/setter的形式,以便在属性值发生改变时能够得到通知。
- 数组方法的变更检测:Vue会重写数组的7个变异方法(push、pop、shift、unshift、splice、sort、reverse)来监测数组的变化,并且在这些方法被调用时通知每个依赖项。
- 异步更新队列:当数据发生变化后,Vue将会开启一个异步更新队列,缓冲所有的数据变化,并且在 nextTick(一个异步的更新方法)后更新视图,以避免多次更新视图导致性能问题。
Vue 2的响应式实现是 Vue 实现数据双向绑定的重要基石,也是其高效和灵活的原因之一。但是,需要注意的是,由于 Object.defineProperty() 方法存在不兼容的问题,因此 Vue 3 采用了 Proxy 对象作为其响应式的实现方式。
watch和computed的区别
computed
:计算属性。特点是定义在计算属性中的属性一旦被访问到就会自动触发计算属性的 getter 方法。因为是缓存的,所以如果未发生依赖值的变化,计算属性会立即返回之前缓存的值,而不会再次计算。计算属性适用于需要根据一些响应式数据计算得出的逻辑属性。通常情况下,我们可以使用 computed getter 函数来定义计算属性。
watch
:观察者。特点是可以监听数据对象内部属性值的变化,并在数据变化时执行回调函数。当需要在数据变化时执行异步操作或较为复杂的操作时,比如发起 Ajax 请求、对数据做出更改等,就需要使用 watch
。
-
computed 适用于计算属性类的场景,即某个值依赖于其他数据的变化而变化的场景;watch 适用于一个数据的变化可能会引起其他数据变化的场景,或者需要进行比较复杂的业务逻辑处理的场景;
-
对于同一个数据变化,computed 可以缓存,而 watch 每次都需要执行回调。
vue中双向绑定的原理
- Vue 通过数据劫持和发布订阅模式实现数据绑定。在
new Vue()
时,会递归遍历 data 对象中的所有属性,并通过Object.defineProperty()
方法为每个属性添加 getter 和 setter 函数,以便在修改数据时,能够监听到数据变化并做出相应的响应; - 当数据发生变化时,setter 函数会通知 watcher 更新视图,而 watcher 对象则负责监听变化,当数据变化时,会通知相关的依赖项进行更新;
- 为了提高数据更新的效率,Vue 还提供了一些额外的优化策略,比如异步处理、同一 Tick 内同一个 watcher 只会被触发一次等。
v-model的原理
- 在表单元素上绑定相应的事件监听,比如 input / change;
- 在事件监听函数中通过调用组件实例的对应数据属性,实现将表单元素的值同步到组件数据中,同时将组件数据的变化同步到表单元素的值上。
vue的自定义指令和自定义指令的方法
Vue 的自定义指令(Directive)是一种用来扩展原有 HTML 元素的能力,通过 Vue 自带的指令和自定义指令可以非常方便地管理 DOM 元素和数据之间的关系,让操作 DOM 变得更加灵活和便捷。
自定义指令有以下几个特点:
- 使用
Vue.directive
函数注册指令; - 指令的钩子函数可以控制绑定元素的行为;
- 指令可以接收参数;
- 指令可以绑定到组件、DOM 元素或模板上;
- Vue 自带了一些常用的指令,如
v-if/v-show
,v-for
,v-bind
,v-model
等。
自定义指令的方法:
Vue 提供了一个全局注册自定义指令的方法 Vue.directive
,接收两个参数,第一个参数是指令名称,第二个参数是一个对象,该对象可以包含以下钩子函数:
bind(el, binding,vnode)
:只调用一次,在指令绑定到元素上时触发,可以在这里进行一些初始化工作;inserted(el, binding,vnode)
:绑定元素插入到父节点时触发,不能保证已经插入到 document 中;update(el, binding,vnode, oldVnode)
:当绑定元素的值更新时调用,而且也可以调用一次,但是可能在初始绑定时不会立即更新;componentUpdated(el, binding,vnode, oldVnode)
:组件更新完成后调用;unbind(el, binding,vnode)
:只调用一次,指令与元素解绑时触发。
vue路由守卫
Vue 路由守卫(Navigation Guards)是用来在导航到某个路由或离开某个路由时进行身份验证、切换动画等需要做的预处理任务的一种机制。Vue 提供了三种不同类型的路由守卫,分别是全局守卫、路由独享守卫和组件内守卫。
三种类型的路由守卫:
-
全局守卫:在
router
实例上调用beforeEach
、beforeResolve
、afterEach
函数,用来确认用户是否有权限进入或离开一个页面。router.beforeEach((to, from, next) => { // ... next() }) router.beforeResolve((to, from, next) => { // ... next() }) router.afterEach((to, from) => { // ... })
-
路由独享守卫:
//beforeEnter:在单个路由配置中定义。 const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... next() } } ] })
-
组件内守卫:
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // beforeRouteEnter:进入某个路由前执行,发生在载入组件之前。 next() }, beforeRouteUpdate (to, from, next) { // beforeRouteUpdate:路由已经解析而且组件已经复用时调用,发生在载入组件之后。 next() }, beforeRouteLeave (to, from, next) { // beforeRouteLeave:离开当前路由时进行验证。 next() } }
vue2和vue3的区别
-
更好的性能:Vue.js 3.x 对核心渲染层进行了重构,使用了 Proxy 对象和 Reflect API 替代了 Object.defineProperty 和 getter/setter 的方式,提高了响应式系统的性能。同时,还加入了静态分析,将静态的模板结构预编译,从而实现更快的渲染速度和更小的打包体积。
-
Composition API:Composition API 是 Vue3 中一个全新的 API,它使用了函数式API的设计理念,可以帮助开发者更加清晰、灵活、可复用地组织业务逻辑,是 Vue.js 3.x 的最重要的新特性之一。
-
更好的 TypeScript 支持:Vue.js 3.x 引导了一种新的编写组件的方式,借助 TypeScript 实现对 Vue 语法的类型推导和补全,使开发者更容易调试和查错,提高了代码的可维护性。
-
更小更快的打包体积:Vue.js 3.x 将平台无关的代码用标准的 ESM 模块化方式编写,使得打包大小大大缩减。在加入 Tree-shaking 和按需加载等优化手段后,其打包体积约为 Vue.js 2.x 的一半。
组件懒加载,路由懒加载,图片懒加载
组件懒加载是一种让应用在需要时再去加载组件代码的技术,而不是在应用初始启动时加载。使用该技术可以减少应用程序的初始启动时间,从而提高响应速度。在 Vue 应用中,可以使用 Vue.lazy() 方法实现组件懒加载,具体示例如下:
const MyComponent = () => import('./MyComponent.vue');
路由懒加载是一种将应用程序的代码按需进行拆分的技术,以便在需要时加载特定的路由或页面。使用该技术可以提高应用程序的速度、减少资源的消耗以及提高用户的交互性,具体示例如下:
{
path: '/home',
name: 'home',
component: () => import('@/views/home.vue')
}
图片懒加载是将网页中的所有图片延迟加载直到它们进入浏览器的可视区域时才开始加载的一种技术。这样可以减少页面的初始加载时间,并在图片需要出现在屏幕上时提高用户体验。
在 Vue 组件中实现图片懒加载逻辑,可使用 vue-lazyload 库等现成的解决方案。Vue-lazyload 是一个轻量级的 Vue 组件,它提供了多种图片懒加载的配置方式,支持图片懒加载的自定义行为等。
//npm install vue-lazyload --save
//编写懒加载配置
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
preLoad: 1.3, // 预加载高度比例
error: 'error.png', // 加载错误的图片
loading: 'loading.gif', // 加载中的图片
attempt: 1 // 尝试次数
});
//在模板中应用懒加载配置
<template>
<div>
<img v-lazy="image_src">
</div>
</template>
vue的token存储
1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token
3、前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面
4、前端每次跳转路由,就判断 localStroage中有无token,没有就跳转到登录页面,有则跳转到对应路由页面
5、每次调后端接口,都要在请求头中加token
6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401
7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面
对nextTick的理解
在 Vue 中,当我们使用 JavaScript 更新组件的数据时并不会立即更新 DOM,而是等到 Vue 重新计算 Virtual DOM 后,统一进行一次 DOM 更新。如果我们需要在 DOM 更新之后立即执行某些操作,就可以使用 nextTick
方法来确保操作的正确执行顺序。也就是说,等 Vue 把我们的数据变更完成后,再去做一些我们想做的事情。这样可以确保我们操作的是确切已渲染的 DOM,而不是一个尚未进行更新的 DOM。
vue性能优化
- 使用
v-once
指令减少不必要的渲染 - 合理使用
v-if
和v-show
- 合理使用 computed 和 watch
- 使用异步组件和路由懒加载
- 避免频繁操作 DOM
vue3的响应式原理
Vue 3 引入了 ES6 的 Proxy 对象来实现响应式原理,代替了 Vue 2 中使用的 Object.defineProperty,使得对动态添加和删除属性的处理更加优越。在 Setup 阶段,Vue 3 通过 Reactive 和 Ref 函数来处理响应式数据;在 Render 阶段,通过模板的编译和渲染来呈现页面,实现静态优化,提高了页面渲染效率。同时,Vue 3 还引入了 Composition API 来取代 Options API,提高代码复用性和可维护性。
Vue进行开发好处
1. 易于学习:Vue的语法简单明了,代码易于理解和维护,所以很容易学习。
2. 双向数据绑定:Vue具有双向数据绑定功能,当数据发生变化时,视图会实时更新,反之亦然。这使得开发者能够更加快速和直观地开发具有响应式功能的应用。
3. 组件化开发:Vue完全支持组件化开发,提供了许多构建组件的指令和功能。这样,可以更好地组织项目结构,提高代码的可重用性和可维护性。
4. 生态系统丰富:Vue社区非常活跃,有大量的第三方库、插件和工具,涵盖了许多应用场景。这些库和插件可以使我们能够更快地构建应用,并且提高开发效率。
5. 运行效率高:Vue使用虚拟DOM实现渲染,不需要直接操作DOM,大大提高了性能。此外,Vue还提供了一些优化手段,如异步渲染和组件懒加载等。
6. 面向未来:Vue是面向未来的,提供了一些新的特性和概念,如Composition API和Vue3的响应式系统,这些可以更好地解决未来的开发需求。