目录
- 1. 防抖和节流
- 2. js闭包
- 3. Vue相关总结
- 4. ES6面试题
-
- 4.1 var let const 区别
- 4.2 解构赋值
- 4.3 如何利用es6快速的去重?
- 4.4 Promise 面试题 以下代码的执行结果是?
- 4.5 跨域的解决方法
- 4.6 git命令(实际工作中常用)
- 4.7 get与post请求有什么区别
- 4.8 cookie、localStorage、sessionStorage的区别
- 4.9 async 和 await 的区别
- 5.0 setTimeout 时间为0, 以及误差的原因
- 5.1 求数组的最大值?
- 5.2 求数组的最小值?
- 5.3 数组去重
- 5.4. 数组求和
- 5.6 js的数据类型
- 5.7 js的变量提升
- 5.8 this指向
- 5.9 map和forEach的区别
- 6.0 箭头函数和普通函数的区别?
- 6.1 es6新增
- 6.2 数组方法汇总
- 6.3 项目性能优化方案
- 6.4 forEach 和 map的区别
- 6.5 forEach 和 for 循环的区别
- 6.6 Vue2 和 Vue3 的区别
- 6.7 call、apply、bind使用和区别
1. 防抖和节流
防抖(debounce):单位时间内,频繁触发事件,只执行最后一次。
比如点击按钮,2秒后调用函数,结果在1.5秒的时候又点了,则会重新计算2秒后在调用函数。
应用场景:搜索框、输入框、手机邮箱验证等
思路:利用定时器,每次触发先清除定时器()
底层代码实现:
const box = document.querySeleter(".box")
let i = 1
function mouseMove() {
box.innerHTML = i++
}
function debounce(fn, t) {
let timer
// return 返回一个匿名函数
return function() {
if(timer) clearTimeout(timer)
timer = setTimeOut(function() {
fn()
}, t)
}
}
box.addEventListener('mousemove', debounce(mouseMove, 500))
节流(throttle):单位时间内,频繁触发事件,只执行一次
应用场景比较多的是:鼠标经过、页面缩放、滚动条滚动scroll事件、下拉刷新等高频事件
思路:利用定时器,判断是否有定时器,如果有等定时器结束再开启新的定时器
代码实现:
const box = document.querySeleter(".box")
let i = 1
function mouseMove() {
box.innerHTML = i++
}
function throttle(fn, t) {
let timer
// return 返回一个匿名函数
return function() {
if(!timer) {
timer = setTimeOut(function() {
fn()
// 清空定时器 此处使用timer=null清除定时器是因为写在了定时器里面,setTimeout中是无法清除定时器的,因为定时器还在运作
timer = null
}, t)
}
}
}
box.addEventListener('mousemove', throttle(mouseMove, 500))
2. js闭包
什么是闭包:闭包就是能够读取其他函数内部变量的函数
function fn0 () {
const aaa = 0
return function() {
return aaa
console.log('打印', aaa)
}
}
闭包存在意义:
可以延长变量的生命周期4可以创建私有的环境
闭包好处:
可以读取其他函数的内部变量
将变量始终保存在内存中
可以封装对象的私有属性和方法
坏处:
消耗内存、使用不当会造成内存溢出问题
3. Vue相关总结
3.1 vue中的data为什么是一个函数?(面试常问)
Vue 中的 data 必须是个函数,因为当 data 是函数时,
组件实例化的时候这个函数将会被调用,返回一个对象,
计算机会给这个对象分配一个内存地址,实例化几次就分配几个内存地址,
他们的地址都不一样,所以每个组件中的数据不会相互干扰,改变其中一个组件的状态,其它组件不变。
简单来说,就是为了保证组件的独立性和可复用性,如果 data 是个函数的话,
每复用一次组件就会返回新的 data,类似于给每个组件实例创 建一个私有的数据空间,
保护各自的数据互不影响
3.2 MVC 和 MVVM的区别
MVC:M(model数据)、V(view视图),C(controlle控制器)
缺点是前后端无法独立开发,必须等后端接口做好了才可以往下走;
前端没有自己的数据中心,太过依赖后台
MVVM:M(model数据)、V(view视图)、VM(viewModel控制数据的改变和控制视图)
html部分相当于View层,可以看到这里的View通过通过模板语法来声明式的将数据渲染进DOM元素,
当ViewModel对Model进行更新时,通过数据绑定更新到View。
Vue实例中的data相当于Model层,而ViewModel层的核心是Vue中的双向数据绑定,
即Model变化时VIew可以实时更新,View变化也能让Model发生变化
MVVM与MVC最大的区别就是:它实现了View和Model的自动同步,
也就是当Model的属性改变时,我们不用再自己手动操作Dom元素,来改变View的显示,
而是改变属性后该属性对应View层显示会自动改变
3.3 v-model 原理
是采用数据劫持结合发布者-订阅者模式的方式,
通过Object.defineProperty()来劫持各个属性的setter,getter,
在数据变动时发布消息给订阅者,触发相应的监听回调从而达到数据和视图同步。
3.4 vue中的data为什么是一个函数?(面试常问)
实际上就是一个闭包,因为vue是单页面应用,是由很多组件构成,每一个组件中都有一个data,
所以通过闭包给每一个组件创建了一个私有的作用域,这样就不会相互影响。
3.5 v-if 和 v-show的区别
v-if是通过添加和删除元素来进行显示或者隐藏
v-show是通过操作DOM修改display样式来修改元素的显示和隐藏
如果需要频繁的进行元素的显示和隐藏使用v-show性能更好
3.6 v-for中为什么要有key
key 可以提高虚拟DOM的更新效率。
在vue中,默认“就地复用”的策略,在DOM操作的时候,如果没有key 就会造成选项错乱
key 只能是字符串或者number,其他类型不可以
1. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,
Vue会根据【新数据】生成【新的虚拟DOM】,
随后Vue进行【新的虚拟DOM】与【旧的虚拟DOM】差异比较比较规则如下:
2. 比较规则:
1)旧虚拟DOM找到了与新虚拟DOM相同的key:
若虚拟DOM中内容没变,直接使用之前的真实DOM
若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
3. 用index作为key可能会引发的问题:
1)若对数据进行:逆序添加、逆序删除等破坏顺序的操作,会产生没有必要的真实DOM更新==>界面效果没问题,但效率低
2)如果结构中还包含输入类的DOM,会产生错误的DOM更新 ==> 界面有问题
3.7 打包后 dist 目录过大,解决办法?
- dist打包生成的文件中有 .map 文件,可以删除。在 vue.config.js文件中配置:productionSourceMap: false
- 组价和路由使用懒加载、按需引入等
- 对于文件和图片进行压缩。 安装压缩组件: compression-webpack-plugin
安装后进行导入配置:
最小化代码 minisize: true
分割代码: splitChunksl
超过限定值的文件进行压缩,threshold: 文件大小(字节为单位)
3.8 computed 和 watch 的区别
- computed是计算属性,watch是监听器,用来监听某一个值的变化进而触发相应的回调
- computed中的函数必须要有return返回、watch没有必须的要求返回return
- computed是第一次加载就触发一次,watch首次加载不会触发,如果需要首次加载需要设置immediate属性
- computed中的函数所依赖的属性没有发生变化,那么调用当前的函数的时候会从缓存中获取;而watch在每次监听值发生变化的时候都会执行回调。
3.9 vue组件之间的数据传递
3.9.1 父 传 子
通过在子组件身上绑定自定义属性,然后再子组件里使用props属性来接收即可
3.9.2 子 传 父
1)第一种方式:通过父组件给子组件传递函数类型的props实现:子组件给父组件传递数据
父组件:
子组件:
2)第二种方式:通过父组件给子组件绑定一个自定义事件实现:子组件给父组件传递数据
父组件
子组件
3)第三种方式:通过父组件给子组件绑定一个自定义事件实现:使用ref实现
父组件