关于Vue面试会问到的问题

本文围绕Vue展开,介绍了MVVM架构,其通过ViewModel实现View和Model双向交互。阐述了Vue生命周期及钩子函数,说明了数据双向绑定基于Object.defineProperty。还涉及组件间参数传递、路由实现、过滤器定义等内容,最后分析了Vue的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于MVVM的理解

MVVM是Model-View-ViewModel的缩写

Model代表数据模型,也可以在Model中定义数据的修改和操作的业务逻辑。

View代表UI组件,它负责将数据模型转化成UI展现出来。

ViewModel监听模型数据(Model)的改变和控制视图行为,处理用户交互,

简单理解就是一个同步View 和Model的对象。连接Model和View的桥梁。

在MVVM架构下,View和Model之间并没有直接的联系,而是通过ViewModel进行交互的

这个交互是双向的,所以Model变化会同步到View ,View变化也会同步到Model.

ViewModel通过双向数据绑定把View和Model连接了起来,而View和Model之间的同步完全是自动,无需人为干涉,因此开发者只需要关注业务逻辑,不需要手动操作DOM.复杂的数据状态的维护完全交给MVVM来统一管理。

Vue的生命周期

beforeCreate:(创建前)在数据观测和初始化事件还未开始前执行该钩子函数

created:(创建后) 完成数据观测,属性和方法的运算,初始化事件。$el属性还未显示出来

beforeMount:(载入前)在挂载前调用,相关的render函数首次被调用。实例已经完成以下配置:

  编译模板,把data里的数据和模板生成html,但是还没有挂载到页面上去

mounted:(载入后)在el被新创建的vm.$el替换,并挂载到实例上去之后被调用。

实例已经完成以下配置:用编译好的html替换el指向的DOM对象。完成页面的渲染

此过程中进行ajax交互

beforeUpdate:(更新前) 在数据更新前调用,发生在虚拟DOM重新渲染

和打补丁之前。可以在这里进一步修改状态

updated:(更新后) 在数据更改后导致虚拟DOM重新渲染和打补丁后

 调用。调用时DOM已经更新

beforeDestroy:(销毁前) 在实例销毁之前调用,实例仍然可用

destroyed: 在实例销毁后调用,销毁就是所有的事件监听被移除,子实例被销毁

什么是Vue生命周期

Vue实例从创建到销毁的过程就是生命周期

生命周期中的钩子函数可以让我们在控制Vue实例的时候书写更好的逻辑

第一次页面加载会触发哪几个钩子函数?

beforeCreate  created    beforeMounte mounted

DOM渲染在哪个周期中就已经完成?mounted

Vue实现数据双向绑定的原理:Object.defineProperty

vue实现数据双向绑定主要是:采用数据劫持和发布-订阅模式的方式,

通过Object.defineProperty()来劫持各个属性的getter 和setter方法,在数据发生变化时

发布消息给订阅者,触发相应的监听回调。当把一个普通的js对象传给vue实例作为它的data

选项时,Vue将遍历它的属性,用Object.defineProperty将它们转为getter/setter,它们让Vue

追踪依赖,发生变化时通知变化。

vue的数据双向绑定整合Observer,Compile,Watcher三者。

Observer来监听自己的Model的数据变化,通过Compile来解析编译模版指令

(vue中是用来解析{{}})

最终利用watcher搭起observer和Compile之间的通信桥梁,达到

数据变化->视图更新;视图交互变化(input)->数据model变更双向绑定的结果

js实现简单双向绑定的例子

<body>
   <div id ='app'>
     <input type="text" id='txt'>
     <p id="show"></p>
   </div>
</body>
<script>
   var obj={}
   Object.defineProperty(obj,'txt',{
      get: function(){
        return obj.txt
      },
      set: function(newValue){
        document.getElementById('txt').value=newValue
        document.getElementById('show').innerHTML=newValue
      }
   })
   document.addEventListener('keyup',function(e){
      obj.txt=e.target.value
   })
