前端Vue面试题
mzgdbk 2024-09-13 09:03:01 阅读 92
Vue介绍
Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API
Vue.js是一个构建数据驱动的Web界面的库。
Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和 Vue生态系统支持的库开发的复杂单页应用。数据驱动+组件化的前端开发。
什么是 mvvm? MVC MVP MVVM
MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。
简述Vue的响应式原理
当一个Vue实例创建时,vue会遍历data选项的属性,用Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。 每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 wocher watcher 重新计算,从而致使它关联的组件得以更新。
Vue特点
简洁:页面由HTML模板+Json数据+Vue实例组成数据驱动:自动计算属性和追踪依赖的模板表达式组件化:用可复用、解耦的组件来构造页面轻量:代码量小,不依赖其他库快速:精确有效批量DOM更新模板友好:可通过npm,bower等多种方式安装,很容易融入
scss是什么?
预处理css,把css当前函数编写,定义变量,嵌套.
vue生命周期的理解?
vue2 、
创建阶段:
beforeCreate 在实例初始化之后
created 在实例创建完成后被立即调用 此时你可以访问到数据,但是组件尚未挂载到 DOM上
挂载阶段:
<code>beforeMount: 在挂载开始之前被调用,相关的 DOM 元素还未被渲染。mounted
: 挂载完成后被调用,此时实例已经完成了 DOM 渲染。
更新阶段:
beforeUpdate
: 当数据变化时,Vue 正在准备更新 DOM 前调用。updated
: 更新 DOM 后立即被调用。
销毁阶段:
beforeDestroy
: 实例销毁之前调用,实例仍然完全可用。destroyed
: 实例销毁后调用,此时实例已经不可用
其他:
activated
和 deactivated
: 仅在 keep-alive
缓存的组件中调用。errorCaptured
: 当捕获一个来自子孙组件的错误时被调用。
Vue 3 生命周期
setup 创建阶段
onMounted() onBeforeMount() 挂载
onUpdated() onBeforeUpdated() 更新阶段
onBeforeUnmount() onUnmounted() 卸载阶段
为什么vue中data必须是一个函数?
对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题
active-class是哪个组件的属性?
vue-router模块的router-link组件
vue-router有哪几种导航钩子?
三种。
一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
to:表示目标路由的位置对象。
from
: 表示当前导航正要离开的路由。next
: 是一个函数,用来放行或跳转路由。调用 next()
将放行到下一个钩子;调用 next('/newPath')
将跳转到一个不同的路由;调用 next(false)
将取消当前的导航。
第二种:组件内的钩子;
beforeRouteEnter
: 在路由进入之前调用,此时无法访问到组件实例 this
。beforeRouteUpdate
: 当路由被重用,且组件被重新渲染时调用,例如通过 params
或 query
改变。beforeRouteLeave
: 在路由离开之前调用,可以访问到组件实例 this
。
第三种:单独路由独享组件
允许为特定的路由定义专用的导航逻辑,使得路由的控制更加精细。
const router = new VueRouter({ routes: [ { path: '/user', component: User, beforeEnter: (to, from, next) => { // 这里可以定义针对 User 组件的独享导航守卫 } } ] });
说出至少4种vue当中的指令和它的用法?
v-if:判断是否隐藏;v-for:数据循环出来;v-bind:class:绑定一个属性;v-model:实现双向绑定
vue-loader是什么?使用它的用途有哪些?
解析.vue文件的一个加载器,跟template/js/style转换成js模块。
请说出vue.cli项目中src目录每个文件夹和文件的用法?
assets文件夹是放静态资源;
components是放组件;
router是定义路由相关的配置;
view视图;
app.vue是一个应用主组件;
main.js是入口文件
计算属性和watch的区别
在我们运用vue的时候一定少不了用计算属性computed和watch
computed计算属性是用来声明式的描述一个值依赖了其它的值。当你在模板里把数据绑定到一个计算属性上时,Vue 会在其依赖的任何值导致该计算属性改变时更新 DOM。这个功能非常强大,它可以让你的代码更加声明式、数据驱动并且易于维护。
watch监听的是你定义的变量,当你定义的变量的值发生变化时,调用对应的方法。就好在div写一个表达式name,data里写入num和lastname,firstname,在watch里当num的值发生变化时,就会调用num的方法,方法里面的形参对应的是num的新值和旧值,而计算属性computed,计算的是Name依赖的值,它不能计算在data中已经定义过的变量。
prop 验证,和默认值
我们在父组件给子组件传值得时候,为了避免不必要的错误,可以给prop的值进行类型设定,让父组件给子组件传值得时候,更加准确,prop可以传一个数字,一个布尔值,一个数组,一个对象,以及一个对象的所有属性。组件可以为 props 指定验证要求。如果未指定验证要求,Vue 会发出警告比如传一个number类型的数据,用defalt设置它的默认值,如果验证失败的话就会发出警告。
vue 组件通信
父传递子 props
子父亲 回调函数
祖孙 event bus 来设置事件的总线程 或者 Provide / Inject: 依赖注入的方式
兄弟通过共同的父组件或者通过
vue路由传参数
使用query方法传入的参数使用this.$route.query接受 query 使用 path query传递的参数刷新还存在使用params方式传入的参数使用this.$route.params接受 params 使用 name 传递的参数刷新不存在
vuex
vuex 是什么? 有哪几种属性?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
有 5 种,分别是 state、getter、mutation、action、module
vuex 的 store 是什么?
vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 datastate 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性
vuex 的 getter 是什么?
getter 可以对 state 进行计算操作,它就是 store 的计算属性虽然在组件内也可以做计算属性,但是 getters 可以在多给件之间复用如果一个状态只在一个组件内使用,是可以不用 getters
vuex 的 mutation 是什么?
更改Vuex的store中的状态的唯一方法是提交mutation
vuex 的 action 是什么?
action 类似于 muation, 不同在于:action 提交的是 mutation,而不是直接变更状态action 可以包含任意异步操作 vue 中 ajax 请求代码应该写在组件的 methods 中还是 vuex 的 action 中
vuex 的 module 是什么?
面对复杂的应用程序,当管理的状态比较多时;我们需要将vuex的store对象分割成模块(modules)。
如果请求来的数据不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入 vuex 的 state 里如果被其他地方复用,请将请求放入 action 里,方便复用,并包装成 promise 返回
pinia
Store: 状态存储的单元,包含 state、getters、actions 和 plugins。State: 状态数据,可以是任何 JavaScript 对象或数组。Getters: 从状态派生的数据,可以进行计算或转换。Actions: 可以包含异步操作的函数,用于修改状态。Plugins: 用于扩展 store 功能的钩子,例如持久化状态。
v-show和v-if指令的共同点和不同点?
v-show指令是通过修改元素的displayCSS属性让其显示或者隐藏
v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果
如何让CSS只在当前组件中起作用?
将当前组件的<style>
修改为<style scoped> scoped做样式隔离
<keep-alive></keep-alive>
的作用是什么?
作用
避免重复渲染:当组件从页面中切换出去时,<keep-alive>
会缓存该组件的实例,而不是销毁它。当再次访问该组件时,可以直接使用缓存的实例,而不需要重新渲染。提高性能:对于复杂或初始化成本较高的组件,使用 <keep-alive>
可以显著提高应用的性能和响应速度。保留状态:在组件被缓存期间,其状态(如数据和计算属性)会被保留,当组件再次被激活时,状态会恢复到之前的状态。 include:指定一个字符串或正则表达式,用于匹配需要被缓存的组件名。只有名称匹配的组件会被缓存。
exclude 指定一个字符串或正则表达式,用于匹配需要被排除的组件名。名称匹配的组件不会被缓存。
max 指定最大缓存的组件数量。当缓存的组件数量超过这个值时,最早的组件实例会被销毁。
钩子
onActivated 当被缓存的组件再次被激活时调用。
onDeactivated 当组件被缓存时调用
onBeforeUnmount 在组件被卸载之前调用,适用于执行清理操作。
delete和Vue.delete删除数组的区别?
delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。 Vue.delete直接删除了数组 改变了数组的键值。
$nextTick是什么?
vue实现响应式并不是数据发生变化后dom立即变化,而是按照一定的策略来进行dom更新。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
v-on可以监听多个方法吗?
可以。
v-on 常用修饰符
.stop 该修饰符将阻止事件向上冒泡。同理于调用 event.stopPropagation() 方法
.prevent 该修饰符会阻止当前事件的默认行为。同理于调用 event.preventDefault() 方法
.self 该指令只当事件是从事件绑定的元素本身触发时才触发回调
.once 该修饰符表示绑定的事件只会被触发一次
v-for key的作用。
当Vue用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue将不是移动DOM元素来匹配数据项的改变,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。 为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。key属性的类型只能为 string或者number类型。
key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
v-for 与 v-if 的优先级
vue2 v-for比v-if优先,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候。
vue3 v-if 比 v-for高 并且不能同时使用
Vue子组件调用父组件的方法
第一种方法是直接在子组件中通过this.$parent.event
来调用父组件的方法
第二种方法是在子组件里用$emit
向父组件触发一个事件,父组件监听这个事件就行了。
Promise对象是什么?
axios的特点有哪些?
1、axios是一个基于promise的HTTP库,支持promise的所有API;
2、它可以拦截请求和响应;
3、它可以转换请求数据和响应数据,并对响应回来的内容自动转换为json类型的数据;
4、它安全性更高,客户端支持防御XSRF;
vue中的 ref 是什么?
ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。 vue3 是响应式数据 也可以获取DOM元素
Vue的路由模式,实现方式?
hash模式 和 history模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下:仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式:前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
<code>$route和$router
的区别?
$route
是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router
是’路由实例’对象包括了路由的跳转方法,钩子函数等。
vue.js的两个核心是什么?
数据驱动、组件系统
vue如何兼容ie的问题。
babel-polyfill插件
页面刷新vuex被清空解决办法?
1.localStorage 存储到本地再回去
2.重新获取接口获取数据
如何优化SPA应用的首屏加载速度慢的问题?
1.将公用的JS库通过script标签外部引入,减小 app.bundel 的大小,让浏览器并行下载资源文件,提高下载速度;
2.在配置 路由时,页面和组件使用懒加载的方式引入,进一步缩小 app.bundel 的体积,在调用 某个组件时再加载对应的js文件;
3.加一个首屏loading图,提升用户体验;
如何优化SPA应用的首屏加载速度慢的问题?
1.将公用的JS库通过script标签外部引入,减小 app.bundel 的大小,让浏览器并行下载资源文件,提高下载速度;
2.在配置 路由时,页面和组件使用懒加载的方式引入,进一步缩小 app.bundel 的体积,在调用 某个组件时再加载对应的js文件;
3.加一个首屏loading图,提升用户体验;
DOM 渲染在哪个周期中就已经完成?
mounted
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
第一次加载会触发哪几个钩子?
会触发beforeCreate , created ,beforeMount ,mounted
vue是一套渐进式框架的理解
渐进式代表的含义是:主张最少。
Angular,它两个版本都是强主张的,如果你用它,必须接受 必须使用它的模块机制- 必须使用它的依赖注入- 必须使用它的特殊形式定义组件
React它也有一定程度的主张,它的主张主要是函数式编程的理念,比如说,你需要知道什么是副作用,什么是纯函数,如何隔离副作用。 它是软性侵入。
Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一两个组件改用它实现
Vue如何监听键盘事件中的按键
keydown 在事件处理函数中,使用 event.key
或 event.keyCode
来识别按下的键。
Vue中的过滤器有什么用?
Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示
单页面应用和多页面应用区别及优缺点
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新
单页面的优点:
用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
前后端分离
页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
不利于seo
导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
初次加载时耗时多
页面复杂度提高很多
什么是计算属性?
计算属性(Computed Properties)是一种特殊的属性,它们描述了组件中数据的派生状态。计算属性是基于它们的依赖进行缓存的,只有当依赖发生变化时,计算属性才会重新计算。这使得计算属性在性能上非常高效,特别是当计算结果复杂或需要重复使用时。
特性
响应式: 计算属性是响应式的,当它们依赖的响应式数据发生变化时,计算属性会自动更新。
缓存: 计算属性具有缓存特性,只有当依赖项之一发生变化时,计算属性才会重新计算。如果依赖项没有变化,Vue 将返回之前的计算结果。
描述性: 计算属性通常用于描述数据是如何从组件中其他数据派生出来的。
方法: 你可以将计算属性视为方法,但它们是声明性的,不需要手动调用。
依赖追踪: Vue 的响应式系统会自动追踪计算属性所依赖的响应式数据。
计算属性什么情况使用?
派生状态:当组件的状态是基于其他数据计算得来时,适合使用计算属性。例如,商品的总价可能由单价和数量相乘得出。
避免重复计算:如果某个值在组件中需要在多个地方使用,并且这个值的计算成本较高,通过计算属性可以避免重复计算。
模板中的复杂表达式:在模板中使用复杂表达式时,可以将这些表达式抽象到计算属性中,以保持模板的简洁性。
响应式依赖:当你需要依赖组件内的响应式数据,并且希望在这些数据变化时更新视图,但更新逻辑相对复杂时,计算属性可以自动追踪依赖并更新。
复用逻辑:如果你发现多个组件有相同的逻辑需要处理,可以将这部分逻辑抽象到计算属性中,然后在不同组件中复用。
数据格式化:当数据显示前需要进行特定的格式化,如日期格式化、货币格式化等,计算属性可以在数据变化时自动更新格式化后的值。
条件渲染:在模板中根据数据进行条件渲染时,可以将条件逻辑抽象到计算属性中,简化模板代码。
API 数据处理:当从 API 获取的数据需要进一步处理或转换格式以适应视图时,计算属性可以用来处理这些数据。
组合数据:如果你需要基于多个数据源组合出新的数据,计算属性可以清晰地表达这种组合逻辑。
性能优化:对于复杂的数据集合操作,如数组的过滤、排序等,使用计算属性可以确保只有在相关数据变化时才重新执行这些操作。
vue-cli提供了几种脚手架模板
六种
computed、methods的区别
1. 缓存机制
Computed Properties:
计算属性是基于它们的依赖进行缓存的。只有当依赖项发生变化时,计算属性才会重新计算。这使得计算属性非常适合用于昂贵的计算或需要重复获取的值。
Methods:
方法不会进行缓存。每次调用方法时,都会执行方法内的代码。
2. 响应性
Computed Properties:
计算属性是响应式的。如果计算属性依赖的响应式数据发生变化,计算属性会自动更新。可以在模板中直接使用,Vue 会自动追踪计算属性的依赖。
Methods:
方法不是响应式的。如果需要在数据变化时执行某些操作,必须手动调用这些方法。
3. 使用场景
Computed Properties:
适合用于声明性地描述一个值是如何根据组件中其他数据派生出来的。适用于模板中,例如,需要根据现有数据动态显示不同的值。
Methods:
适合用于执行可能改变组件状态的逻辑。可以在事件处理中使用,例如,响应用户点击事件。
4. 定义方式
Computed Properties:
通常是一个对象,属性名是计算属性的名称,属性值是一个函数,该函数返回计算结果。
Methods:
通常是一个对象,属性名是方法的名称,属性值是一个函数,该函数包含要执行的代码。
vue自定义指令
自定义指令的接收参数
自定义指令可以通过钩子函数接收以下参数:
el: 指令所绑定的元素,可以对其进行直接的 DOM 操作。binding: 一个对象,包含以下属性:
<code>name: 指令的名称。value
: 传递给指令的值,可以用在 v-xxx="value"code> 中。
oldValue
: 上一个值,如果有的话。expression
: 绑定的表达式,例如 v-my-directive="a + b"code>,则
expression
为 "a + b"
。arg
: 传递给指令的参数,用在带参数的指令中,例如 v-my-directive:arg
。modifiers
: 一个包含修饰符的对象,如 v-my-directive.foo.bar
,则 modifiers
为 { foo: true, bar: true }
。vnode: Vue 编译生成的虚拟 DOM 节点对象,包含了更多关于元素的信息。oldVnode: 上一个虚拟 DOM 节点对象,如果有的话。
自定义指令的钩子
自定义指令可以定义以下几个钩子函数:
bind: 当指令第一次绑定到元素时调用。这里适合进行一次性的初始化设置。
inserted: 元素被插入到父节点时调用(仅保证父节点存在,不一定已被插入文档中)。
update: 被绑定元素的 binding
更新时调用。适用于动态更新指令。
componentUpdated: 指令所在的组件更新后调用。
unbind: 指令与元素解绑时调用。这里是进行清理工作的合适时机。
父组件获取异步动态数据传递给子组件
在父组件中使用axios获取异步数据传给子组件,但是发现子组件在渲染的时候并没有数据,在created里面打印也是空的, 通过v-if,也就是判断数据是否为空,为空就不渲染,也能解决了
为不能读取的属性添加一个默认值,就可以很好的解决了
vue-router导航解析流程
初始化
创建 Vue Router 实例,并使用 routes
配置路由规则。将 Vue Router 实例注册到 Vue 应用中。
2. 监听 URL 变化
Vue Router 监听浏览器的 URL 变化(通过 hashchange
事件或 HTML5 history.pushState
API)。
3. 匹配路由
当 URL 变化时,Vue Router 根据 routes
配置查找匹配的路由记录。
4. 执行路由守卫
在匹配到路由后,Vue Router 会执行路由守卫(全局前置守卫、路由独享守卫、全局后置守卫等)。
5. 组件匹配
确定路由后,Vue Router 会查找对应的组件进行匹配。
6. 组件渲染
Vue Router 根据匹配的组件创建对应的 Vue 组件实例,并将其渲染到 <router-view>
组件的位置。
7. 导航完成
组件渲染完成后,导航流程结束,用户可以看到新页面的内容。
8. 处理嵌套路由
如果路由配置中包含嵌套路由,Vue Router 会递归地解析和渲染这些嵌套的子路由。
9. 滚动行为
Vue Router 允许配置滚动行为,可以在页面跳转时控制页面的滚动位置。
10. 监听路由变化
Vue Router 会提供 watchers
或通过 this.$route
来监听路由的变化,以便执行一些基于路由变化的操作。
vue-router实现原理
1. 路由配置
Vue Router 允许开发者通过一个路由配置数组来定义应用的路由结构。每个路由记录包括路径(path
)、路由名称(name
,可选)、是否精确匹配(exact
,可选)、重定向(redirect
,可选)和组件(component
)等属性。
2. 路由匹配
Vue Router 使用路径匹配算法来确定当前 URL 应该渲染哪个组件。它通过遍历路由配置数组,查找与当前 URL 匹配的路由记录。
3. 哈希模式和历史模式
哈希模式:使用 URL 的哈希(#
)部分来模拟一个完整的 URL,从而实现页面的无刷新更新。这是 Vue Router 的默认模式。历史模式:使用 HTML5 的 history.pushState
API 来实现 URL 的变更,从而不需要哈希部分。这种模式下,URL 更加美观,但需要服务器配置以支持 HTML5 History API。
4. 监听 URL 变化
在 哈希模式 下,Vue Router 监听 hashchange
事件来响应 URL 的变化。在 历史模式 下,Vue Router 依赖 popstate
事件以及 history.pushState
和 history.replaceState
方法来监听和修改浏览器历史。
5. 视图渲染
匹配到路由后,Vue Router 将对应的组件渲染到 <router-view>
组件的位置。如果存在嵌套路由,Vue Router 会递归地渲染每个级别的组件。
6. 路由守卫
Vue Router 提供了路由守卫(Navigation Guards)机制,允许开发者在路由跳转前后执行额外的逻辑,如权限验证、数据预取等。路由守卫可以在全局、单个路由或组件级别设置。
7. 滚动行为
Vue Router 可以配置滚动行为,控制路由跳转后页面的滚动位置。它可以记忆用户离开时的位置,或在跳转时滚动到顶部。
8. 响应式和组件的生命周期钩子
Vue Router 与 Vue 的响应式系统和组件生命周期钩子紧密结合。路由的变化会触发组件的 beforeRouteEnter
、beforeRouteUpdate
和 beforeRouteLeave
钩子。
9. 懒加载和代码分割
Vue Router 支持路由级别的代码分割,可以将不同路由对应的组件和资源进行懒加载,从而提高应用的加载性能。
10. 嵌套路由和命名视图
Vue Router 支持嵌套路由和命名视图,允许开发者定义复杂的路由结构,并使用 <router-link>
组件来实现导航。
vue-router有哪几种导航钩子
全局导航钩子
beforeEach(…): 在全局注册的钩子中,beforeEach
会在每个路由跳转开始时调用。
beforeResolve(…): beforeResolve
钩子在所有组件内守卫和全局 beforeEach
钩子调用之后调用。
afterEach(…): 在每个路由跳转完成后调用。
路由独享导航钩子
beforeEnter(…): 路由独享的 beforeEnter
钩子会在路由跳转开始时调用,但仅针对该路由。
组件内导航钩子
beforeRouteEnter(…): 在路由渲染该组件之前调用,此时不能访问 this
,因为组件实例尚未被创建。
beforeRouteUpdate(…): 当路由发生变化,但该组件被重用时调用。这个钩子可以访问 this
。
beforeRouteLeave(…): 在路由离开前调用,可以访问 this
。
导航守卫的参数
所有导航钩子都会接收以下参数:
to: Route: 目标路由对象。from: Route: 当前导航正要离开的路由。next: Function: 必须调用该函数来解决这个钩子。执行 next()
继续到下一个钩子。执行 next('/newPath')
跳转到一个不同的路由。执行 next(false)
或 next()
中止当前导航。
vue-router参数传递方法详述及区别
Query 参数
通过查询字符串(即 URL 的 ?
后面部分)传递参数。适用于传递一些过滤条件或临时状态。
传递方式:在路由跳转时附加到 URL 的末尾。接收方式:使用 this.$route.query
接收。// 传递参数 this.$router.push({ path: '/user', query: { name: 'John Doe' } });
2. Params
通过路由的动态片段(即路径参数)传递参数。适用于需要在路由中直接引用参数的情况。
传递方式:在路由定义中使用 :paramName
定义动态片段,在跳转时通过 params
传递。接收方式:使用 this.$route.params
接收。this.$router.push({ name: 'user', params: { id: '123' } });
Props
通过将路由的组件转换为接受 props 的方式,将参数以 props 的形式传递给组件。
传递方式:在路由配置中使用 props: true
使组件接收路由参数作为 props。接收方式:组件可以直接通过 props
接收参数。
如何定义嵌套路由
定义嵌套路由的步骤:
使用 children
属性: 在父路由对象中使用 children
属性来定义嵌套路由。children
是一个数组,数组中的每个对象都是一个子路由的配置。
指定 path
: 每个子路由需要有一个 path
属性。如果子路由的 path
是相对于父路由的,可以使用斜杠 /
开头,否则可以省略或使用点 .
开头表示相对路径。
组件定义: 每个子路由都应该有一个 component
属性,指定对应的 Vue 组件。
可选的 name
: 可以为每个子路由指定一个 name
,用于命名视图或编程式导航。
router-link 属性用途和常用的方法
<router-link>
的作用:
声明式导航:使用 <router-link>
可以声明性地定义导航链接,Vue Router 会自动处理 URL 的变更。响应式:<router-link>
会响应路由变化,自动更新链接的激活状态(active or not)。替换历史记录:使用 <router-link>
的 replace
属性可以实现替换当前历史记录的导航,而不是向历史添加新记录。
常用属性配置:
to:
描述链接的目标地址,可以是一个字符串或者是一个路由对象。例如:to="/home"code> 或者
to={ name: 'user', params: { userId: 123 }}
。
replace:
布尔值,如果为 true
,则在跳转时使用 replace()
而不是 push()
,不会留下浏览记录。例如:replace
.
active-class:
定义激活链接的 CSS 类名,默认为 "router-link-active"
。例如:active-class="my-active-class"code>。
exact:
布尔值或字符串,控制何时显示链接激活状态。如果为 true
,则只有当路径完全匹配时才激活;如果为字符串,则使用该字符串作为激活的精确匹配。例如:exact
或 exact="full"code>。
event:
定义触发导航的事件类型。默认为 "click"
,可以是任何有效的事件,如 "hover"
。例如:event="hover"code>。
append:
布尔值,如果为 true
,则在当前路径之后追加 to
的路径,而不是整个替换。例如:append
.
tag:
定义渲染的 HTML 标签,通常用于实现非 <a>
标签的链接,如使用 "li"
或 "div"
。例如:tag="li"code>。
exact-active-class:
定义精确匹配时使用的激活类,与 active-class
类似,但仅用于精确匹配的情况。例如:exact-active-class="my-exact-active-class"code>。
如何实现路由懒加载有什么好处
如何实现路由懒加载
Vue Router 允许你使用 component
属性的工厂函数来实现懒加载:
使用 import()
函数: 利用 ES6 的动态 import()
语法,可以按需加载组件。
定义路由时使用函数: 在路由配置中,将 component
属性设置为一个返回 Promise
的函数。
路由懒加载的好处
减少初始加载时间: 用户在访问应用时,不需要一次性加载所有组件,初始包体积更小,加载更快。
按需加载: 只有在用户实际访问某个路由时,对应的组件才会被加载,有助于提升应用的响应速度。
优化内存使用: 对于那些不常访问的页面,可以避免不必要的内存占用。
改善用户体验: 用户可以更快地看到应用的初始视图,提升整体体验。
代码分割: 利用 Webpack 或其他打包工具的代码分割功能,实现更细粒度的资源管理。
适用于大型应用: 对于大型单页面应用(SPA),路由懒加载可以显著提高性能和可维护性。
提高缓存效率: 懒加载的组件可以在用户再次访问时从缓存中加载,提高页面加载速度。
路由懒加载是一种常见的性能优化手段,特别是在构建大型应用时,合理使用懒加载可以显著提升应用的加载性能和用户体验。
vue-router共有几种模式,有什么区别?
hash模式:这是默认的路由模式。在这种模式下,URL 使用 #
来分割路径,例如 http://www.example.com/#/home
。当 #
后面的片段改变时,页面不会重新加载,Vue Router 会捕获这些变化并更新视图。
优点:兼容性好,简单易用。缺点:URL 中包含 #
,不够美观;在某些场景下(如使用 meta
的 refresh
标签),可能存在兼容性问题。
history模式:这种模式利用 HTML5 的 history.pushState
和 history.replaceState
方法来实现 URL 的改变,从而不需要 #
。例如 http://www.example.com/home
。这种模式下,URL 更加简洁和规范。
优点:URL 格式美观,更符合传统多页应用的 URL 风格。缺点:需要服务器配置支持,否则可能遇到 404 错误。
abstract模式:这种模式下,Vue Router 不会使用任何浏览器的 history 记录,也不会对 URL 进行任何改变。它仅在内存中进行路由匹配和视图更新。
优点:可以在非浏览器环境中使用,如 Node.js 服务器端。缺点:不改变 URL,不适合需要通过 URL 共享和书签的场景。
区别
URL格式:hash模式在URL中使用 #
,history模式使用标准URL路径,abstract模式不改变URL。浏览器历史记录:hash模式不使用浏览器的历史记录API,history模式使用。服务器配置:hash模式不需要特别配置服务器,history模式需要服务器配置以正确响应URL路径。使用场景:hash模式适用于简单应用或不需要太关注URL格式的情况,history模式适用于需要更美观URL的应用,abstract模式适用于非浏览器环境或不关心URL的场景。
vuex中如何异步修改数据
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
axios有哪些特点
基于 Promise: Axios 支持 Promises/A+ 规范,这意味着你可以使用 .then()
和 .catch()
方法来处理请求响应。
浏览器和 Node.js 兼容: Axios 可以在浏览器和 Node.js 中使用,提供了统一的 API。
拦截器: Axios 允许你添加请求拦截器和响应拦截器,可以在请求发送前或响应返回前执行一些操作。
转换请求和响应数据: 你可以在发送请求之前和接收响应之后转换请求和响应数据。
取消请求: Axios 支持取消请求,你可以取消一个正在进行的请求。
自动转换 JSON 数据: Axios 会自动将请求和响应数据转换为 JSON 格式。
HTTP 方法的便捷别名: Axios 提供了 HTTP 方法的别名,如 .get()
, .post()
, .put()
, .delete()
等,简化了请求的发起。
查询字符串处理: Axios 可以方便地处理查询字符串,.get('/some-url', { params: { foo: 'bar' } })
会自动处理查询字符串。
配置可定制: Axios 允许你全局或单个请求地配置默认设置。
CSRF 安全: Axios 可以配置以支持 CSRF 令牌,提高安全性。
WebSockets 支持: 在浏览器中,Axios 还支持 WebSockets。
类型支持: Axios 提供了 TypeScript 定义文件,支持类型推断。
错误处理: Axios 可以捕获请求和响应过程中的错误,提供详细的错误信息。
跨域请求: Axios 支持跨域请求(CORS),无需额外配置。
可扩展性: Axios 的设计允许你扩展其功能,例如通过插件或自定义配置
组件样式中的scoped有什么用 (样式隔离)
vue中常用的UI组件库有哪些?
Vuetify:
类型: 通用描述: 基于 Material Design 的组件库,适合构建遵循 Material Design 规范的现代应用。网址: https://vuetifyjs.com
Element UI:
类型: 桌面端描述: 提供一套企业级桌面端应用的 UI 组件库。网址: https://element.eleme.io
Ant Design Vue:
类型: 企业级应用描述: 基于企业级后台场景设计的 UI 组件库,适合构建中后台管理系统。网址: https://www.antdv.com
iView (现称 View UI):
类型: 桌面端描述: 基于 Vue.js 的高质量 UI 组件库,适合构建复杂的桌面端应用。网址: https://www.iviewui.com
BootstrapVue:
类型: 通用描述: 结合了 Bootstrap 的强大功能和 Vue.js 的灵活性,适合快速构建响应式网站。网址: https://bootstrap-vue.org
Quasar Framework:
类型: 跨平台描述: 可用于构建响应式网站、移动应用和桌面应用的全功能框架。网址: https://quasar.dev
Buefy:
类型: 通用描述: 轻量级的 UI 组件库,基于 Bulma CSS 框架,适合构建简洁风格的应用。网址: https://buefy.org
Vant:
类型: 移动端描述: 轻量、可靠的移动端 Vue 组件库,适合构建移动端应用。网址: Vant 4 - A lightweight, customizable Vue UI library for mobile web apps.
Muse UI:
类型: 通用描述: 基于 Material Design 的 Vue.js 组件库,适合构建遵循 Material Design 规范的应用。网址: https://museui.github.io/#/
Tailwind UI (与 Vue 集成):
类型: 通用描述: 虽然 Tailwind CSS 本身不是 Vue 特定的,但可以与 Vue 集成,适合构建高度定制化的用户界面。网址: https://tailwindui.com
Keen UI:
类型: 通用描述: 轻量级、高性能、可定制的 Vue.js UI 组件库,适合构建各种类型的应用。网址: https://github.com/JosephusPaye/Keen-UI
Vue Material:
类型: 通用描述: 提供 Material Design 组件,适合构建遵循 Material Design 规范的应用。网址: https://vuematerial.io
如何优化首屏加载速度
1. 代码分割
路由懒加载:使用 Vue Router 的路由懒加载功能,按需加载组件。动态导入:使用 Webpack 或其他打包工具的代码分割功能,将不同路由的代码分割成不同的 chunk。
2. 压缩资源
压缩 JavaScript 和 CSS:使用工具如 UglifyJS 或 Terser 压缩 JavaScript,使用 cssnano 压缩 CSS。压缩图片:使用工具如 ImageOptim 或在线服务压缩图片资源。
3. 使用 CDN
静态资源托管:将静态资源(如 JavaScript、CSS、图片)托管到 CDN,减少加载时间。
4. 减少 HTTP 请求
合并文件:减少 CSS 和 JavaScript 文件的数量。内联小资源:将小的 CSS 或 JavaScript 直接内联到 HTML 中。
5. 优化 CSS 和 JavaScript
异步加载非首屏资源:使用 async
或 defer
属性异步加载非首屏的 JavaScript 文件。优化选择器性能:减少 DOM 操作和复杂的 CSS 选择器。
6. 使用 Service Workers
缓存资源:通过 Service Workers 缓存首屏资源,提高重复访问的加载速度。
7. 优化首屏内容
减少首屏渲染的 DOM 元素数量:简化首屏的 HTML 结构。延迟加载非首屏资源:使用 IntersectionObserver
或 Lazyload
延迟加载非首屏的图片和脚本。
8. 使用 Webpack 优化
合理配置 Webpack:使用 Webpack 的 SplitChunksPlugin
进行代码分割,优化输出文件。使用 Webpack 插件:如 HtmlWebpackPlugin
来优化 HTML 的生成。
9. 优化服务器响应
使用 HTTP/2:提高服务器与客户端之间的传输效率。减少服务器响应时间:优化后端代码,减少数据库查询时间。
10. 使用预加载和预取
预加载关键资源:使用 <link rel="preload" href="...">code> 预加载关键资源。预取资源:使用
<link rel="prefetch" href="...">code> 预取可能需要的资源。
11. 优化第三方库
移除未使用的代码:使用 Tree Shaking 移除未使用的代码。替换大型库:考虑使用更小的库替换大型的第三方库。
12. 监控和分析
使用性能分析工具:如 Google Lighthouse、WebPageTest 等,定期检查应用的性能。
打包命令是什么?(mpm run build)
打包后会生成哪些文件?
index.html:
这是应用的主 HTML 文件,通常包含一个指向打包后的 JavaScript 和 CSS 文件的链接。
main.[contenthash].js:
这是应用的主要 JavaScript 入口文件,包含了应用的初始代码和运行时依赖。文件名中的 [contenthash]
是一个哈希值,用于确保文件名的唯一性,以便利用浏览器缓存。
chunk.[contenthash].js:
对于使用了代码分割的应用,每个分割出的代码块将生成一个单独的 JavaScript 文件。这些文件通常按路由或其他逻辑进行分割。
vendor.[contenthash].js:
包含第三方库的代码,例如 Vue.js 库本身和其他 npm 依赖。这个文件有助于将第三方代码与应用代码分离,以优化长期缓存。
manifest.[contenthash].js:
Webpack 4 引入了 Manifest 插件,用于生成一个清单文件,记录所有输出文件的映射关系。
app.[contenthash].css:
如果应用包含了 CSS,这将是最终的 CSS 文件,包含了所有样式规则,可能通过 ExtractTextPlugin 或类似插件从源文件中提取并合并。
images, fonts, and other assets:
应用中使用的图片、字体文件或其他静态资源也会被复制到构建目录中,通常在 dist
文件夹下。
source maps:
为了开发和调试方便,构建过程可能还会生成源映射文件(如 main.js.map
),这些文件映射回原始源代码。
stats.json 或 bundle-stats.json:
Webpack 可以生成一个包含打包详情的 JSON 文件,用于分析打包内容和优化。
service-worker.js:
如果使用了 Service Workers,可能会生成一个 Service Worker 脚本文件,用于控制缓存和资源加载。
prefetch/preload 资源:
使用 Webpack 的 prefetch/preload 插件,可能会生成额外的资源文件,用于预加载或预取资源。
这些文件的确切名称和数量可能会根据 Webpack 的配置和使用的插件有所不同。构建输出目录通常在 dist/
或 build/
目录下,但这也取决于配置。
如何配置打包后生成的文件路径错误问题
1. 检查 output
配置
Webpack 的 output
配置项定义了最终输出文件的目录和命名规则。确保 output.path
指向正确的目录,并且该目录存在且可写。
// webpack.config.js module.exports = {
// ... output: { path: path.resolve(__dirname, 'dist'), // 确保路径正确
filename: '[name].[contenthash].js',
},
// ...
};
2. 使用 publicPath
如果你的应用将部署在一个特定的根路径下,你可能需要配置 publicPath
。这个选项定义了 Webpack 打包时资源引用的基础路径
module.exports = {
output: {
publicPath: '/', // 根据你的部署路径进行设置
}
}
检查 index.html
的资源引用
确保 index.html
中引用的资源路径是正确的。如果你使用了 publicPath
,可能需要相应地调整这些引用。
使用 Webpack 插件
使用 Webpack 插件,如 HtmlWebpackPlugin
,可以自动将 publicPath
和其他环境变量注入到 index.html
中。
plugins: [
new HtmlWebpackPlugin({
template: 'index.html', publicPath: '/', // 确保与 output 中的 publicPath 一致
}), ],
5. 检查路径引用
确保在代码中引用的路径是正确的,特别是如果你的应用有特定的部署结构或使用了模块联邦等特性。
6. 使用环境变量
在 Webpack 配置中使用环境变量来定义不同环境下的路径。
7. 检查文件系统权限
确保 Webpack 有权限写入到指定的输出目录。如果没有权限,可能会导致打包失败。
8. 使用绝对路径
在配置路径时,尽量使用绝对路径,避免相对路径带来的不确定性。
9. 清理输出目录
在打包前清理输出目录,确保旧的构建文件不会干扰新的构建。
MVVM、MVP、MVC模式及区别
MVC (Model-View-Controller)
Model: 代表数据模型,负责数据和业务逻辑。View: 代表用户界面,负责显示数据(模型)和接收用户指令。Controller: 作为中间人,接收用户的输入并调用模型和视图去完成用户的指令。
MVC 模式将应用程序分为三个核心组件,使得视图可以独立于模型变化,控制器负责接收用户输入并调用模型和视图进行相应的处理。
MVP (Model-View-Presenter)
Model: 同 MVC,负责数据和业务逻辑。View: 负责显示数据,但不包含逻辑,它暴露一些接口供 Presenter 调用。Presenter: 作为逻辑处理的中心,它直接与 View 通信,处理用户交互,从 Model 读取数据并更新 View。
MVP 模式中,Presenter 充当了逻辑处理的角色,并且持有 View 的引用,但 View 不直接与 Model 交互,而是通过 Presenter 来进行数据的获取和更新。
MVVM (Model-View-ViewModel)
Model: 同上,负责业务逻辑和数据。View: 负责呈现 UI,可以绑定 ViewModel 的数据。ViewModel: 包含 View 的状态和行为,作为 View 的代理。它负责将 Model 的数据转换成 View 可以绑定的形式。
区别
职责分离: MVC 和 MVP 将逻辑处理放在 Controller 或 Presenter 中,而 MVVM 将逻辑放在 ViewModel 中,并且通常依赖框架提供的数据绑定机制。数据绑定: MVVM 模式特有的数据双向绑定,可以减少大量手动更新 UI 的代码。测试性: MVP 和 MVVM 由于将视图逻辑分离得更清晰,通常比 MVC 更易于测试。框架依赖: MVVM 通常依赖特定的前端框架(如 Vue.js、Angular 或 Knockout.js),而 MVC 和 MVP 更加通用,不依赖于特定框架。
MVVM模式的理解
组件
Model(模型):
负责处理应用程序的数据逻辑,比如数据库读写、网络请求等数据操作。通常不包含任何与视图相关的代码,保持数据的纯粹性。
View(视图):
负责显示数据(即模型层的数据)并且接收用户操作界面的界面。在 MVVM 中,视图不直接与模型交互,而是通过 ViewModel 进行数据绑定。
ViewModel(视图模型):
作为 Model 和 View 之间的桥梁,从 Model 中获取数据后,处理并返回给 View 显示。包含 View 的状态和行为,提供数据绑定的数据源。处理用户在 View 上的输入,将相关事件转发到 Model 层进行处理。
核心概念
数据绑定:ViewModel 与 View 之间的数据通过数据绑定机制连接。当 ViewModel 中的数据变化时,这种变化会自动反映在 View 上,反之亦然。命令:ViewModel 可以包含命令(Command),这些命令响应 View 上的用户交互(如按钮点击),并触发 Model 层的业务逻辑。依赖属性:在某些 MVVM 框架中(如 WPF),ViewModel 会使用依赖属性(Dependency Properties)来实现数据的自动通知和绑定。
工作流程
数据变化:当 Model 层的数据发生变化时,ViewModel 层会接收到通知。更新视图:ViewModel 层将数据变化同步到其属性中,触发数据绑定机制,自动更新 View。用户交互:用户在 View 层进行操作(如点击按钮),ViewModel 层接收到这些交互事件。触发命令:ViewModel 层根据用户交互执行相应的命令,这些命令可能会修改 Model 层的数据或触发其他逻辑。
优点
低耦合:Model、View 和 ViewModel 之间的耦合度低,易于管理和维护。可测试性:由于组件分离,可以单独对 ViewModel 进行测试,提高测试的覆盖率和质量。可重用性:ViewModel 可以独立于特定的 View 存在,提高了代码的重用性。响应式:数据绑定机制使得 UI 界面能够自动响应数据变化,提升了用户体验。
缺点
学习曲线:对于初学者来说,理解数据绑定和命令的概念可能需要一定的学习时间。框架依赖:MVVM 模式通常需要依赖特定的框架(如 Vue.js、Angular、Knockout.js)来实现数据绑定和命令。
应用
MVVM 模式在前端开发中被广泛应用,尤其是在使用 Vue.js、Angular、React(通过额外的库如 MobX 或 Redux)等框架时。这些框架提供了数据绑定和响应式编程的原生支持,使得开发者能够更容易地实现 MVVM 模式
Vue中的双向数据绑定是如何实现的
Vue.js 中的双向数据绑定是通过一系列机制实现的,这些机制包括:
响应式系统:
Vue 使用响应式系统来追踪数据的变化。当 Vue 的实例被创建时,它会递归地遍历实例的 data
对象,使用 Object.defineProperty
把所有属性转换为 getter/setter,这样属性的访问和赋值操作就可以被追踪。
数据劫持:
Vue 在初始化时对数据对象进行劫持,使用 Object.defineProperty
来劫持各属性,从而能够监听到对这些属性的访问和修改。
发布者-订阅者模式(Observer):
当数据变化时,响应式系统会通知订阅者(通常是组件的更新函数),然后组件会重新渲染。
指令系统:
Vue 的指令系统(如 v-model
)负责在视图和数据之间建立连接。v-model
指令背后使用了 :value
和 @input
来实现数据的双向绑定。
虚拟 DOM:
当数据变化触发组件的重新渲染时,Vue 会使用虚拟 DOM 来计算出最优的 DOM 更新策略,然后应用到真实 DOM 上。
v-model
指令:
在表单元素上使用 v-model
可以创建双向数据绑定。Vue 为不同的输入类型提供了不同的指令处理逻辑(例如,text
和 checkbox
)
实现过程
以 v-model
为例,双向数据绑定的实现过程如下:
初始化:当组件初始化时,Vue 会解析 v-model
指令,并使用插值表达式(如 <input v-model="username">code>)获取当前绑定的数据。
数据劫持:通过 Object.defineProperty
劫持数据属性,当数据变化时,可以通知到订阅者。
渲染:Vue 使用数据渲染视图,对于 v-model
绑定的输入框,其值就是数据对象中对应的属性值。
用户输入:当用户在输入框中输入时,触发输入事件。
事件处理:Vue 在指令中定义了事件处理逻辑,对于 v-model
,它会监听 input
事件。
更新数据:当 input
事件发生时,Vue 会获取输入框的新值,并更新数据对象中对应的属性。
重新渲染:数据更新后,响应式系统通知订阅者,组件使用新的数据重新渲染视图。
保持同步:由于数据和视图之间的绑定关系,任何一方的变化都会触发另一方的更新,从而实现双向同步。
Object.defineProperty()方法做什么用
基本用法
Object.defineProperty()
方法接受三个参数:
对象 (obj
): 要在其上定义属性的对象。属性名 (prop
): 要定义或修改的属性的名称。属性描述符 (descriptor
): 一个对象,包含定义属性的特性,如 value
, writable
, enumerable
, configurable
。
属性描述符的选项:
value: 属性的值。writable: 表示属性是否可写(默认为 false
)。enumerable: 表示属性是否可枚举,即是否会出现在 for-in 循环或 Object.keys 中(默认为 false
)。configurable: 表示属性是否可配置,例如是否可以使用 delete
删除属性,或者是否可以再次使用 Object.defineProperty
修改属性描述符(默认为 false
)。
// 创建一个空对象 let obj = {}; // 使用 Object.defineProperty 定义一个属性 Object.defineProperty(obj, 'property', {
value: 42,
writable: true,
enumerable: true,
configurable: true
}); console.log(obj.property); // 输出:42
特点
使用 Object.defineProperty()
定义的属性是可配置的,这意味着可以使用 delete
操作符删除它们,并且可以使用 Object.defineProperty()
再次修改它们。此方法不会改变对象的原型,它只修改对象本身。
在 Vue.js 中的应用
Vue.js 在实现响应式系统中使用了 Object.defineProperty()
方法来劫持数据对象的属性。当属性被访问或修改时,Vue 可以捕获这些行为,从而触发视图的更新。这是 Vue 2.x 版本中实现响应式系统的关键技术之一。
简述vue内部运作机制
响应式系统:
Vue 使用响应式系统来追踪数据的变化。在 Vue 2.x 中,这是通过 Object.defineProperty
来实现的,而在 Vue 3.x 中,则使用了 Proxy 作为基础。
虚拟 DOM:
Vue 通过虚拟 DOM 来提高性能。虚拟 DOM 是实际 DOM 的一个轻量级副本,Vue 在其中执行所有 DOM 操作,然后通过高效的算法最小化实际 DOM 操作。
组件化:
Vue 应用由一系列的组件构成。每个组件都有自己的视图(模板)、数据(数据对象)和逻辑(方法、生命周期钩子等)。
模板渲染:
Vue 的模板语法允许开发者声明式地将数据渲染进 DOM。Vue 编译模板时,会分析其中的指令和插值表达式,并生成虚拟 DOM 树。
编译过程:
Vue 应用的模板在运行时被编译成 JavaScript 渲染函数。这个过程将模板转换为可执行的代码,用于创建和更新虚拟 DOM。
数据绑定:
Vue 提供了数据绑定功能,包括文本插值、属性绑定、事件处理等。数据绑定确保了视图和数据的同步。
指令系统:
Vue 的指令(如 v-model
、v-if
、v-for
等)为开发者提供了处理用户交互和 DOM 操作的声明式方法。
依赖收集与派发:
响应式系统通过依赖收集机制追踪依赖于数据的组件或指令。当数据变化时,系统会通知这些依赖进行更新。
组件通信:
Vue 提供了父子组件通信、事件发射和监听机制,以及非父子组件间的通信方法,如提供者(provide)和注入(inject)。
生命周期钩子:
Vue 的实例有多个生命周期钩子,允许开发者在不同阶段执行代码,如创建、挂载、更新和销毁。
异步更新队列:
Vue 批量异步更新以避免不必要的重复渲染。当数据变化时,Vue 会将更新推迟到下一个事件循环。
服务端渲染(SSR):
Vue 支持服务端渲染,可以在服务器上生成完整的 HTML,然后将其发送到客户端,提高首屏加载速度。
单文件组件(SFC):
Vue 支持单文件组件,允许模板、JavaScript 和 CSS 代码在同一个文件中编写,简化了模块化开发。
插件系统:
Vue 的插件系统允许开发者扩展 Vue 的功能,如 Vuex 状态管理和 Vue Router 路由管理。
Vue 的内部运作机制是围绕构建声明式、组件化的用户界面而设计的,提供了丰富的功能和优化,以确保应用的性能和开发效率。
vuex内部运作机制
状态存储(State):
Vuex 使用单一状态树来集中存储应用的状态。状态是响应式的,Vue 组件可以读取状态,但不能直接修改状态。
视图(View):
Vue 组件作为视图,可以访问 Vuex 状态。当状态变化时,视图会自动更新以反映新的数据。
获取状态(Getters):
类似于组件的计算属性,Getters 允许你从状态派生出一些状态。它们是响应式的,并且可以用于在组件中获取计算后的数据。
更改状态的唯一方式(Mutations):
状态的变更必须通过提交 Mutations 来完成。Mutations 是同步的函数,你可以在其中修改状态。
异步操作(Actions):
Actions 类似于 Mutations,但它们可以包含异步操作。Actions 可以分派(Dispatch)Mutations 来改变状态。
模块(Modules):
大型应用的状态可以被分割成模块。每个模块拥有自己的 state、mutations、actions、getters,并且可以包含嵌套子模块。
响应式系统:
Vuex 利用 Vue 的响应式系统来追踪状态的变化,并通过 Vue 的依赖收集机制来更新视图。
中央仓库(Store):
Vuex 的核心是 Store 对象,包含所有状态、getters、mutations、actions 和模块。组件通过 Store 与状态交互。
组件与 Store 的交互:
组件通过 mapState
、mapGetters
、mapActions
和 mapMutations
辅助函数来映射状态和分派 actions。
严格模式(Strict Mode):
在严格模式下,任何试图直接修改状态的行为都会抛出错误,确保所有状态变更都是可追踪的。
时间旅行调试:
Vuex 提供了时间旅行调试功能,允许开发者在开发工具中回溯历史状态快照,便于调试。
插件支持:
Vuex 允许使用插件来扩展其功能,例如 Vuex-persist 插件用于持久化存储状态。
状态替换和热重载:
状态可以被替换,并且 Vuex 支持热重载,这在开发过程中非常有用。
你是怎么理解组件化开发的
封装性:
组件化开发强调封装,每个组件包含自己的模板、逻辑和样式,隐藏内部实现细节,只暴露必要的接口。
可复用性:
组件化使得开发出的组件可以在不同的项目或应用中重复使用,提高开发效率。
独立性:
每个组件应该是自包含的,不依赖于其他组件的特定实现,这使得组件可以在不同的上下文中使用。
维护性:
组件化有助于降低应用的维护成本,因为每个组件都是独立的,修改一个组件不会影响到其他组件。
扩展性:
新功能可以通过添加新的组件或扩展现有组件来实现,而不需要重写整个应用。
关注点分离:
组件化开发支持关注点分离原则,将逻辑、样式和结构分离,使得开发更加模块化。
可测试性:
独立组件更容易进行单元测试,因为它们可以被单独测试,而不需要依赖其他组件。
状态管理:
在组件化应用中,状态管理尤为重要,尤其是在多层嵌套组件间共享状态时。
通信机制:
组件化开发需要定义清晰的组件间通信机制,如事件系统、回调函数、状态提升等。
UI一致性:
组件化有助于保持应用的 UI 一致性,因为相同的组件可以在不同的地方重复使用。
开发流程:
组件化开发通常与现代前端开发流程相结合,如使用构建工具(Webpack)、版本控制系统(Git)和自动化测试。
工具和框架支持:
现代前端框架(如 React、Vue、Angular)和库提供了对组件化开发的原生支持。
单向数据流:
组件化开发通常遵循单向数据流原则,使得数据在组件之间的流动更加可预测和容易管理。
简述vue-cli每个目录的作用
node_modules/:
存放项目依赖的第三方库和模块,这些依赖通过 npm
或 yarn
安装。
public/:
包含静态资源文件,如 index.html
模板和其他不会被 Webpack 处理的静态资源。
src/:
源代码目录,包含应用的主要代码。components/: 存放 Vue 组件。assets/: 存放静态资源,如样式表、图片等。router/: 存放路由配置文件。store/: 存放 Vuex 状态管理文件。views/: 存放主要的视图组件。App.vue: 根组件。main.js: 入口文件,用于创建 Vue 应用实例并挂载到 DOM 元素上。
tests/:
包含自动化测试文件,通常使用 Jest 或 Mocha 等测试框架。
.eslintrc:
ESLint 配置文件,用于代码风格检查和质量保证。
.gitignore:
指定 Git 版本控制要忽略的文件和目录。
babel.config.js:
Babel 配置文件,用于定制 JavaScript 编译行为。
jest.config.js:
Jest 测试框架的配置文件。
package.json:
定义项目的依赖、脚本和元数据。
README.md:
项目说明文件,通常包含项目的介绍、安装步骤和使用说明。
vue.config.js:
Vue CLI 项目配置文件,用于自定义 Webpack 配置。
yarn.lock 或 package-lock.json:
锁定依赖版本,确保不同环境中安装的依赖版本一致。
vue两个核心点是什么?(数据驱动、组件系统)
第一次页面加载会触发哪几个钩子
Vue 2.x
beforeCreate:
在实例初始化之后被调用,此时数据观测和事件/侦听器的配置尚未完成。
created:
在实例创建完成后被调用,数据观测和事件/侦听器的配置已完成,但是组件尚未挂载到 DOM 上。
beforeMount:
在挂载开始之前被调用,相关的 DOM 元素还未被渲染。
mounted:
挂载完成后被调用,此时实例已经完成了 DOM 渲染,并且可以访问到 DOM 元素。
Vue 3.x
Vue 3.x 引入了 Composition API,生命周期钩子的概念有所变化,但是首次页面加载时仍然有类似的钩子:
setup():
在 Vue 3 中,setup()
函数是 Composition API 的入口点,在组件实例创建之前执行,类似于 Vue 2.x 中的 beforeCreate
和 created
钩子。
onBeforeMount:
在挂载开始之前调用,与 Vue 2.x 中的 beforeMount
钩子类似。
onMounted:
挂载完成后调用,与 Vue 2.x 中的 mounted
钩子类似,此时可以执行依赖于 DOM 的操作。
vue中的数组和原生js中的数组有什么区别?
响应性:
Vue 中的数组变化是响应式的。当数组被修改时(例如,使用 push()
, pop()
, shift()
, unshift()
, splice()
等方法),视图会自动更新以反映这些变化。原生 JavaScript 数组的变化通常不会自动触发视图更新,除非手动操作 DOM 或使用其他机制。
侦听数组变化:
Vue 2.x 使用 Object.defineProperty
来劫持数组索引的 getter 和 setter,以侦听数组项的变化。Vue 3.x 使用 Proxy 来实现对数组的响应式侦听,包括索引和数组长度的变化。
限制:
Vue 的响应式系统对直接的索引赋值(例如,vm.items[indexOfItem] = newValue
)在 Vue 2.x 中不总是触发更新。Vue 3.x 中,由于 Proxy 的使用,这不再是问题。原生 JavaScript 数组没有这种限制,任何形式的赋值都会改变数组状态。
替换数组:
在 Vue 中,如果你想替换整个数组,最好使用 vm.items = []
或 vm.items.splice(0, vm.items.length)
,以确保响应系统能够检测到变化。在原生 JavaScript 中,你可以直接赋值给数组变量来替换数组。
Vue 特定方法:
Vue 提供了一些方法来操作数组,这些方法会改变数组并通知视图更新,如 this.$set
用于 Vue 2.x 中更新数组的特定索引。
使用场景:
Vue 中的数组主要用于在组件的数据对象中存储状态,以便在视图中展示和修改。原生 JavaScript 数组可以用于任何需要数组操作的场景,不仅限于与 DOM 或视图状态相关的情况。
工具函数:
Vue 2.x 提供了一些数组工具函数(如 vm.$delete
),用于确保数组的某些操作是响应式的。Vue 3.x 中,由于 Proxy 的使用,这些工具函数不再是必需的。
性能:
Vue 的响应式系统可能会引入一些额外的性能开销,尤其是在数组操作非常频繁的情况下。原生 JavaScript 数组操作通常具有更好的性能,因为它们不涉及额外的响应式侦听逻辑。
简述$set及使用场景
使用场景
添加新属性:
当需要在已有的响应式对象上添加新的属性时,使用 $set
可以确保新属性同样是响应式的。
修改数组索引:
在 Vue 2.x 中,直接通过索引修改数组项(例如 vm.items[index] = newValue
)并不总是触发视图更新。使用 $set
方法(例如 this.$set(vm.items, index, newValue)
)可以确保这种修改能够触发更新。
避免直接赋值:
直接赋值(例如 vm.someObject.key = value
)可能不会触发视图更新,特别是在使用 Object.freeze()
冻结对象时。使用 $set
可以避免这个问题。
确保响应性:
如果你从一个非响应式的源获取数据,并希望将其转换为响应式的,可以使用 $set
方法逐个属性赋值。
什么样的项目比较适合用vue框架
单页面应用(SPA):Vue 非常适合构建单页面应用,因为它的组件化和视图分离特性使得页面的动态更新变得简单高效。
需要复杂交互的应用:对于需要丰富用户交互和动态内容的应用,Vue 的响应式系统和指令可以简化开发。
需要快速迭代的项目:Vue 的易用性和灵活性使得快速开发和迭代变得容易。
需要良好维护性的项目:Vue 的组件化和清晰的架构使得代码易于维护和扩展。
需要跨平台的应用:通过使用 Vue CLI、Vue Native 或者其他跨平台工具,Vue 应用可以扩展到移动应用和桌面应用。
需要良好社区支持的项目:Vue 拥有活跃的社区和丰富的生态系统,提供了大量的插件、工具和支持。
中小型项目:Vue 的轻量级和灵活性使其非常适合中小型项目,可以快速搭建原型并逐步扩展功能。
需要 SEO 优化的项目:Vue 支持服务端渲染(SSR),有助于提高应用的 SEO 表现。
Vue不能检测数组或对象变动问题的解决方法有哪些
使用 Vue 提供的方法:
对于数组,使用 this.$set
方法可以在 Vue 2.x 中确保数组项的更新是响应式的。对于对象,使用 this.$set
来更新对象的属性。
替换数组:
替换数组时,使用 this.items = []
或 this.items.splice(0, this.items.length)
来确保 Vue 检测到数组的变动。
使用 Vue.set
:
在 Vue 2.x 中,Vue.set
方法可以用来向响应式对象添加新的属性,并确保新属性同样是响应式的。
使用 Object.assign
或展开运算符:
使用 Object.assign
或者展开运算符 ...
来更新对象,这可以触发对象的响应式更新。
使用 this.$delete
:
在 Vue 2.x 中,使用 this.$delete
删除数组中的项可以确保 Vue 检测到数组长度的变化。
重新定义数组或对象:
重新定义数组或对象,例如 this.items = [...this.items, newItem]
,可以确保 Vue 检测到新的引用。
使用计算属性:
对于基于现有数组或对象派生的数据,使用计算属性可以确保响应性。
使用 Vuex:
如果状态管理复杂,使用 Vuex 可以更有效地跟踪数组和对象的变化。
使用 nextTick
:
有时在数据变化后立即需要访问更新的 DOM,可以使用 this.$nextTick
等待更新完成。
避免直接修改来自 Props 的数据:
如果数组或对象是从父组件通过 Props 传递的,不要直接修改它们。相反,应该使用 this.$emit
发出事件来让父组件进行修改。
使用 Object.defineProperty
:
虽然这不是 Vue 的标准做法,但可以在某些情况下手动使用 Object.defineProperty
来添加响应式属性。
升级到 Vue 3:
Vue 3 使用 Proxy 作为其响应式系统的基础,可以自动侦听数组和对象的变化,无需上述方法。
打包后访问某个视图,刷新404问题
1. 确保服务器正确配置
如果你的应用使用 history
模式,服务器需要被配置为对所有路由请求都返回 index.html
文件。这样,Vue Router 可以在前端处理路由。
2. 使用 nojekyll
文件
如果你的应用托管在 GitHub Pages 上,创建一个名为 .nojekyll
的空文件在你的仓库中。这是因为 GitHub Pages 默认会忽略以 _
开头的文件。
3. 服务器重定向配置
对于不同的服务器,需要不同的配置来实现重定向:
Apache: 使用 .htaccess
文件中的重写规则。Nginx: 修改 Nginx 配置文件,使用 try_files
指令。Node.js (Express): 使用中间件如 express.static
来提供 index.html
。
4. 使用 Vue Router 的 base
选项
如果你的应用不是作为域名的根路径部署的,使用 Vue Router 的 base
选项指定基础路径。
5. 检查 publicPath
在 Webpack 的 output
配置中,确保 publicPath
设置为应用的部署路径。
6. 使用服务工作线程 (Service Workers)
如果你的应用使用了服务工作线程,确保服务工作线程正确处理了路由和缓存。
7. 检查是否有错误的路由配置
确保 Vue Router 的路由配置正确,没有遗漏或错误的路径定义。
vue-router,history模式下打包后访问空白
. 服务器重定向配置
Apache: 使用 .htaccess
文件进行重写规则配置。Nginx: 修改 Nginx 配置文件,使用 try_files
指令。Node.js (Express): 使用中间件如 express.static
来提供 index.html
。
2. Vue Router 配置
确保在创建 Vue Router 实例时,<code>mode 选项设置为 'history'
。
3. Webpack 配置
确保 Webpack 的 output.publicPath
配置正确,特别是当你的应用部署在子路径下时。
4. 检查 Vue 应用的入口文件
确保 index.html
中正确引入了打包后的 JavaScript 文件。
5. 清除浏览器缓存
有时候浏览器缓存可能会导致问题,尝试清除浏览器缓存或使用无痕模式访问。
7. 使用 Vue Router 的 base
选项
如果你的应用不是部署在域名的根路径下,使用 base
选项指定基础路径。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。