1. vue2和vue3的区别
- 响应式系统不同:Vue 2 使用 Object.defineProperty 实现响应式,存在一些限制,比如不能检测到数组索引和对象的新增属性。而 Vue 3 使用 Proxy 实现响应式,更加灵活,性能也更好,能处理更多复杂的数据结构。
- 组合方式不同:Vue 2 使用 Options API(如 data、methods、computed 等)来组织代码;Vue 3 引入了 Composition API,通过 setup() 函数、ref、reactive 等方式来组合逻辑,使得复杂组件的逻辑更清晰、更易于复用。
- 性能更优:Vue 3 在编译和运行时都有优化,体积更小,渲染更快,并且支持 Tree-shaking,可以只引入用到的功能,减少打包体积。
- TypeScript 支持更好:Vue 3 是用 TypeScript 编写的,对 TypeScript 有更好的内建支持,而 Vue 2 对 TS 的支持较弱。
- 模板改进:Vue 3 支持 Fragment(多个根节点)、Teleport(跨层级渲染)、Suspense(异步组件加载时的占位)等新特性,使模板编写更加灵活。
- 生命周期钩子不同:Vue 3 的 Composition API 使用如 onMounted、onUnmounted 等钩子函数替代了 Vue 2 的 mounted、destroyed 等生命周期选项,命名更统一,也便于逻辑复用。
Vue2 的响应式原理
- 核心:Object.defineProperty + 观察者模式****
- 实现机制:
- Vue 在初始化数据时,会遍历 data 的每个属性,用 Object.defineProperty 把它们转成 getter/setter。
- 当访问属性时,getter 会收集依赖(记录哪些组件/Watcher 用到了这个数据)。
- 当修改属性时,setter 会通知依赖更新,触发视图重新渲染。
- 缺点:
- 不能监听对象属性的新增/删除(需要 Vue.set / Vue.delete)。
- 数组部分方法(如直接通过索引修改)无法触发更新(需要用变异方法 push、splice 等)。
Vue3 的响应式原理
- 核心:ES6 的 Proxy + Reflect****
- 实现机制:
- Vue3 使用 Proxy 拦截对象的读取、修改、删除操作。
- 通过 Reflect.get/set/deleteProperty 实现依赖收集和触发更新。
- 可以直接监听 新增/删除属性、数组索引修改、Map/Set 等新数据结构。
- 优点:
- 解决了 Vue2 的缺陷。
- 性能更好,逻辑更清晰。
- 响应式系统可独立使用(@vue/reactivity 包)。
2. watch和watch effect的区别
- 使用方式不同:
- watch 需要指定要监听的具体数据源(可以是一个 ref、reactive 属性或 getter 函数)。
- watchEffect 不需要显式指定监听目标,它会自动收集在回调中使用到的所有响应式数据。
- 执行时机不同:
- watch 默认是懒执行的,只有被监听的数据变化时才会执行回调。
- watchEffect 会在组件创建时立即执行一次回调,然后在依赖变化时再次执行。
- 应用场景不同:
- 用 watch 更适合监听特定数据的变化,比如监听某个 prop、路由参数变化。
- 用 watchEffect 更适合进行一些依赖多个响应式数据的副作用处理,比如自动跟踪逻辑或简化一些复杂的 watch 写法。
3. watch和computed的区别
作用不同
- computed 是用于声明一个计算属性,通常用于从已有数据中派生出新的值,结果会被缓存,只有相关依赖发生变化时才重新计算。
- watch 是用于观察某个数据变化时,执行某些副作用逻辑(如异步请求、打印日志等),不会返回一个值。
是否有返回值
- computed 是有返回值的,你可以把它当作一个值来使用(例如模板中显示)。
- watch 没有返回值,它只是监听数据变化后执行回调函数。
是否缓存
- computed 会缓存结果,依赖数据没变时不会重复计算。
- watch 没有缓存,每次数据变化都会执行回调。
4. watch监听多个值
方法是传入一个数组或一个返回多个值的函数
5. watch想要马上执行
immediate: true
6. watch深度监听对象
deep: true
7. echarts数据改变了,但是图表没改变
myChart.setOption(option, true); // 第二个参数为 true,表示覆盖旧配置
8. vue中数组改变 但是视图没更新
// 方法 1:使用 Vue.set
this.$set(this.items, 1, 'new value');
// 方法 2:替换整个数组(触发响应)
this.items = [...this.items.slice(0, 1), 'new value', ...this.items.slice(2)];
9. vue中如果自己封装组件,子组件怎么改变父组件的值
10. ref和reactive的区别
**作用对象不同**:
- ref 用来包装一个**基本类型的值**(如数字、字符串、布尔值)或者对象,生成一个响应式的对象,访问时要通过 .value。
- reactive 用来包装一个**对象(Object)或者数组**,返回的是一个响应式的代理对象,直接访问属性即可。
**访问方式不同**:
- ref 包装的值通过 .value 访问和修改。
- reactive 返回的对象直接访问和修改属性。
**适用场景不同**:
- 当需要对一个基本类型值做响应式处理时,使用 ref。
- 当需要对一个复杂对象或数组做响应式处理时,使用 reactive。
**响应式实现不同**:
- ref 是通过一个包含 .value 属性的对象包装值。
- reactive 是通过 Proxy 实现对整个对象的深度响应式。
* * *
11. ref为什么能定义基本类型和对象
- ref 是一个容器对象,它把任何值(基本类型或对象)都放到 .value 属性里。
- 对于对象,.value 是响应式的代理对象(类似 reactive),可以深度响应。
- 对于基本类型,.value 就是普通值,但包裹在对象中,方便 Vue 跟踪变化。
12. es6和es7
13. promise和async await
| 特点 | Promise | async/await |
|---|---|---|
| 语法形式 | 链式回调 .then().catch() | 同步写法,使用 async 和 await |
| 可读性 | 相对复杂,特别是多个嵌套 | 更清晰,接近同步代码 |
| 错误处理 | .catch() 捕获错误 | try/catch 捕获错误 |
| 执行顺序 | 通过链式执行 | 通过等待异步操作 |
| 兼容性 | ES6 支持较广 | ES2017,现代环境支持好 |
14.路由中 history和hush的区别
### **1. hash 模式(基于 URL 的 hash)**
- URL 里带 # 符号,比如:
http://example.com/#/about
- 工作原理:监听浏览器地址栏的 hash 变化(window.location.hash),不会向服务器发送请求。
- 特点:
- 不需要服务器配置,兼容性好
- URL 中有 #,不美观
- 页面刷新时,浏览器不会向服务器请求不同路径,只请求主页面
* * *
### **2. history 模式(基于 HTML5 History API)**
- URL 是正常的路径,比如:
http://example.com/about
- 利用浏览器的 history.pushState 和 popState 来实现路由跳转,地址栏路径看起来更干净。
- 特点:
- URL 更加美观,没有 #
- 需要服务器配置,将所有路径都指向 index.html,防止刷新 404
- 兼容性稍差,IE9 以下不支持(但现代浏览器都支持)
14.vue中key的作用
-
唯一标识节点****
key 赋给列表中每个节点一个独一无二的标识,Vue 通过这个标识来判断节点是否发生变化,而不是简单靠顺序比较。
-
提升渲染性能****
当数据更新时,Vue 会用 key 来复用、移动、删除和添加元素,避免不必要的重新渲染和 DOM 操作。
-
防止渲染错误****
如果没有合理的 key,Vue 默认用就地复用策略,可能导致组件状态错乱,比如输入框输入内容错位、动画异常等。
15、v-for可以用index作为索引吗?
-
语法上是允许的,Vue 不会报错。
-
适合列表不会发生增删改,且顺序不变的简单场景。
-
为什么不推荐用
-
当列表发生增删改操作时,用 index 作为 key 会导致 Vue 误判节点,产生错误复用,可能出现:
- 组件状态错乱
- 输入框内容错乱
- 动画异常等
16、vue中data为什么是个函数
在 Vue 中,data 必须是函数而非对象,主要是为了避免组件复用导致的数据共享问题。
核心原因:组件复用与数据独立性
- 对象是引用类型:如果
data是对象,所有组件实例将共享同一份数据引用。当一个实例修改数据时,其他实例也会同步变化,导致数据污染。 - 函数返回新对象:每个组件实例调用
data()时返回独立的对象副本,确保数据相互隔离。
17、mvvm和mvm的区别?
MVVM 和 MVM 是两种不同的软件架构模式,核心区别在于架构层次的划分和职责分工:
-
MVVM(Model-View-ViewModel)
是主流的前端架构模式(如 Vue、React 常用),包含四层清晰分工:- Model:数据模型(后端数据或本地数据)
- View:视图(UI 界面,用户能看到的部分)
- ViewModel:连接 View 和 Model 的中间层,处理业务逻辑,双向绑定数据
- 核心特点:View 与 ViewModel 通过数据绑定联动,开发者无需手动操作 DOM,专注逻辑。
-
MVM(Model-View-Model)
并非通用标准模式,可能是某些场景下的简化或变种:- 通常去掉了 ViewModel 层,由 View 直接与 Model 交互,或两个 Model 层分别处理不同数据逻辑
- 特点:层次更简单,但 View 和 Model 耦合度可能更高,适合简单场景。
简单说,MVVM 是分层清晰、解耦彻底的成熟模式,而 MVM 是更简化的架构,应用范围较窄。前端开发中,MVVM 是主流选择(如 Vue 的响应式系统就是典型实现)。
18、跨域有哪几种解决方案?
- CORS(跨域资源共享)
最标准、推荐的方式,由服务器配置响应头(如Access-Control-Allow-Origin)允许指定域名跨域,支持所有 HTTP 方法,安全性高。 - JSONP
利用<script>标签不受同源限制的特性,通过动态创建脚本标签请求数据,仅支持 GET 方法,适合兼容旧浏览器。 - 代理服务器
前端请求同域的代理服务器,由代理转发请求到目标跨域服务器(如 Vue 项目的vue.config.js配置devServer.proxy),开发环境常用。 - iframe 相关方案
如postMessage实现 iframe 与父页面跨域通信,适用于页面嵌套场景。 - WebSocket
建立持久连接后可跨域通信,适合实时交互场景(如聊天、弹幕)。
实际开发中,优先用 CORS(生产环境)或 代理服务器(开发环境),JSONP 仅作为兼容方案。
19、你对vue的生命周期是如何理解的?
🔹 1. 什么是 Vue 生命周期?
Vue 生命周期就是 一个组件从创建到销毁的整个过程,Vue 在不同阶段提供了钩子函数,开发者可以在这些钩子里写逻辑。
🔹 2. Vue 2.x 生命周期钩子
主要分四个阶段:
- 创建阶段****
- beforeCreate:实例刚初始化,还没 data 和 props。
- created:data/props 已经可以用了,但还没挂载 DOM。
- 挂载阶段****
- beforeMount:模板已编译,还没渲染到页面。
- mounted:页面渲染完成,可以访问 DOM。
- 更新阶段(数据变化 → 重新渲染)
- beforeUpdate:数据更新了,但 DOM 还没更新。
- updated:DOM 已经更新。
- 销毁阶段****
- beforeDestroy:实例销毁前,可以清理定时器/事件。
- destroyed:实例已经销毁。
🔹 3. Vue 3.x 生命周期(组合式 API)
Vue 3 里如果用 setup,生命周期钩子变成了 onXxx 的形式:
- onBeforeMount
- onMounted
- onBeforeUpdate
- onUpdated
- onBeforeUnmount
- onUnmounted 而 beforeCreate、created 这两个被合并进了 setup() 里,因为 setup 就是初始化逻辑。
🔹 4. 常见使用场景
- created / setup:获取路由参数、初始化请求。
- mounted / onMounted:操作 DOM、初始化第三方插件(比如 echarts)。
- beforeUpdate:数据改动前做一些计算或记录。
- updated:数据更新后依赖 DOM 的逻辑。
- beforeUnmount / unmounted:清理定时器、移除事件监听
🔹 5. 总结理解
- 生命周期就是 组件不同阶段的钩子,让我们有机会在合适的时机做合适的事。
- Vue2 和 Vue3 差别主要是:
- Vue2 是选项式 API(created/mounted 等)。
- Vue3 是组合式 API(setup + onMounted/onUnmounted 等)。
20、从输入url到页面加载的过程?
- 浏览器会先进行 DNS 解析,把域名转成 IP。
- 然后通过 TCP 三次握手 建立连接,如果是 HTTPS 还要做 TLS 握手。
- 建立连接后浏览器发送 HTTP 请求,服务器接收并返回响应。
- 浏览器拿到响应内容后会进行 解析渲染:构建 DOM 树、CSSOM 树,合成渲染树,最后绘制页面。
- 在这个过程中还会执行 JS 脚本,处理异步请求和 DOM 更新。
- 最终用户看到完整的页面。