</script>

Vue组件间的参数传递

1 父组件与子组件之间的传值

父组件给子组件传值:父组件用v-bind传递一个对象给子组件,子组件用props接收对象里的每个属性。

                                 或者父组件用:title传递title给子组件,子组件用props接收title

子组件给父组件传值:子组件触发一个事件,把数值作为参数传给给父组件this.$emit('eventname','value')。

                                   父组件监听事件@eventname

2  兄弟组件之间传值,1 vuex

2 使用根元素$root触发事件,缺点:谁都可以改,不好维护

A组件
this.$root.$emit('add-todo','helloworld')
B组件create方法里监听
this.$root.$on('add-on',(value)=>{
   console.log(value)
})

Vue路由的实现:hash   history模式

hash模式:浏览器中#及#之后的称为hash,用window.location.hash获取

hash虽然在url中,但不包含在HTTP请求中。

history模式:history模式采用H5新特性,且提供了pushState()

replaceState(),可以对浏览器历史记录栈进行修改。

history模式下,前端url必须和向后端发起请求对url一致。

路由的钩子函数

router实例上的:beforeEach    afterEach

单个路由:beforeEnter

组件内的钩子:beforeRouteEnter   beforeRouteUpdate  beforeRouteLeave

参数

to: 要进入的目标,到哪里去

from:正要离开的路由对象,从哪里来

next:用来决定跳转或取消导航

this.$router.forward()前进

this.$router.back() 后退

this.$router.push('/home')

this.$router.push({path:'/home'})

Vue如何定义一个过滤器

<div>
  <input type="text" v-model="msg">
  {{msg|capitalize}}
</div>
<script>
   new Vue({
     el:"#app",
     data:{
       msg: ''
     },
     filters:{
       capitalize:function(value){
           return value.charAt(0).toUpperCase()+value.substring(1)
       }
     }
   })
</script>

定义全局过滤器

Vue.filter('capitalize',function(){})

对keep-alive的了解

keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态

避免重新渲染

$route和$router的区别

$route是路由信息对象,包含路由的信息参数path

params,hash,query等

$router是路由实例,调用路由钩子

Vue的两个核心

数据驱动    组件系统

Vue中key的作用

vue它默认用“就地复用”策略

key的作用主要是为了高效的更新虚拟DOM

Vue优缺点

优点:轻量,高效,友好,数据双向绑定

缺点:不利于seo,第一次加载首页耗时较长。

