HTML+CSS
Javascript
1.什么是事件委托?
- 概念:将子元素的事件委托给父级元素去处理
- 好处:节约内存+方便管理+防止内存泄漏
- 节约内存:事件监听器的数量少
- 方便管理:当子元素动态删减时,无需考虑其事件监听器动态删减的问题
- 防止内存泄漏:当子元素删除时,无需删除其对应的事件监听器
- ps:何为内存泄漏?
2.何为内存泄漏?
- 用闭未释放的【全局变量+闭包+定时器+事件监听器】
- 当我们删除DOM元素时,忘记删除其对应的事件监听器
- 当我们离开页面时,没有释放掉各种的事件监听器
- 用完的全局变量没有释放,obj = null
- 用完的定时器没有clear掉
- 用完未释放的数据闭包,newFn = null
3.ES6有哪些新特性?
- 分为四个层面:变量层面+数据结构层面+函数层面+类层面
变量层面:
- let:克服了var的弊病(变量提升+作用域穿透+重复声明)
- const:把不希望被改变地址的对象声明为常量
数据结构层面:
- 数组的展开+解构
- 对象的简写+解构
- 字符串:模板字符串
- Map:方便增删改查的键值对存储器
- Set:有序且不重复的元素集
函数层面:
- 箭头函数:this从父级作用域当中继承
- ps:this有哪些存在的情形?
类层面:
- class系列语法:class(构造函数+原型属性),constructor(函数构造器),static:静态成员(属性+方法),super()调用父类的属性+方法,super(name)调用父类构造器,super.xxx() 调用父类实例方法
4.this所有可能情形?
- 普通函数:函数的this为该函数的调用者(显式主语/无显式主语时,隐式的为window/DOM元素的事件监听器的this恒为事件源e.currentTarget)
- 箭头函数:函数的this从父级作用域当中继承(可以认为箭头函数就是没有this)
- 普通函数可以通过call(),apply(),bind(),来改变函数的this
- constructor构造器当中的this,为当前构造的实例
- 实例方法当中的this,为当前实例
- 静态属性/方法当中的this,为当前类
5.请说出十个请求头
6.请说出十个响应头
7.什么是深拷贝以及什么是浅拷贝
8.什么是值传递以及什么是引用传递
9.谈谈对事件传播/派发机制的理解
10.谈谈对闭包的理解
Git
Vue
1.谈谈你对Vue的理解
- MVVM:VM层相当于MVC分层当中C层的一部分特定职能的分离,即实时监控数据和读取数据变化,当数据修改时,及时通知视图更新。
- 响应式:与VM本质相同,提法不同,都是数据驱动视图,声明响应式数据,当数据变化时,驱动视图更新。
- 组件化开发:把一个页面分隔成若干个小块(组件),每个组件都有自己的模板,数据,样式,逻辑,相互独立,互不干扰,目的就是为了方便复用。
- 虚拟DOM:把真实的DOM结构映射成JS对象,目的就是为了,当数据发生变化时,能够快速的递归比较出发生变化的节点,比较的过程就是diff算法的过程。
- diff算法:对数据实行差量渲染,最大化的使用上一次缓存的结果,前提是需要得到两个新老虚拟DOM的不同之处。在暴力递归的基础做了很多优化,例如用key去唯一标识特定的节点。
- SPA单页面应用开发框架:当浏览器的路由地址发生变化时,是在同一个页面里面切换不同的组件,实现了整站开发的效果。
2.列表当中key的作用
- 在diff算法的过程当中,提升了很大的性能
- 当新老虚拟DOM的key相同时,直接认定其节点的整个DOM结构没有发生变化,直接使用上一次老的虚拟DOM渲染的结果,不带对其进行深入的递归比较,极大的提高了性能。
- 当新老虚拟DOM的key不同时,也不带对其节点进行深入的递归比较,而是直接把老的干掉,原地根据新的数据进行渲染新的节点。
3.computed和watch的区别
- 共同点:都是侦听一手数据状态变化,从而触发相应的逻辑
- computed:专注于根据一手数据状态变化换算出二手数据状态,即计算属性
- computed只有在计算属性依赖的数据项发生变化时,才会重新根据新的一手数据状态进行计算,否则直接复用上一次的渲染结果。
- computed不应该产生副作用。
- watch是专门侦听特定数据的变化,从而触发相应的副作用逻辑。
4.Vue的生命周期有哪些
- 创建实例阶段(init option):beforeCreate,created
- 挂载阶段(渲染DOM):beforeMount,mounted
- 数据更新阶段(数据驱动视图):beforeUpdate,updated
- 卸载阶段(渲染条件不成立/用户切换页面):beforeUnmount,unmounted
- Vue2当中两个卸载阶段:beforeDestroy,destroyed
- 八大生命周期图解:
5.父子组件生命周期联动
- 原则:父组件搭台,子组件唱戏
- 创建实例与挂载阶段:父组件创建实例完毕并预备挂载,子组件一一创建实例完毕并挂载完毕,父组件宣布整体挂载完毕。
- 数据更新阶段:父组件预备更新,子组件一一更新完毕,父组件宣布整体更新完毕。
- 卸载阶段:父组件预备卸载,子组件一一卸载完毕,父组件宣布整体卸载完毕。
6.Vue有哪些常用的修饰符
- 事件修饰符:stop、prevent、capture、once、self
- 键盘修饰符:esc,ctrl,shift,meta,enter
- 系统修饰符:exact
- v-model修饰符:lazy,number,trim
- 自定义v-model修饰符
- 自定义指令修饰符
7.v-if和v-show的区别
- 渲染条件不成立时:v-if压根就不存在,v-show不显示(display:none)
- 适合使用v-show的场景:频繁的切换显隐
- 适合使用v-if的场景:一锤子买卖(例如某某电影专区,需要VIP才可以观看)
8.谈谈你对nexttick的理解
- 当数据变化时,无法立即拿到最新状态下的DOM
- 数据变化是立刻完成,渲染跟进是需要时间的(异步)
- 可以通过nexttick(()=>{在这里可以拿到最新的DOM状态})
- 在nexttick回调函数当中,是在DOM结构渲染(更新)完毕才回调,这时候就可以拿到DOM的最新状态
9.什么是具名插槽以及什么是作用域插槽?
- 具名插槽:就是插槽内容有很多,需要指定某些内容到哪个插槽当中,就需要指名道姓
//子组件
<son>
<slot name="head">
<P>我是head具名插槽的默认内容</p>
</slot>
</son>
//父组件
<father>
<template #head>
<P>我是外界注入的head插槽的内容</p>
</template>
</father>
- 作用域插槽:父组件在自己的模板上部署子组件及其插槽内容时,只能使用父组件自身作用域内的数据,要想子组件内部的数据,就需要用到作用域插槽
- 作用域插槽,子组件需要自己暴露数据供父组件使用,暴露的数据,会以一个对象的方式,父组件只需起一个别名接收即可
//子组件
<son>
<slot name="head" :age="18" :color="red">
<P>我是head具名插槽的默认内容</p>
</slot>
</son>
//父组件
<father>
<template #head="newObj">
<p>{{newObj.age}}</p>
<p>{{newObj.color}}</p>
<P>我是外界注入的head插槽的内容</p>
</template>
</father>
10.Vue组件通信方式有哪些?
- 父子通信:prop down
- 子父通信:event up
- 祖孙通信:provide + inject
provide() 接受两个参数:第一个参数是要注入的 key,可以是一个字符串或者一个 symbol,第二个参数是要注入的值。
<script setup>
import { ref, provide } from 'vue'
// 提供静态值
provide('foo', 'bar')
// 提供响应式的值
const count = ref(0) provide('count', count)
</script>
<script setup>
import { inject } from 'vue'
// 注入值的默认方式
const foo = inject('foo')
// 注入响应式的值
const count = inject('count')
// 注入一个值,若为空则使用提供的默认值
const bar = inject('foo', 'default value')
// 注入一个值,若为空则使用提供的工厂函数
const baz = inject('foo', () => new Map())
// 注入时为了表明提供的默认值是个函数,需要传入第三个参数
const fn = inject('function', () => {}, false)
</script>
- 子组件自己暴露给父组件:expose
//子组件
export default {
expose:{
myname,
myage,
sayHelloFn
}
}
//父组件
<son ref="sonRef"/>
this.$refs.sonRef.sayHelloFn()
//Vue3
//子组件
<script setup>
import { ref,defineExpose } from 'vue'
const a = 1
const b = ref(2)
defineExpose({
a,
b
})
</script>
//父组件
<son ref="sonRef"/>
this.$refs.sonRef.a
- 使用全局状态管理自由通信:把需要共享的数据状态都存储在【具有响应式的中央数据仓库里】使用vuex/pinia,并且对外暴露CRUD接口,任意组件去修改数据状态,其他用到改状态的组件,都会具有响应,根本不必去可以通信