# offer **Repository Path**: qq_zhang/offer ## Basic Information - **Project Name**: offer - **Description**: 面试题 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-12-30 - **Last Updated**: 2025-12-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 复习 # ■ week1-day1 基本语法 ## 💘 课题 week1-day1 Vue基础(基本语法:简介、模板语法、列表渲染、条件渲染、事件处理) ## 🆕 先学vue3基本语法 Vue.createApp({}).mount('#root') ## 🌟 说出vue常用的指令 ## 💘 课件 {{}} v-text v-html v-if v-show v-on v-for v-modul v-pre v-once ## 🌟 MVVM、MVC面试题 - 谈谈你对MVC的理解 后端常用的开发思想,M代表Model模型,V代表View视图,C是控制器,分别控制M和V - 谈谈你对MVVM理解 前端常用的开发思想,,M代表Model模型,V代表View视图,MV是M和V之间的桥梁 - 谈谈MVVM和MVC区别 一个是前端常用一个后端常用,MVC单向通信 目的将M和V代码分离,MVVM则是双向通信,不需要手动操作DOM ## 🌟 说一下v-show、v-if的区别 都可以用户判断控制元素隐藏显示 v-if动态的向DOM树内添加或者删除DOM元素 v-show操控CSS(display:none;) v-if语法更强 高频切换例如二维码、登录弹框、提示框、删除提示框、tab选项卡,推荐使用v-show 来减少DOM频繁删除创建所产生的额外性能开销 ## 🆕 判断循环v-if、v-for优先级 vue2.0中v-for>v-if vue3.0中v-if>v-for # ■ week1-day2 特殊语法 ## 💘 课题 week1-day2 Vue基础(特殊语法:表单输入绑定、购物车案例) 无,都在【week1-day6 Vue原理】课件中 # ■ week1-day3 花式思想 ## 💘 课件 week1-day3 Vue基础(花式思想:Class与Style绑定、计算属性、侦听器、过滤器、自定义指令、ref属性、混入) ## 🌛 Class与Style绑定工作有用过吗 在vue提倡尽量减少DOM操作,所以不建议使用原生JS方法操作样式,使用Class和Style可以减少DOM操作, 提升性能 ## 🌟 计算属性和侦听器区别、使用场景 都是普通函数的升级版 不同: 1、调用时,计算属性不加小括号,侦听器不能调用 2、计算属性有响应式依赖缓存,侦听器没有缓存 场景:计算属性 : 登录功能,利用vuex辅助函数 侦听器 : 网站搜索,模糊筛选,弹框显示二维码,面包屑... ## 🌟 watch监控失效场景&解决方案 添加deep属性进行深度监听 ## 🌟 watch两大属性应用场景 deep:重置面包屑,权限分配 重置属性控件... immediate: 首次重置面包屑... ## 🌟 谈谈你对过滤器的理解有没有用过 理解: vue中用于过滤数据 场景: src/utils/filters 订单状态,性别,支付状态,发货状态... ## 🌟 谈谈你对混入的理解有没有用过 理解: 复用组件里的逻辑层 场景: src/utils/mixins 重定向跳转jump,接口操作成功后的判断成功或失败... # ■ week1-day4 组件编程 ## 💘 课件 week1-day4 Vue基础(组件编程:组件化开发思想、组件封装、props、$emit、组件通信、插槽slot、仿写UI组件库、动态组件等) ## 🌟 为啥data要写函数里面返回对象 一个组件被复用多次,会创建多个实例,但本质上同属一个构造函数,如果data直接是对象,会影响到所有实例 ## 🌛谈谈你对单向数据流的理解 数据只能由父传递给子,子不能直接修改数据,必须由父修改后再传递给子 注意:如果要子给父传递,可以通过vuex和$emit 实现 ## 🌟 如何实现组件通信? 状态管理工具:vuex 父传子:props 子传父:$emit 兄弟:$eventBus 插槽:slot 组件实例:$ref $root $parent $children v-model ## 🌟 事件.native作用 在组件上写原生事件 ## 🌟 在组件上写原生事件失效解决方案 1、加.native 2、通过自定义事件重写原生事件 ## 🌟 在组件上使用v-model原理 <组件名 :value="data中的键" @input="data => data中的键 = data"> ## 🌛 修饰符.sync原理 <组件名 v-bind:属性名="data中的键" @update:必须一样的属性名="data => data中的键 = data"> # ■ week1-day5 剩余知识:生命周期、keep-alive等等 ## 💘 课件 week1-day5 Vue基础(剩余知识:虚拟DOM、浏览器运行机制、回流重绘、生命周期、keep-alive、transition过渡 ## 🌟 说出浏览器运行机制 主进程: 负责tab的创建和销毁,文件下载等... 渲染进程: 每个tab底下对应一个渲染进程,js引擎线程,事件线程,定时器线程,异步请求线程,GUI渲染线程 GPU进程: 负责3D图的绘制 第三方插件进程: 负责第三方插件的处理 ## 🌟 说出浏览器输入网址干了啥 输入网址,根据网址去DNS服务器寻找对应的IP地址,找不到,无法访问该网页,找到了,根据IP地址去请求服务器,服务器返回数据,渲染页面 ## 🌛 说出JS为什么是单线程 这是根据JS的特性去定义的,如果JS是多线程,那么 当特殊情况时,一个线程需要删除一个元素,另一个线程需要修改这个元素,则会发生冲突 ## 🌛 说出JS是单线程 为什么不存在执行效率问题 JS在执行代码时,会形成一个执行栈,碰到比较耗时的代码,不会阻塞等待,而是交给其他线程处理,其他线程处理完毕之后再交给执行栈,所以不存在执行效率问题 ## 🌟 谈谈你对回流重绘的理解 回流: 改变元素样式,影响了原本的布局流(width,height,font...) 重绘: 改变元素样式,不影响原本的布局流(background,color...) ## 🌟 哪些属性导致回流、哪些属性导致重绘 回流: width、height、border、top... 重绘:color、background、box-shadow... ## 🌟 如何避免或减少回流重绘 js优化法:避免重复修改样式,一次性写好 避免频繁操作DOM... css优化法:transform 替代 top visibility 替代 display: none 避免使用table布局... ## 🌟 谈谈你对虚拟DOM的理解 用js描述真实DOM,减少回流重绘 ## 🌟 说出VUE有哪些生命周期并说出应用场景 created: 异步请求 mounted: 异步请求,操作DOM updated: 进一步操作DOM destroyed: 清除非VUE资源,(倒计时定时器) 2109班面试追问 ``` 问1:created、和mounted区别 答1:created不可以dom操作 问2:真的不可以吗 答2:可以通过 this.$nextTick() 问3:父子组件嵌套、生命周期执行顺序 created、mounted 答2:大方向 父created、子created、子mounted、父mounted ``` ## 🌟 created里面可以操作DOM吗 原则上不可以,但是可以通过 this.$nextTick()实现 ## 🌛 watch与created() 哪个先执行? 一般是created先执行,但是当watch使用 immediate时,则是 watch先执行 ## 🌟 谈谈你对keep-alive的理解,并说出应用场景 理解:将组件中的相关数据缓存到内存中,减少重复挂载卸载所产生的的性能开销 场景:后台管理系统环境数据、移动端长列表、tab选项卡... ## 🌟 谈谈你对$nextTick的理解,并说出应用场景 理解:vue中用来确保,在下次 DOM 更新循环结束之后执行延迟回调 场景:对话框放登录二维码,放表单选项获取数据、获取焦点,点击事件修改对话框状态后开始加载DOM,为确保能获取并操作DOM使用$nextTick包起来 ## 🌟 说出$nextTick原理 Vue底层监控的数据更新会开启一个队列进行优化处理,然后在下一个的事件循环中去触发nextTick的callback执行,也就是会把nextTick的callback依次尝试放到用原生的 Promise.then、MutationObserver 和 setImmediate、setTimeout中 Vue在更新dom时是异步执行的。只要监听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓存时去重对于避免不必要的计算和dom操作是非常重要的。nextTick方法会在队列中加入一个回调函数,确保该函数在前面的dom操作完成后才调用。 # ■ week1-day6 Vue原理 ## 💘 课题 week1-day6 Vue原理(语法原理:v-model语法原理、响应式原理、Vue源码分析、自定义Vue库) ## 🌟 说一下v-model原理 v-model其实是个语法糖底层,基于 :value 和 @input 封装 ## 🌟 VUE2响应式原理(中级) Vue2在初始化数据时,会使用Object.defineProperty语法对data中的所有属性进行数据劫持,如果属性发生变化就会通知进行更新操作 ## 🌟 VUE2响应式原理(高级) 底层通过Object.defineProperty进行数据劫持,通过发布订阅通知视图更新 ## 🌟 VUE2响应式数据无法劫持原因、和解决方案 ``` 原因:原生Object.defineProperty针对复杂数据修改无法劫持,因此无法通知视图更新 解决:自己解决:递归全搞定 VUE解决: 1.对象递归 2.数组重写(因为深度监听需要递归到底,而数组相对数据很多,一次性计算量大 所以改用重写方式) 3.增加额外api this.$forceUpdate() this.$set(this.data数据, 要劫持得数组索引或对象键, 默认值) ``` ## 🌟 $forceUpdate 原理 notify强制视图所有数据更新 ## 🌟 $set 原理 1.是vue原型上的一个方法 2.主要两大核心:通过defineReactive进行数据劫持 ,通过notify进行视图更新 ## 🌛 $delete 原理 删除对象的属性 语法:this/Vue.$delete(target,propertyName/index) 1.是vue原型上的一个方法 2.主要两大核心:通过delete 删除对象的属性 ,通过notify进行视图更新 ## 🌟 Vue.set/delete 原理 Vue.set = set Vue.prototype.$set = set 都是从 ../observer/index 文件中导出的 区别在于Vue.set()是将set函数绑定在Vue构造函数上,this.$set()是将set函数绑定在Vue原型上 ## 🆕 响应式原理 ``` 为啥VUE3要选择proxy和reflect 1.Object.defineProperty 拦截的是对象的属性,会改变原对象 proxy 是拦截整个对象,通过 new 生成一个新对象,不会改变原对象 2.proxy 语法更强,拦截方式除了上面的 get 和 set ,还有 11 种,以前就6个 3.proxy 特性更强,可以监听未定义的,针对于N层则get时判断递归添加proxy拦截即可 不用reflect可以吗 简单场景可以,复杂场景不行 举例:存在BUG ,其次:用了更方便推荐结合用 例如 has、deleteProperty、defineProperty友好提示等 ``` # ■ week2-day1 路由相关 ## 💘 课件 week2-day1 Vue进阶(项目准备:路由、重定向、路由模式、路由原理、路由参数、路由传参、嵌套路由、命名视图、导航守卫、路由addRoute) ## 🌛 路由-对象里面的键 path,component,name,redirect,alias,children,components,meta ... ## 🌟 路由-你说下vue路由模式有几种? 常用的有2个,分别为hash和history,直接修改路由构造函数加个mode键即可 准确说有3个,hash/history用于客户端,abstract用户服务端 ## 🌟 路由-你说下vue路由原理? vue路由是基于SPA单页面应用思想去开发的 利用BOM API 来使用 hash模式,通过 BOM location对象的hash属性来改变路由,window.onhashchange history模式, 通过BOM history对象的pushState方法来改变路由,window.onpopstate ## 🌟 路由-history有什么问题,如何解决? 刷新无法加载网页问题 ,可以通过服务器配置来解决 ## 🌟 路由-什么是单页面应用SPA优缺点,如何选择 SPA优点:减少HTTP请求、加载响应数据、提高用户体验度,方便增加动画 SPA缺点:首屏加载过慢、不利于SEO优化 如何选择:根据项目需求 ## 🌟 路由-参数周边种类、方式 参数种类:query、params query、path this.$router.push( {query, path} ) 定义路由时 不用管,刷新 不丢失 params、name 写冒号 this.$router.push( {params, name} ) 定义路由时 需要管,刷新 不丢失 params、name 不写冒号 this.$router.push( {params, name} ) 定义路由时 不用管,刷新 丢失 ## 🌟 路由-谈谈你对编程式导航的理解 作用:就是利用js跳转网页(声明式就是用a标签跳转) 场景:登陆、添加按钮、删除按钮等 语法:this.$router.push( { path:'/路径', query: {参数名:值} } ) this.$router.push( { name:'名称', params: {参数名:值} } ) 获取:this.$route.query/params.参数名 ## 🌟 路由-说出嵌套路由&命名视图的场景 嵌套路由:一个路由,显示多个组件,并且有父子关系 场景:后台管理系统经典两栏布局 点击左侧菜单,右侧显示子组件内容 命名视图:一个路由,显示多个组件,并且有兄弟关系所以component改为components 场景:移动端navBar、tabBar ## 🌟 路由-全局导航守卫登陆鉴权 作用:没登陆不可以访问会员中心、后台首页 语法:router.beforeEach 判断h5 next ## 🌟 路由-导航守卫种类&作用 全局:beforeEach 登录状态、网页加载进度条 全局:beforeResolve 不用(路由、组件守卫被解析也就是被调用后) 全局:afterEach 关闭网页加载进度条 NProgress 路由:beforeEnter 不用 组件:beforeRouteEnter 组件被创建前(注:不能用this) 组件:beforeRouteUpdate 动态路由匹配/动态获取路由参数 组件:beforeRouteLeave 未保存离开组件/清除定时器/切换组件保存数据等 ## 🌛 路由-导航守卫执行顺序 导航被触发。 在失活的组件里调用 beforeRouteLeave 守卫 调用全局的 beforeEach 守卫 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+) 在路由配置里调用 beforeEnter 解析异步路由组件 在被激活的组件里调用 beforeRouteEnter 调用全局的 beforeResolve 守卫 (2.5+) 导航被确认 调用全局的 afterEach 钩子 触发 DOM 更新 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入 ## 🌟 路由-动态路由如何实现 作用:不同角色,权限菜单看到的不一样 1:页面菜单导航根据接口数据渲染 2:路由不能全部写死,而是全部注释掉,利用addRoutes或addRoute动态添加路由规则 ## 🌟 路由-元信息有啥用 meta 存放面包屑、也可以加标识控制是否缓存组件 实现1:页面菜单导航根据接口数据渲染 实现2:路由不能全部写死,利用addRoutes或addRoute动态添加路由规则 ## 🌛 路由-过渡特效场景 # ■ week2-day2 脚手架相关 ## 💘 课件 week2-day2 Vue进阶(项目准备:脚手架、ToDoList案例、组件封装、全局组件、Vue.config.js配置) ## 🌟 说出框架中做了哪些配置vue.config.js 别名,跨域(最终上线还得后端或运维处理,移出console,图片压缩,引入外部CDN,等等 ## 🌟 说出跨域的解决方案 常用的谷歌命令,谷歌插件,JSONP,http-proxy-middleware,等等 追问:项目中如何配置,vue中配置 devServer ## 🌟 说出Vue.use原理 Vue.use主要用来在框架中全局注册插件,例如注册全局的组件等,然后底层源码大致做了两件事 1 检查传递的插件有没有重复注册 2 判断plugin.install是不是函数 或 plugin 是不是函数 然后分别用apply调用让函数执行 注册 Vue.component(组件名, 单文件组件) # ■ week2-day3 UI组件库 ## 💘 课件 week2-day3 Vue进阶am(项目准备:UI组件库ElemenUI、IView、AntdV、Vant、Mint等、自研UI组件库) ## 🌛 说出UI组件库/UI框架原理 1:通过vue单页面应用定义好公共组件 2:定义所有UI组件导出入口文件 src/components/index.js 3:接着打包 步4最后按照node包发布就可以使用 # ■ week2-day4/5 Vue千锋🤝美团项目布局 ## 🌟 项目开发中有没有封装过组件 开发过 ## 🌟 项目中封装了哪些组件 有很多,比如封装了公共的table、form等组件,还有很多页面组件,例如例如编辑用户、分配角色,分配权限、门店创建、分类编辑等都有封装提取页面组件,从而便于后期维护 ## 🌟 组件如何封装的 页面组件:在页面中完成功能,再views/模块名/components中定义单文件组件,然后导入使用,从而让组件更便于后期维护 公共组件:在src/components定义form公共组件,然后全局注册导入使用,最终根据需求利用props接受参数&创建自定义事件 ## 🌟 样式相关 防止样式的污染:scoped scoped解决样式污染原理:vue在编译的时候通过在DOM元素以及css样式上加上唯一标记,实现样式私有化,不污染全局样式 项目中开启样式私有化后,无法修改子组件例如elementui、antdv如何解决:使用 >>> 操作符或者/deep/ 或 ::v-deep ## 🌟 用户角色权限三者是如何关联的 在权限管理可以添加删除权限,实现后端路由 接着可以添加删除角色,然后给角色分配权限 最后在用户管理给用户分配角色, 后期不同用户登录就可以看到不同点权限菜单/导航 # 2109新增 实战 # 王云龙3月17日 1 2 3 4 5 6