SPA 单页面的理解,和优缺点:SPA仅在 Web 页面初始化时加载相应的 HTML、js 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换。优点:用户体验好、快避免了不必要的跳转和重复渲染;SPA 相对对服务器压力小;前后端职责分离,架构清晰。缺点:初次加载耗时多、前进后退路由管理,所有的页面切换需要自己建立堆栈管理、SEO 难度较大
v-show 与 v-if 有什么区别:v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的,条件第一次变为真时,才会开始渲染条件块。v-show只是简单地基于 CSS 的 “display” 属性进行切换。所以,v-if 适用于不需要频繁切换条件;v-show 则适用于频繁切换条件的场景。
:class 与 :style 区别:都可以通过对象语法和数组语法进行动态绑定。:class 用于绑定一个或多个类,可以用来动态地切换元素的类。:style 用于绑定内联样式,可以用来动态地更改元素的样式。
怎样理解 Vue 的单向数据流:指的是父组件通过属性(props)向子组件传递数据,而子组件修改父组件需要使用事件(events)来通知父组件进行状态更新。好处有:易于追踪数据流动、提高代码的可维护性、易于调试和测试,对于定位和解决bug非常有帮助。
computed 和 watch 的区别和运用的场景:computed:是计算属性,有缓存,只有它依赖的属性值发生改变,才会重新计算 。watch:更多的是「观察」的作用,当监听的数据变化时都会执行回调进行后续操作。运用场景:计算数值,并且依赖其它数据时,应该使用 computed。当执行异步或开销较大的操作时使用 watch。
数组项赋值,Vue 能检测到变化吗:Vue 不能检测到利用索引设置一个数组项和修改数组的长度,使用Vue.set的一个别名和使用数组方法来解决。
谈谈你对 Vue 生命周期的理解:也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程。beforeCreate组件实例被创建属性生效之前、created组件实例已经完属性生效dom还没生成、beforeMount挂载前、mounted挂载后,el被新创建的 vm.$el 替换、beforeUpdate更新前、update更新后activited,keep-alive 专属,组件被激活时调用。deadctivated,keep-alive 专属,组件被销毁时调、beforeDestory销毁前、destoryed销毁后
在哪个生命周期内异步请求: created、beforeMount、mounted 调用,data 已经创建。推荐在 created 中调用,因为优点是:更快获取到服务端数据,减少减少等待时间、ssr(浏览器环境)不支持 beforeMount 、mounted 。
Vue的SSR:服务器端渲染,服务器上将Vue组件渲染为HTML字符串,然后发送到客户端,最后在客户端“挂载”VM实例
在什么阶段才能访问操作DOM: mounted 中,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。
父组件可以监听到子组件的生命周期吗:父组件通过@hook:mounted监听子组件的mounted内的逻辑
组件中 data 为什么是一个函数:组件是复用的,查看源码可以发现data函数是在vue函数内,所以形成一个闭包。每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响
Vue 组件间通信有哪几种方式:父传子:props 来接受 父组件、通过 $parent 、$attrs 和 $listeners 来获取父组件实例的属性和方法。父传子孙:
provide 和 inject 实现。子传父:子组件 向父组件传递值:子组件通过 this.$emit('函数名',传递参数)绑定事件,父组件 通过 $refs / $children 来获取子组件值。跨层级:绑定$emit 事件 , 然后再通过 $on 监听触发的事件、还有vuex
什么是 MVVM以及它和mvc的区别:MVVM是一种前端架构模式,用户界面(View)与应用程序逻辑(ViewModel)和数据模型(Model)分离,以提高代码的可维护性和复用性。在MVVM中,ViewModel负责将数据从Model传递到View,同时也负责处理用户交互,并将用户操作反馈到Model。MVVM的核心思想是数据驱动视图。ViewModel在这一模式中起到了关键作用,它使得View和Model之间的通信不再直接,而是通过ViewModel来进行。MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示
Vue 是如何实现数据双向绑定的:View 变化更新 Data ,可以通过事件监听的方式来实现,所以 Vue 的数据双向绑定的工作主要是如何根据 Data 变化更新 View。Observer(监听器)会递归遍历数据对象,通过Object.defineProperty将每个对象属性添加setter、getter方法,并且单独给每个属性创建一个dep(依赖收集器)实例。Compile(解析器) 遍历 DOM,解析指令,如 v-model 和 v-bind为每个解析到的指令添加更新函数update创建对应的 Watcher(观察者),并添加到对应属性的 Dep 中。Observer监听到数据变化会通知对应的dep对象,dep 根据通知找到对应的一组 Watcher,并调用它们的 update 方法来更新视图。
Vue 框架怎么实现对象和数组的监听:过以上 Vue 源码部分查看,我们就能知道 Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用 Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。Proxy 与 Object.defineProperty 优劣对比:Proxy 可以直接监听对象、数组的变化;有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等;Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性修改;Object.defineProperty 的优势如下:兼容性好
虚拟 DOM 实现原理:用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;diff 算法 — 比较两棵虚拟 DOM 树的差异;pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。
Vue 中的 key 有什么作用:在 Vue 中,key 是一个特殊的属性,用于给每个节点(组件)设置唯一的标识符。提高渲染效率 当 Vue 在进行虚拟 DOM 的 diff 算法比较新旧节点时,如果节点具有相同的 key,则 Vue会认为它们是相同的节点,不会进行重新渲染,从而提高渲染效率。
Vue 修饰符有哪些:事件修饰符(.stop 阻止事件继续传播、.once 事件将只会触发一次、.prevent 阻止标签默认行为、.self 只当在 event.target 是当前元素自身时触发处理函数),v-model 的修饰符(.lazy 通过这个修饰符,转变为在 change 事件再同步、.trim 自动过滤用户输入的首尾空格),键盘事件的修饰符(.enter、.tab、.delete捕获 “删除” 和“退格”键),系统修饰键(.ctrl、.alt、.shift),鼠标按钮修饰符(.left、right、middle)
vue怎么引入路由:在 Vue 中引入路由的最简单方法是使用 Vue Router 库。1. 安装 Vue Router,2. 创建 Vue Router 实例,3 配置 Vuex Store,4.挂载 Vue Router。
vue-router 动态路由是什么 有什么问题:匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。我们可以在 vue-router 的路由路径中使用 “动态路径参数”。问题: vue-router 组件复用导致路由参数失效怎么办?1.通过 watch 监听路由参数再发请求,2. 用 :key 来阻止 复用
谈一下对 vuex 的个人理解:Vuex 是 Vue开发的状态管理模式,它为应用内的所有组件提供集中式的状态(数据)管理。简单来说,当多个组件共享状态时使用vuex。核心概念包括:(State:存放公共数据的地方,getter:根据业务场景处理返回的数据,mutations:唯一修改state的方法,修改过程是同步的,action:异步处理,通过分发操作触发mutations,module:将store模块分割,减少代码臃肿)
页面刷新vuex的state数据丢失怎么解决:放在localStore或者sessionStore或者借用辅助插件,推荐使用 vuex-persist 插件
Vuex 为什么要分模块并且加命名空间:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了让模块具有更高的封装度和复用性,可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
使用过 Vue SSR 吗?说说 SSR:SSR 也就是服务端渲染,也就是将 Vue 在客户端把标签渲染成 HTML 的工作放在服务端完成,然后再把 html 直接返回给客户端。优点:SSR 有着更好的 SEO、并且首屏加载速度更快。缺点: 开发条件会受到限制,服务器端渲染只支持 beforeCreate 和 created 两个钩子。
vue 中使用了哪些设计模式:1. 工厂模式 - 传入参数即可创建实例,虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。2. 单例模式 - 整个程序有且仅有一个实例,vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。3. 发布 - 订阅模式 (vue 事件机制)。4. 观察者模式 (响应式数据原理)。5. 装饰模式: (@装饰器的用法)。6. 策略模式 策略模式指对象有某个行为, 但是在不同的场景中, 该行为有不同的实现方案 - 比如选项的合并策略
你都做过哪些 Vue 的性能优化:1.对象层级不要过深,否则性能就会差、2.不需要响应式的数据不要放到 data 中、3.v-if 和 v-show 区分使用场景、4.computed 和 watch 区分使用场景、5.v-for 遍历必须加 key,key 最好是 id 值,且避免同时使用 v-if、6.防止内部泄漏,组件销毁后把全局变量和事件销毁、7.图片懒加载、8.路由懒加载、9.第三方插件的按需引入、10.适当采用 keep-alive 缓存组件、11.防抖、12.节流运用、13.服务端渲染 SSR or 预渲染
Vue.mixin 的使用场景和原理:相同或者相似的代码,这些代码的功能相对独立,可以通过 Vue 的 mixin 功能抽离公共的业务逻辑,原理类似 “对象的继承”,当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行 “合并”。
nextTick 使用场景和原理:nextTick 中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。主要思路就是采用微任务优先的方式调用异步方法去执行 nextTick 包装的方法
keep-alive 使用场景和原理:keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。常用的两个属性 include/exclude,允许组件有条件的进行缓存。两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态。
Vue.set 或者说是 $set 原理如下:它调用 Vue.util.defineReactive 方法将新的属性添加到响应式对象中。该方法将属性标记为可观测的,并设置 getter 和 setter 函数来触发依赖追踪。
Vue.extend 作用和原理:主要作用是扩展 Vue 构造器,创建出一个“子类”。这个“子类”可以包含组件选项对象(如 data、methods 等周期钩子)。原理是基于 js 的原型继承。它创建了一个新的 Vue 子类,这个子类继承了 Vue 的所有属性和方法。
自定义指令以及原理是什么:可以使用 Vue.directive 函数来注册一个指令。该函数接受两个参数,第一个参数是指令的名称,第二个参数是一个对象,用来定义指令的行为,应为有五个生命周期可用,分别是 bind、inserted、update、componentUpdated、unbind
Vue 模板编译原理:第一步是将 模板字符串 转换成 element ASTs(解析器)第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)
函数式组件使用场景和原理:主要适用于简单的展示组件、高阶组件和v-for循环中的子组件。 它们的特点是无状态和无实例,所有属性和逻辑都通过外部传递的props和context来处理。这种组件非常适合用于性能优化,因为它们不需要维护内部状态或创建类实例,从而减少了内存消耗和渲染时间。
vue-router 中常用的路由模式实现原理吗:hash 模式和history模式。hash 的值实际就是 URL 中 #后面的东西 它的特点在于:hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。可以为 hash 的改变添加监听事件。history 模式利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器的历史记录站,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。这两个方法有个共同的特点不刷新页面。
diff 算法原理:Diff 算法是用于同级比较两个虚拟 DOM 树的差异,并以最小的操作代价将旧的 DOM 树更新为新的 DOM 树的一种算法。常见的策略有双指针比较:从新旧子节点列表的头部和尾部同时开始比较。key 值比较:如果子节点设置了 key 属性,通过 key 来快速找到对应的节点进行比较和更新。