2024 面试题第一站
1.vue的组件通信
vue是一个构建页面的js框架,是一个声明式,组件式的模型。封装复用组件是vue的一大特点,组件之间的通信是封装组件必须学习的内容。
- 父子之间通信: props、$emit。
- 事件总线:eventBus.$emit、eventBus.$on,第三方js插件mitt。
- 依赖注入:provide、inject。
- 获取某个组件实例:this.$parent、this.$children、this.$refs。
- 全局混入 mixin。
2.vuex和pinia的区别
vuex和pina作为vue2,3的全局状态管理工具,操控全局的数据,双向数据流动,方便管理。
- 架构设计原则,vuex有5个核心概念:state,getter,action,mutations,modules。pina采用中心化管理有三个核心概念:state,getter,action。
- state中的数据修改,vuex 通过派发action,通知mutations修改state数据。pina可以直接修改state数据。
- 对 ts 的支持,pina对ts支持较全面。
- 包的大小,vuex的包大,pina小。
- 性能上,pina采用集中化管理状态变更,效率更高。每个Store都是独立的,更容易进行状态追踪和优化。
3.怎么实现类似vuex让两个比较远的组件进行通信
- 定义全局变量,在window,vuex中挂载。
- 路由之间的参数传递,params、query。
- 事件总线 EventBus、mitt。
4.定义全局变量方法
定义全局变量太多,会影响代码质量以及性能,尽量减少全局变量的定义。
- 使用全局变量 window,定义全局的aa变量:window.aa = 1234。
- 全局状态管理工具 vuex。使用:this.$store.state.baseUrl
- main.js定义全局变量 Vue.prototype.baseName = "asa"; 使用:this.baseName 取值;
- 在env文件定义全局变量VUE_APP_BASE_URL = "test"; 使用:process.env.VUE_APP_BASE_URL 获取值
- 全局或局部混入 mixin。
- 浏览器缓存。
- vue3 提供专门配置全局变量的api ,globalProperties、getCurrentInstance 。
- 使用var定义变量。
5.vue的响应式原理
vue是双向数据流动,react是单向数据流动。 双向数据流是指更新数据后,视图可以主动局部刷新,不需要主动全局刷新。 首先,遍历data的数据,通过 Obejct.defineProperty 劫持数据,给数据加上 geter 和 setter 函数,获取数据触发 getter函数, 修改数据时触发 setter函数,在 setter 函数更新视图 dom ,从而实现数据的响应式 ;原理就是发布订阅模式。vue3的响应式原理proxy替代了Obejct.defineProperty。
6.你了解过哪些设计模式
- 单例模式 核心思想:一个类只能有一个实例,并提供一个访问它的全局访问点,vuex的实现原理就是单例模式。 使用场景:vuex全局状态管理器 - new vuex.Store({}),在不同组件之间共享和管理状态数据。
js
<script>
class Singleton {
constructor(name) {
this.name = name;
this.instance = null; // 用来判断是否已将创建了该类的实例
}
// 构造一个广为人知的接口,供用户对该类进行实例化
static getInstance(name) {
// 没有实例化的时候创建一个该类的实例
if(!this.instance) {
this.instance = new Singleton(name);
console.log( this.instance );
}
// 已经实例化了,返回第一次实例化对象的引用
return this.instance;
}
}
var a = Singleton.getInstance("a");
var b = Singleton.getInstance("b");
// a===b 说明指向的是唯一实例化的对象,说明a、b之间是引用关系。
console.log(a,b,a===b); // { "name": "a","instance": null } true
</script>
- 策略模式 定义:定义一系列算法,把他们全部封装起来,并是他们可以相互替换。就是把算法的使用和算法的实现分离出来。提高代码的可维护性和扩展性。核心是面向接口编程。 使用场景:使用了很多if,switch语句都可以使用策略模式改写。我们可以把策略从业务代码中抽离出来,以后维护或扩展业务,只需要修改策略即可。 核心概念:策略类(Strategy):封装了具体的算法,是算法实现的部分。环境类(Context): 算法的使用,把具体实现逻辑委托到策略类。
js
举例:公司绩效评级的方法
// 特点:1. 一堆的if语句 2. 具体实现和使用不分离
function computeBonus(level, basicBonus) {
if(level === 'A') {
return basicBonus * 1;
} else if(level === 'B') {
return basicBonus * 2;
} else if(level === 'C') {
return basicBonus * 3;
} else if(level === 'D') {
return basicBonus * 4;
}
}
var result = computeBonus('A', 1000);
console.log(result);
// 使用策略类 实现和使用分离
// 1. 定义策略类 -- 具体实现
const strategies = {
'A': function(basicBonus) {
return basicBonus * 1;
},
'B': function(basicBonus) {
return basicBonus * 2;
},
'C': function(basicBonus) {
return basicBonus * 3;
},
'D': function(basicBonus) {
return basicBonus * 4;
},
}
// 2. 定义环境类 -- 算法的使用
function computeBonus2(level, basicBonus) {
return strategies[level](basicBonus);
}
// 3. 使用环境类
var b = computeBonus2("A",1000)
console.log(b);
- 发布订阅模式(也叫观察者模式) 定义:定义了一种一对多的依赖关系,当一个对象的状态改变,其他依赖者(观察者)自动收到通知并更新 核心概念:
- 主题(Subject):也叫发布者,维护一组观察者,并在状态变化时通知观察者。
- 观察者(Observer): 也叫订阅者,负责接收主题的通知并做出对应的处理。 前端使用场景:
- 事件总线实现了观察者模式。
- 双向绑定,数据变化,自动更新相关视图。 优点:减少对象之间的依赖,实现解耦。灵活性:方便增加删除观察者。 缺点:观察者过多时,影响性能。
7.浏览器从输入url到渲染经过了哪些过程
- 浏览器解析URL,解析出协议、域名、方法体等信息。
- DNS解析,dns服务器解析url,把url解析对应的ip。
- 浏览器和服务器简历tcp三次链接。
- 浏览器发送http请求,服务器解析请求并返回响应数据。
- 浏览器处理数据生成dom树和cssom树合并为渲染树renderDom,加载js脚本,绘制页面。
- 断开tcp链接,四次挥手。
8.加载js脚本会阻塞渲染,怎么解决
使用async或defer属性来异步加载JavaScript脚本。 ● async属性会允许脚本异步加载并执行,但它不能保证脚本的执行顺序。 ● defer属性会延迟脚本的执行,直到整个页面解析完成。 ● defer和async的区别: defer:加载完资源不会执行,其他所有资源加载完毕才会执行 defer 资源,稳定。 async:加载完立即执行,如果在async代码段中修改了dom,可能出现错误,不稳定。 使用async或defer属性来异步加载JavaScript脚本。
9.watch和computed的区别?
watch是监听data和props中的数据是否改变,computed监听自己的数据是否改变。
- 计算属性会混入到vue实例中,watch监听data和props里面数据的变化。
- computed有缓存,它依赖的值变了才会重新计算,watch没有。
- computed是多对一(监听属性依赖其它属性)。
- computed必须有return返回值,watch不一定需要。
- 第一次加载computed就开始监听,watch如果需要第一次监听使用immediate: true; 属性。
10.vue组件的data为什么必须是函数
为什么是函数而不是对象形式。 组件复用的时候,要求每一份的数据都是独立的,互不影响,如果使用引用对象,那么复用组件中的data数据就会冲突。