前端Vue.js面试题(3)

发布于:2025-07-16 ⋅ 阅读:(14) ⋅ 点赞:(0)

✨✨✨目录

1.v-model的原理是什么样的?

2.Vue的生命周期?

3.Vue子组件和父组件执行顺序?

4.created和mounted的区别?

5.vue中,推荐在哪个生命周期发起请求?

6.keep-alive中的生命周期有哪些?

7.Vue组件间通信的方式?

8.Vue-Router的懒加载如何实现?

9.vue路由中,history和hash两种模式有什么区别?

10.为什么 SPA 应用都会提供一个 hash 路由,好处是什么?

11.Vue中$route和$router有什么区别?

12.如何定义动态路由?如何获取传过来的动态参数?

13.Vue-router跳转和location.href有什么区别?

14.Vue-router导航守卫有哪些?

15.对前端路由的理解?


    1.v-model的原理是什么样的?

    v-model是Vue.js框架中的一个指令,用于在表单元素和组件之间实现双向数据绑定。它提供了一种简洁的方式来将表单输入的值与Vue实例的属性进行关联。

    当使用v-model指令时,Vue会根据表单元素的类型(如inputselecttextarea等)自动为其添加相应的事件监听器,并在用户输入时更新绑定的数据。

    具体地讲,v-model的原理如下:

    在模板中,我们可以使用v-model指令来绑定一个变量到表单元素(或组件)上,例如:<input v-model="message">;

    Vue解析模板时,会将v-model指令转换成合适的属性和事件绑定。对于大多数表单元素,它会将value属性与输入框的当前值进行绑定,并监听input事件来实时更新绑定的数据;

    当用户在输入框中键入或选择内容时,触发input事件。Vue会捕获该事件并更新绑定的数据,以及根据数据的变化重新渲染视图;

    同样地,如果在表单元素上使用v-modellazy修饰符,Vue会监听change事件而不是input事件。这样,只有当用户完成输入并触发change事件时,才会更新绑定的数据。

    v-model指令实现双向绑定的原理是通过监听表单元素的输入事件(如inputchange),将用户的输入同步到Vue实例中的属性,并在属性值变化时重新渲染视图。这使得我们可以轻松地将表单数据与Vue实例的状态保持同步,消除了手动监听和更新的冗余代码。

    2.Vue的生命周期?

    Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom->渲染、更新->渲染、卸载等一系列过程,称这是Vue的生命周期。

    (1)beforeCreate(创建前):数据观测和初始化事件还未开始,此时data的响应式追踪、event/watcher都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。

    (2)created(创建后):实例创建完成,实例上配置的options包括data、computed、watch、methods等都配置完成,但是此时渲染得节点还未挂载到DOM,所以不能访问到$el属性。

    (3)beforeMount(挂载前):在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。此时还没有挂载html到页面

    (4)mounted(挂载后):在el被新创建的vm.$el替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html染到html页面中。此过程中进行ajax交互。

    (5)beforeUpdate(更新前):响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实DOM还没有被渲染。

    (6)updated(更新后):在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时DOM已经根据响应式数据的变化更新了。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

    (7)beforeDestroy(销毁前):实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例。

    (8)destroyed(销毁后):实例销毁后调用,调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。

    3.Vue子组件和父组件执行顺序?

    (1)加载渲染过程:

    父组件:beforeCreate->created->beforeMount

    子组件:beforeCreate->created->beforeMount->mounted

    父组件:mounted

    (2)更新过程:

    父组件:beforeUpdate

    子组件:beforeUpdate->updated

    父组件:updated

    (3)销毁过程:

    父组件:beforeDestroy

    子组件:beforeDestroy->destroyed

    父组件:destroyed

    4.created和mounted的区别?

    在Vue中,createdmounted是两个常用的生命周期钩子函数,它们在组件的生命周期中扮演着不同的角色:

    created

    • created是组件生命周期中的一个钩子函数,在Vue实例被创建后立即调用。
    • created钩子函数中,Vue实例已经完成了数据观测(data observation),但尚未渲染真实DOM。这意味着你可以访问实例中的数据、方法、计算属性等,但不能保证实例已经被插入到DOM中。
    • created常用于一些初始化操作,例如数据请求、事件监听或其他非DOM相关的任务。因为此时,组件的模板还未被编译成真实DOM。

    mounted

    • mounted是组件生命周期中的一个钩子函数,在Vue实例挂载到DOM后调用。
    • mounted钩子函数中,Vue实例已经完成了模板编译,并且已经将生成的虚拟DOM渲染到真实DOM中。
    • mounted常用于需要对DOM进行操作的任务,例如初始化第三方库、绑定事件监听器、执行动画等。因为此时,组件已经被插入到DOM中,可以安全地访问和操作DOM元素。

    区别总结:

    created在实例创建后被调用,适合处理数据初始化和非DOM相关的任务。

    mounted在实例挂载到DOM后被调用,适合进行DOM操作、初始化第三方库和绑定事件监听。

    5.vue中,推荐在哪个生命周期发起请求?

    可以在钩子函数created、beforeMount、mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务端返回的数据进行赋值。

    推荐在mounted生命周期钩子中发起请求。理由如下:

    (1)确保DOM已经被渲染

    mounted钩子在组件的DOM已被插入文档之后调用。意味着所有DOM元素已存在,如果你的请求结果需要直接操作或依赖这些 DOM 元素,那么在 mounted 中发起请求是安全的。

    (2)避免不必要的请求

    在 created 钩子中发起请求有时会导致在组件还没有挂载时请求数据。如果组件在请求完成之前被销毁,可能会引发内存泄漏或不必要的资源浪费。因此,等待组件挂载完成再发起请求可以减少这些潜在问题。

    (3)处理组件状态

    在mounted钩子中发起请求,能够确保你有机会在请求开始前处理组件的状态(例如设置加载状态),并且在请求完成后更新组件的状态(例如显示数据或处理数据)

    尽管mounted是推荐的生命周期钩子,但是一些特定场景可能需要在created钩子中发起请求,例如:

    • SSR(服务端渲染):在服务器端渲染中,Vue实例的mounted钩子不会被调用,因为DOM并不会被真正挂载。在这种情况下,可能需要在created钩子中发起请求。
    • 依赖数据初始化:如果组件在挂载之前就需要某些数据来初始化,可以在created钩子中发起请求,以确保数据在组件挂载时已经可用。

    6.keep-alive中的生命周期有哪些?

    keep-alive是Vue提供的一个内置组件,在组件切换时将状态保留在内存中,防止重复渲染DOM。

    如果一个组件包裹了keep-alive,那么它会多出两个生命周期:deactived、activated。同时,beforeDestroy和destroyed就不会再被触发了,因为组件不会被真正销毁。

    当组件被换掉时,会被缓存到内存中,触发deactivated生命周期;当组件被切回来时,再去缓存里找这个组件,触发activated钩子函数。

    7.Vue组件间通信的方式?

    Vue中的每一个.vue都可以视为一个组件。

    组件间通信分类:父子组件之间的通信;兄弟组件之间的通信;祖孙与后代组件之间的通信;非关系组件之间的通信。

    vue中常规的组件间通信方案:

    (1)通过props传递

    • 适用场景:父组件传递数据给子组件
    • 子组件设置props属性,定义接收父组件传递过来的参数
    • 父组件在使用子组件标签中通过字面量来传递值

    (2)通过$emit触发自定义事件

    • 适用场景:子组件传递数据给父组件
    • 子组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
    • 父组件绑定监听器获取到子组件传递过来的参数

    (3)使用ref

    • 父组件在使用子组件的时候设置ref
    • 父组件通过设置子组件ref来获取数据
    <Children ref="foo" />  
      
    this.$refs.foo  // 获取子组件实例,通过子组件实例我们就能拿到对应的数据  

    (4)EventBus

    • 使用场景:兄弟组件传值
    • 创建一个中央事件总线EventBus
    • 兄弟组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
    • 另一个兄弟组件通过$on监听自定义事件

    (5)$parent/$children或$root

    • 通过共同祖辈$parent或者$root搭建通信

    兄弟组件

    this.$parent.$on('add',this.add)

    另一个兄弟组件

    this.$parent.$emit('add')

    需要注意:

    • 通过$parent访问到的是上一级父组件的实例,可以使用$root来访问根组件的实例
    • 在组件中使用$children拿到的是所有的子组件的实例,它是一个数组,并且是无序的
    • 在根组件#app上拿$parent得到的是newVue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组
    • $children的值是数组,而$parent是个对象

    (6)attrs与listeners

    • 适用场景:祖先传递数据给子孙
    • 设置批量向下传属性$attrs和 $listeners
    • 包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。
    • 可以通过 v-bind="$attrs" 传⼊内部组件

    (7)依赖注入Provide与Inject

    • 在祖先组件定义provide属性,返回传递的值
    • 在后代组件通过inject接收组件传递过来的值

    祖先组件

    provide(){     

      return 

        {         

          foo:'foo'     

        }

    }

    后代组件

    inject:['foo']

    (8)Vuex

    • 适用场景: 复杂关系的组件数据传递
    • Vuex作用相当于一个用来存储共享变量的容器
    • state用来存放共享变量的地方
    • getter,可以增加一个getter派生状态,(相当于store中的计算属性),用来获得共享变量的值
    • mutations用来存放修改state的方法。
    • actions也是用来存放修改state的方法,不过action是在mutations的基础上进行。常用来做一些异步操作

    8.Vue-Router的懒加载如何实现?

    非加载:

    (1)(常用方式)使用箭头函数+import动态加载。

    (2)使用箭头函数+require动态加载。

    (3)使用webpack的require.ensure技术,也可以实现按需加载。这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。

    9.vue路由中,history和hash两种模式有什么区别?

    Vue-Router有两种模式:hash模式和history模式。默认的路由模式是hash模式。

    (1)hash模式

    hash模式是一种把前端路由的路径用井号#拼接的真实URL后面的模式。当井号#后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发hashchange事件。

    使用onhashchange0事件的好处就是,在页面的hash值发生变化时,无需向后端发起请求,window就可以监听事件的改变,并按规则加载相应的代码。除此之外,hash值变化对应的URL都会被浏览器记录下来,这样浏览器就能实现页面的前进和后退。虽然是没有请求后端服务器,但是页面的hash值和对应的URL关联起来了。

    优点:浏览器兼容性较好,连IE8都支持

    缺点:路径在井号#后面,比较丑

    (2)history模式

    history API是H5提供的新特性,允许开发者直接更改前端路由,即更新浏览器URL地址而不重新发起请求。

    history api可以分为两个部分,切换历史状态和修改历史状态。

    • 修改历史状态:新增了pushState()和replaceState()方法,这两个方法应用于浏览器历史记录栈,提供了对历史记录进行修改的功能。
    • 切换历史状态:包括forward()、back()、go()三方法,对应浏览器的前进、后退、跳转操作。

    优点:路径比较正规,没有井号#

    缺点:兼容性不如hash,且没有服务端支持,否则一刷新页面就404了

    10.为什么 SPA 应用都会提供一个 hash 路由,好处是什么?

    SPA (单页应用)采用 Hash路的核心原因在于其兼容性、性能优化及实现成本优势,具体好处如下:

    (1)兼容性

    Hash路由利用URL的哈希部分(即#后的内容)实现路由切换,无需依赖 HTML5历史记录API 或服务器配置,可在所有浏览器(包括旧版本IE9及以下)中正常运行,避免了因浏览器兼容性问题导致的应用崩溃。 ‌

    (2)减少服务器请求

    当哈希值变化时,浏览器不会向服务器发送新页面请求,而是由JavaScript动态加载内容。这对SPA尤为重要,可避免全页刷新带来的延迟,提升用户体验。例如电商应用中切换不同视图时,仅更新局部组件而非重新加载整个页面。 ‌

    (3)开发成本低

    Hash路由基于浏览器原生支持,无需额外配置服务器或API支持。开发者可通过监听hashchange事件实现路由逻辑,简化开发流程。

    11.Vue中$route和$router有什么区别?

    在 Vue.js 中,$route 和 $router 是 Vue Router 提供的两个不同的对象,分别用于不同的目的。

    (1)$route

    功能:$route 路由信息对象包含当前路由的信息,包括路径、参数、查询字符串、路由名称等

    使用:用于访问当前路由的详细信息和状态。你可以从 $route 对象中获取路由参数、查询参数等。

    console.log(this.$route.path);   // 当前路由的路径
    console.log(this.$route.params);   // 路由参数
    console.log(this.$route.query);   // 查询字符串

    (2)$router

    功能:$router 路由实例对象提供了控制路由的功能,例如导航到不同的路由、替换当前路由等。

    使用:用于编程式导航,控制路由的跳转。

    this.$router.push('/new-path');   // 导航到新路径
    this.$router.replace('/another-path');   // 替换当前路径

    总结

    • $route:提供关于当前路由的信息。

    • $router:提供操作路由的方法,控制路由导航。

    12.如何定义动态路由?如何获取传过来的动态参数?

    (1)param方式

    • 配置路由格式:/router/:id
    • 传递的方式:在path后面跟上对应的值
    • 传递后形成的路径:/router/123
    • 参数获取:$route.param.id

    (2)query方式

    • 配置路由格式:/router,也就是普通配置
    • 传递的方式:对象中使用query的key作为传递方式
    • 传递后形成的路径:/route?id=123
    • 参数获取:$route.query.id

    两者区别:

    用法:query要用path来引入,params要用name来引l入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
    url地址显示:query更加类似于ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示。
    注意:query刷新不会丢失query里面的数据params刷新会丢失params里面的数据。

    13.Vue-router跳转和location.href有什么区别?

    • 使用location.href=/url来跳转,简单方便,但是刷新了页面;
    • 使用history.pushState(/url),无刷新页面,静态跳转;
    • 引进router,然后使用router.push(/url)来跳转,使用了diff算法,实现了按需加载,减少了dom的消耗。其实使用router跳转和使用history.pushState()没什么差别的,因为vue-router就是用了history.pushState(),尤其是在history模式下。

    14.Vue-router导航守卫有哪些?

    • 全局前置/钩子:beforeEach、beforeResolve、afterEach
    • 路由独享的守卫:beforeEnter
    • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

    15.对前端路由的理解?

    前端路由是指通过JavaScript在前端实现的一种路由机制,它允许在不重新加载整个页面的情况下,根据URL的变化来更新页面内容。这种机制主要通过监听URL的变化(如hash的变化或HTML5的HistoryAPI),并在前端动态地加载和渲染相应的页面组件或内容来实现。前端路由通常用于单页面应用(SPA)中,以提供流畅的用户体验和快速的页面切换。

    前端路由适合在以下场景中使用:

    • 单页面应用(SPA):SPA通常只有一个HTML页面,通过前端路由可以在不刷新页面的情况下实现页面的切换和导航,从而提升用户体验。
    • 需要快速响应和流畅体验的应用:前端路由可以减少页面加载时间和网络请求次数,使得页面切换更加快速和流畅。
    • 需要良好SEO的应用:虽然SPA在SEO方面存在一些挑战,但通过合理的前端路由配置和服务器端渲染(SSR)等技术,可以部分解决SPA在SEO方面的问题,提高应用在搜索引擎中的可见性。

    前端路由优缺点:

    优点:用户体验好;更快的响应速度;更高的扩展性;实现灵活;支持单页面应用

    缺点:初次加载慢;SEO不友好;增加复杂度;可维护性差

    💕💕💕持续更新中...... 
     若文章对你有帮助,点赞❤️、收藏⭐加关注➕吧!


    网站公告

    今日签到

    点亮在社区的每一天
    去签到