1. vue生命周期
- 第一阶段(创建阶段):beforeCreate、created
- 第二阶段(挂载阶段):beforeMount、mounted
- 第三阶段(更新阶段):beforeUpdate、updated
- 第四阶段(卸载阶段): beforeUnmount、unmounted
created(创建后):
数据对象 data 已存在,可以调用 methods 中的方法,操作 data 中的数据,但 dom 未生成 。
mounted(挂载后):
vue 实例挂载完成,用户已经可以看到渲染好的页面了,在这个阶段可以对dom进行操作。
2. vue的双向绑定原理是什么?
Vue2:
1、原理:通过数据劫持和发布订阅模式来实现。通过Object.defineProperty()来劫持各个属性的setter和getter,并在geeter和setter中添加响应的依赖和观察者。当数据发生变化时,setter会通知相关的观察者更新视图。当组件被销毁时,会清除该组件的所有依赖和观察者。
2、优点:
- 向后兼容性:兼容老版本
- 数据变化能够自动更新视图,视图变化也能够自动更新数据
3、缺点:
- 对对象劫持,需要对属性进行重写添加getter和setter,多层嵌套对象时,性能差
- 对数组不采用defineProperty来劫持,单独处理,改写数组原有方法,对所有索引劫持造成性能浪费
Vue3:
1、原理:使用ES6的proxy来实现响应式。通过reactive()函数将data对象转换为响应式对象,使用proxy对对象进行拦截。当读取对象的属性时,在get方法中收集依赖WeakMap,每个reactive对象对应一个Map,用于存储该对象的所有依赖;当属性发生变化时,会触发set方法,通过找到当前对象属性所存储的依赖集Set,触发更新。
2、优点:
- 解决了vue2中Object.defineProperty的问题
3、缺点:
- 向后兼容性差,不支持老版本浏览器
- 不可变性和不可拓展性。Proxy创建的对象是不可变的。Obeject.freeze()或Obeject.seal()无法改变对象的不可变性和不可拓展性。
3. vue的组件间通信方式有哪些?
(1)props / emits :父组件通过 props传值给子组件,子组件通过 emits 通知父组件触发一个事件,并且可以传值给父组件。
(2)expose / ref :子组件可以通过 expose 暴露自身的方法和数据,父组件通过 ref 获取到子组件并调用其方法或访问数据。
(3)provide / inject :provide 是在父组件里使用的,可以往下传值,inject 是在后代组件里使用的,可以往上取值。
(4)Vuex / Pinia :主要解决 跨组件通信 的问题。
4. vue的nextTick作用?
- 当调用
nextTick()方法时,Vue 将回调函数放入一个队列中,等待下次 DOM 更新循环结束后执行。 - Vue 的数据变化会触发重新渲染 DOM,这个过程是异步的,数据变化后并不会立即更新 DOM,而是等待下一个事件循环才会进行 DOM 更新。
- 在所有同步任务执行完毕后,Vue 开始执行异步队列中的回调函数,此时 DOM 已经更新完成,确保在回调函数中获取到最新的 DOM。
5. vue中的keep-alive是什么?它有什么作用?
它是Vue中的一个内置组件,用于缓存动态组件。当组件包裹在中时,组件的状态将被保留,包括它的实例、状态和DOM结构。这样可以避免在组件切换时重复创建和销毁组件,提高性能和用户体验。
6. computed 和 watch 的区别?
(1)computed 是计算一个新的属性,并将该属性挂载到 Vue 实例上,而 watch 是监听已经存在且已挂载到 Vue 实例上的数据,所以用 watch 同样可以监听 computed 计算属性的变化。
(2)computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值。而 watch 则是当数据发生变化便会调用执行函数。
(3)从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据。
7. v-show 和 v-if 的区别?
v-show: 本质就是通过设置 display 控制隐藏
v-if: 动态的向 DOM 树添加或者删除元素
应用场景: 都是控制元素隐藏和显示的指令,切换显示/隐藏频繁用v-show,不频繁可以用 v-if。
8. v-for和 v-if 的优先级?
vue2中 v-for 比 v-if 具有更高的优先级,所以每次渲染时都会先循环再判断,用在一起会特别消耗性能,一般把v-if放在外层并且包一层template,然后内部进行v-for循环。
vue3中 v-if 比 v-for 具有更高的优先级,所以每次渲染时都会先判断再循环,只有在条件满足的情况下,才会执行v-for循环来渲染相应的 DOM 元素。这种改变使得在类似上述性能问题场景下,能够避免不必要的v-for循环操作,从而提高了性能。
9. router和route的区别?
route:是一个局部对象,包含了路由参数
router:是一个全局路由对象,包含了路由的跳转方法,钩子函数等
10. vue 常用的修饰符?
- .prevent: 提交事件不再重载页面
- .stop: 阻止单击事件冒泡
- .self: 当事件发生在该元素本身而不是子元素的时候会触发
11. vue 中 key 值的作用?
(1)v - if 场景
Vue 为高效渲染常复用元素,使用v - if切换相同类型元素时会复用已有元素,比如input元素切换前后用户输入可能保留,不符合需求。此时设置key可唯一标识元素,使其不被复用,key在此的作用是明确标识独立元素。
(2)v - for 场景
v - for更新已渲染元素列表默认采用 “就地复用” 策略,数据项顺序改变时,Vue 不移动 DOM 元素匹配,而是复用现有元素。为列表项设置key值能让 Vue 跟踪元素身份,实现高效复用,此时key的作用在于高效更新渲染虚拟 DOM。
12. vue-router常用路由模式有哪些?
-
hash模式:
- url会带有 /#/
- hash改变不会发起请求
- 兼容性更好
-
history模式:
- url更美观
- 需要配合后端,不然会出现跳转页面返回出现404问题
13. 父组件如何监听子组件生命周期?
- vue2 使用 @hook:mounted
- vue3 使用 @vue:mounted
- 自定义事件,在子组件生命周期中去执行
<template>
<h1>Home 页面</h1>
<Text @vue:mounted="fn" />
</template>
<script setup>
import { onMounted, ref } from 'vue'
import Text from '../components/Text.vue'
const fn = () => {
console.log('Text mounted')
}
</script>
14. Vue3中 ref 和 reactive 的区别?
-
ref和reactive都是响应式数据的创建 -
参数不同
ref可以传引用数据和基础数据reactive只能传入引用数据
-
使用不同
ref在js中需要.valuereactive可以直接访问templete中用法一样
15. this指向
-
普通函数 指向window(非严格模式下,严格模式下指向undefined)
-
函数 中的this,谁调用指向谁
-
箭头函数本身没有this,继承外层函数,如果有外层函数,外层函数的 this 就是内部箭头函数的 this ,如果没有,就是 window(非严格模式下)
16. call、apply和bind的区别?
- 都可以改变this的指向
- call和apply都可以立即调用
- bind会返回一个新函数,需要手动调用,它预先绑定了一个this的值
17. 箭头函数
- 箭头函数是一种匿名函数,当函数体是单条语句可以省略{}和return
- 箭头函数没有自己的this
- 箭头函数没有原型
- 不能够作为构造函数
18. 什么是跨域,怎么解决?
出于浏览器的同源策略限制,当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同就会跨域。
解决:
- webpack本地代理:在vue.config.js中配置本地代理
module.exports = {
devServer: {
port: 8000,
proxy: {
"/api": {
target: "http://localhost:8080"
}
}
}
}
- CORS跨域资源共享:需要服务端设置响应头
- nginx反向代理
19. 如何提高页面的加载性能?
- 路由懒加载
- 组件按需加载
- 减少HTTP请求
- 启用浏览器缓存
- 图片转 base64 格式