# 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