转发自https://segmentfault.com/a/1190000016344599

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<think>嗯,用户想了解在Vue岗位面试中会被问到什么问题。我需要先整理一下常见的Vue面试题,然后分门别类地解释。首先,应该包括基础概念、组件相关、Vue Router、Vuex、性能优化、Vue3新特性,以及项目经验这几个方面。 基础概念方面,肯定会问响应式原理,比如Object.defineProperty和Proxy的区别。然后生命周期钩子函数,每个阶段的作用。可能还有计算属性和方法的区别,以及v-if和v-show的不同应用场景。 组件相关的问题,像是父子组件通信的方式,比如props和$emit,还有事件总线、provide/inject等。插槽的使用,特别是作用域插槽和具名插槽。动态组件和keep-alive的作用也是常考点。 Vue Router部分,路由模式hash和history的区别,导航守卫的使用场景,动态路由和懒加载的实现方法。可能还会问路由传参的几种方式,比如params和query的区别。 Vuex的状态管理,核心概念如state、mutations、actions、getters,以及模块化的应用。需要解释为什么需要异步操作放在actions里,以及如何持久化状态,比如结合localStorage。 性能优化方面,可能涉及虚拟DOM的优势,组件懒加载,长列表的优化方法,比如使用Object.freeze或者分页。还有如何减少不必要的重新渲染,比如合理使用v-if和v-show,或者key的管理。 Vue3的新特性,比如Composition API和Options API的对比,ref和reactive的区别,setup函数的使用,以及响应式系统的改进。还有Teleport、Suspense等新功能的理解。 项目经验方面,面试官可能会让举一个实际项目中遇到的难题,如何解决的,或者如何实现某个特定功能,比如权限控制、路由鉴权、组件库封装等。需要准备具体的例子,展示解决问题的思路和步骤。 还要考虑到不同公司的侧重点可能不同,有的重视原理,有的看重实战。因此,除了理论知识,还要准备一些实际编码的例子,比如手写一个简单的响应式系统,或者实现一个自定义指令。 另外,可能有一些进阶问题,比如Vue的diff算法原理,nextTick的工作机制,以及SSR的应用场景和实现方式。这些需要深入理解Vue的内部机制。 最后,提醒用户不仅要记忆知识点,还要理解背后的原理,最好通过项目经验来加深理解。同时,动手实践和模拟面试也是很好的准备方式。</think>以下是在Vue岗位面试中常见问题的分类整理及解析建议(使用$$...$$格式展示代码示例): --- ### 一、基础概念 1. **响应式原理** - 问题Vue2/Vue3如何实现数据响应式? - 示例: ```javascript // Vue2使用Object.defineProperty Object.defineProperty(obj, key, { get() { /* 依赖收集 */ }, set(newVal) { /* 触发更新 */ } }) // Vue3使用Proxy const proxy = new Proxy(obj, { get(target, key) { /* 依赖收集 */ }, set(target, key, newVal) { /* 触发更新 */ } }) ``` 2. **生命周期** - 必问:`created`和`mounted`的区别?`beforeDestroy`适合做什么? --- ### 二、组件开发 1. **通信方式** | 方式 | 适用场景 | |---------------|--------------------------| | Props/$emit | 父子组件简单通信 | | Event Bus | 跨层级组件通信(小型项目)| | Vuex | 复杂状态管理 | 2. **插槽** - 具名插槽:`<template v-slot:header>` - 作用域插槽:向父组件传递子组件数据 --- ### 三、Vue Router 1. **路由模式** ```javascript const router = new VueRouter({ mode: 'history', // 或 'hash' routes: [...] }) ``` - Hash模式:通过`#`实现,兼容性好 - History模式:需要服务端配合 2. **导航守卫** - 全局守卫:`router.beforeEach((to, from, next) => {})` --- ### 四、Vuex核心 1. **核心概念** ```javascript const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } }, actions: { asyncIncrement({ commit }) { commit('increment') } } }) ``` 2. **持久化方案** - 使用`vuex-persistedstate`插件或手动`localStorage`存储 --- ### 五、性能优化 1. **代码层面** - 使用`v-if`替代`v-show`(频繁切换时相反) - 长列表优化:`Object.freeze()`冻结非响应数据 2. **打包优化** ```javascript // vue.config.js module.exports = { configureWebpack: { splitChunks: { chunks: 'all' } } } ``` --- ### 六、Vue3新特性 1. **Composition API** ```javascript setup() { const count = ref(0) const double = computed(() => count.value * 2) return { count, double } } ``` 2. **响应式原理升级** - 使用Proxy替代Object.defineProperty - 嵌套对象自动响应化 --- ### 七、实战问题示例 1. **如何实现权限控制?** - 路由级别:通过全局守卫校验用户角色 - 组件级别:封装`<auth-button v-permission="'admin'">` 2. **遇到过最难解决的Bug?** - 准备案例:如响应式数据未更新(Vue2数组操作需用`$set`) --- ### 八、加分项准备 1. **原理实现** - 手写简易响应式系统 - 实现虚拟DOM的diff算法 2. **生态工具** - Nu.js(SSR) - Vue Test Utils(单元测试) --- 面试时建议结合具体项目经验回答,例如: > "在我的XX项目中,通过Vuex模块化管理用户权限状态,结合路由守卫实现了动态菜单渲染,过程中优化了..." 这种表述方式能体现理论结合实践的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值