前端面试练习24.3.12

本文详细介绍了CSSflex布局的使用、space-between和space-around的区别、粘性布局(sticky)的特点,以及opacity、visibility和display的对比。此外,还涵盖了JavaScript原型链、数组操作、V-model的工作原理、Vue组件间的通信方式(Vuex和Pinia)、浏览器事件轮询和TypeScript中的数组类型声明。
摘要由CSDN通过智能技术生成

目录

flex 布局如何使用

说出 space-between 和 space-around 的区别

介绍下粘性布局(sticky)

特点:

分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景。

结构:

继承:

性能:

居中为什么要使用 transform(为什么不使用 marginLeft/Top)

区别:

说一说transition 和 animation

Transition(过渡)

基本语法:

Animation(动画)

基本语法:

区别

JS原生的Object.definePrototype()的一些属性方法

一个数组,如何使用Math.max()取最大值

1.使用拓展运算符

2.使用apply()

多个数组的拼接

1.拓展运算符:

2.concat() 方法:

3.push() 方法:

4.使用 Array.from() 和合并操作:

v-model的实现原理

基础用法

实现原理

vue2组件间的通信

 vuex和pinia的区别

 浏览器的事件轮询

事件轮询的基本原理:

事件轮询过程大致分为以下几个阶段:

使用TS声明数组类型

使用元素类型 + 方括号 []:

 使用数组泛型 Array:

使用 Array 类型别名:

使用接口定义数组类型:


flex 布局如何使用

flex 是 Flexible Box 的缩写,意为"弹性布局"。指定容器display: flex即可。

容器有以下属性:flex-direction,flex-wrap,flex-flow,justify-content,align-items,align-content。

  • flex-direction属性决定主轴的方向;
  • flex-wrap属性定义,如果一条轴线排不下,如何换行;
  • flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap;
  • justify-content属性定义了项目在主轴上的对齐方式。
  • align-items属性定义项目在交叉轴上如何对齐。
  • align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

项目(子元素)也有一些属性:order,flex-grow,flex-shrink,flex-basis,flex,align-self。

  • order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
  • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
  • flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
  • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
  • flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
  • align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

说出 space-betweenspace-around 的区别

这个是 flex 布局的内容,其实就是一个边距的区别,

按水平布局来说,space-between是两端对齐,在左右两侧没有边距,而space-around是每个 子项目左右方向的 margin 相等,所以两个item中间的间距会比较大。

介绍下粘性布局(sticky

position 中的 sticky 值是 CSS3 新增的,设置了 sticky 值后,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。

特点:

  1. 元素不脱离文档流:设置了position: sticky的元素仍然保留在文档流中,它的位置不会影响其他元素的布局。

  2. 固定位置效果:当元素在容器中被滚动超过指定的偏移值时,元素会固定在容器内的指定位置。比如,如果设置了top: 50px,当粘性元素距离相对定位的容器顶部50px时,它就会固定在这个位置,不再向上移动。

  3. 相对偏移值的计算:元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素。如果祖先元素都不具有滚动功能,那么相对偏移值是相对于viewport来计算的,即浏览器窗口。

position: sticky的这些特点使得它非常适合创建需要在滚动时保持固定位置的元素,比如导航栏、表格头部等。

分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景。

结构:

display:none: 元素完全从渲染树中消失,渲染的时候不占据任何空间, 不能点击

visibility: hidden:不会让元素从渲染树消失,渲染元素占据空间,内容不可见,不能点击

opacity: 0: 不会让元素从渲染树消失,渲染元素继续占据空间,内容不可见,可以点击

继承:

display: none和opacity: 0:是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示。

visibility: hidden:是继承属性,子孙节点消失由于继承了hidden,通过设置visibility: visible;可以让子孙节点显式。

性能:

displaynone : 修改元素会造成文档回流,读屏器不会读取display: none元素内容,性能消耗较大

visibility:hidden: 修改元素只会造成本元素的重绘,性能消耗较少读屏器读取visibility: hidden元素内容

opacity: 0 : 修改元素会造成重绘,性能消耗较少

居中为什么要使用 transform(为什么不使用 marginLeft/Top

总的来讲就是transform不会触发页面的重排和重绘,而top/left 会导致重排

区别:

transform 属于合成属性(composite property),对合成属性进行 transition/animation 动画将会创建一个合成层(composite layer),这使得被动画元素在一个独立的层中进行动画。通常情况下,浏览器会将一个层的内容先绘制进一个位图中,然后再作为纹理(texture)上传到 GPU,只要该层的内容不发生改变,就没必要进行重绘(repaint),浏览器会通过重新复合(recomposite)来形成一个新的帧。

top/left 属于布局属性,该属性的变化会导致重排(reflow/relayout),所谓重排即指对这些节点以及受这些节点影响的其它节点,进行CSS计算->布局->重绘过程,浏览器需要为整个层进行重绘并重新上传到 GPU,造成了极大的性能开销。

灵活性:使用transform可以实现更多种居中方式,包括水平居中、垂直居中、水平垂直居中等,而且不受父元素宽高的限制。

性能:使用transform通常比使用marginLeftmarginTop更高效,因为transform不会触发页面的重排和重绘。重排和重绘会消耗更多的性能,特别是在有大量元素需要居中时。

简洁性:使用transform的代码通常更简洁,更易读,而且不需要考虑父元素的尺寸,因为transform是相对于元素本身进行定位的。

兼容性transform具有良好的兼容性,几乎所有现代浏览器都支持,包括移动端浏览器。

说一说transitionanimation

Transition(过渡)

transition 允许元素在一种状态变化到另一种状态时平滑地过渡。它可以应用于元素的属性,比如 width, height, color, opacity 等。

transition 需要两个状态:初始状态和最终状态,当触发状态变化时,会自动计算过渡中间状态,从而实现平滑的过渡效果。

基本语法:
/* 属性 过渡时间 过渡速度 */
transition: property duration timing-function;
  • property要过渡的 CSS 属性,可以是单个属性,也可以是多个属性,用逗号分隔。
  • duration过渡的持续时间,以秒(s)或毫秒(ms)为单位。
  • timing-function过渡效果的时间函数,包括 lineareaseease-inease-outease-in-out 等。

Animation(动画)

animation 允许你创建自定义的动画效果,可以控制动画的每一帧。它比 transition 更加灵活,可以定义更复杂的动画效果,包括旋转、缩放、位移等。

基本语法:
/* 动画名称 动画时长 过渡速度 延迟 动画次数 动画方向 填充模式 是否暂停 动画播放状态 */
animation: name duration timing-function delay iteration-count direction fill-mode play-state;
  • name定义动画名称,可以通过 @keyframes 定义。
  • duration动画持续时间,以秒(s)或毫秒(ms)为单位。
  • timing-function动画效果的时间函数,与 transition 相同。
  • delay动画开始之前的延迟时间,以秒(s)或毫秒(ms)为单位。
  • iteration-count动画播放次数,可以为数字或 infinite
  • direction动画播放方向,包括 normalreversealternatealternate-reverse
  • fill-mode动画结束后元素样式的状态,包括 noneforwardsbackwardsboth
  • play-state动画播放状态,包括 runningpaused

区别

  1. 灵活性animation 更加灵活,可以实现更复杂的动画效果;而 transition 只能在两种状态之间过渡。

  2. 定义方式transition 直接作用于 CSS 属性,而 animation 需要先定义关键帧(@keyframes)。

  3. 控制animation 可以通过 JavaScript 控制播放状态,而 transition 无法直接控制。

  4. 性能:在某些情况下,transitionanimation 更节省性能,特别是在只需要简单的过渡效果时。

JS原生的Object.definePrototype()的一些属性方法

Object.defineProperty() 是 JavaScript 中用于定义新属性或修改现有属性的方法。它允许我们精确控制属性的行为,包括属性的值、可枚举性、可配置性和可写性等。

下面是 Object.defineProperty() 的一些属性方法:

  1. value:要设置的属性的值。可以是任何有效的 JavaScript 值(数值、对象、函数等)。

  2. writable:布尔值,指定属性值是否可写。如果为 true,属性值可被修改;如果为 false,属性值不可被修改。默认为 false

  3. enumerable:布尔值,指定属性是否可枚举。如果为 true,属性可以通过 for...in 循环遍历到;如果为 false,属性不会被枚举。默认为 false

  4. configurable:布尔值,指定属性是否可配置。如果为 true,属性的可配置性可以被修改;如果为 false,属性的可配置性不可被修改,且属性不可删除。默认为 false

  5. get:函数,当访问属性时被调用。该函数返回属性的值。如果不存在此方法,则返回 undefined

  6. set:函数,当属性被修改时被调用。该函数接受被赋予的新值作为参数。

例如,下面是一个使用 Object.defineProperty() 定义新属性的示例:

var obj = {};

Object.defineProperty(obj, 'name', {
  value: 'John',
  writable: true,
  enumerable: true,
  configurable: true
});

console.log(obj.name); // 输出 "John"

在上面的示例中,我们定义了一个名为 name 的属性,其值为 'John',可写、可枚举和可配置。

一个数组,如何使用Math.max()取最大值

1.使用拓展运算符

var arr = [1, 2, 3, 4, 5];
var maxNumber = Math.max(...arr);
console.log(maxNumber); // 输出 5

2.使用apply()

var arr = [1, 2, 3, 4, 5];
var maxNumber = Math.max.apply(null, arr);
console.log(maxNumber); // 输出 5

多个数组的拼接

1.拓展运算符:

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

var concatenatedArray = [...arr1, ...arr2, ...arr3];
console.log(concatenatedArray); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]

2.concat() 方法:

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

var concatenatedArray = arr1.concat(arr2, arr3);
console.log(concatenatedArray); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]

3.push() 方法:

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

arr1.push(...arr2);
arr1.push(...arr3);

console.log(arr1); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]

4.使用 Array.from() 和合并操作:

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = [7, 8, 9];

var concatenatedArray = Array.from([arr1, arr2, arr3].reduce((acc, curr) => acc.concat(curr), []));
console.log(concatenatedArray); // 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]

v-model的实现原理

基础用法

v-model 本质上不过是语法糖,可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。

它会根据控件类型自动选取正确的方法来更新元素。

它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。


v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。


实现原理

v-model只不过是一个语法糖而已,真正的实现靠的还是 v-bind:绑定响应式数据
触发oninput 事件并传递数据
例如: 上面的等价于下面的写法

<input v-model="searchText">

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>
<!--
自html5开始,input每次输入都会触发oninput事件,
所以输入时input的内容会绑定到searchText中,于是searchText的值就被改变;
$event 指代当前触发的事件对象;
$event.target 指代当前触发的事件对象的dom;
$event.target.value 就是当前dom的value值;
在@input方法中,value => searchText;
在:value中,searchText => value;
-->

vue2组件间的通信

  1. Props 和 Events: 父组件可以通过 props 向子组件传递数据,子组件可以通过 events 发送消息给父组件。这是最常见的一种组件间通信方式。

  2. Vuex: Vuex 是 Vue.js 的官方状态管理库,用于在组件之间共享状态。可以将需要共享的状态存储在 Vuex 的 store 中,然后在任何组件中通过 getters、mutations 和 actions 进行状态的读取和修改。

  3. $emit 和 $on: Vue.js 提供了 $emit 和 $on 方法用于自定义事件的触发和监听。组件可以通过 $emit 触发一个自定义事件,其他组件可以通过 $on 监听该事件来实现通信。

  4. $parent 和 $children: 可以通过 $parent 和 $children 来访问父组件和子组件的实例,从而进行直接的通信。但这种方式一般不推荐,因为它会使组件的耦合度增加。

  5. provide 和 inject: 父组件可以通过 provide 提供数据,子组件可以通过 inject 来注入父组件提供的数据。这种方式可以实现祖先组件与后代组件之间的通信。

  6. 事件总线: 可以使用一个空的 Vue 实例作为事件总线,将事件注册在这个实例上,然后任何组件都可以通过这个实例来触发和监听事件。

 vuex和pinia的区别

主要就是体现在修改值这一方面比较直观,

使用vuex时,严格模式下,禁止直接修改 store 中的数据。这是为了确保状态的改变是可追踪的,同时也避免了状态的突变带来的难以调试的问题。如果需要修改 store 中的数据,应该通过提交 mutation 来修改。

在 Pinia 中,默认情况下也是不允许直接修改 store 中的数据的,需要通过提交 mutation 或者调用 action 来修改。不过 Pinia 也提供了一种非常规的方式来修改数据,即使用 store.state 属性直接访问 state 的数据,并且直接修改。这种方式不会触发任何 Pinia 提供的响应式特性,也不会进行任何状态变更的记录和追踪。因此,在开发中,不建议直接使用这种方式来修改 state。

所以,使用pinia的弊端也就是我们直接修改变量后无法做到追踪。

 浏览器的事件轮询

浏览器的事件轮询(Event Loop)是浏览器中用于处理异步任务和事件的一种机制。它是浏览器保持响应性的核心部分之一。在 JavaScript 引擎中,事件轮询负责管理执行任务队列,并在合适的时机执行任务。

事件轮询的基本原理:

  1. 执行栈(Execution Stack): JavaScript 是单线程的语言,代码的执行是在一个执行栈中进行的。当执行 JavaScript 代码时,它们会被按照执行顺序依次压入执行栈中,并执行其中的任务。

  2. 任务队列(Task Queue): 除了执行栈外,浏览器还有一个任务队列,用于存放异步任务和事件。当发生异步任务或事件时,它们会被放入任务队列中等待执行。

  3. 事件循环(Event Loop): 事件循环是一个持续运行的过程,它不断地检查执行栈和任务队列的状态,根据一定的规则将任务队列中的任务移入执行栈中执行。当执行栈为空时,事件循环会从任务队列中取出任务执行,这个过程会一直重复。

事件轮询过程大致分为以下几个阶段:

  • 执行同步任务: 首先执行执行栈中的同步任务,直到执行栈为空或者遇到异步任务。

  • 执行微任务(Microtask): 在同步任务执行完毕后,会立即执行所有微任务队列中的任务。微任务包括 Promise 的回调函数、MutationObserver 的回调函数等。

  • 执行宏任务(Macrotask): 如果执行栈为空,并且微任务队列中的任务执行完毕,事件循环会从宏任务队列中选择一个任务放入执行栈中执行。常见的宏任务包括 setTimeout、setInterval、requestAnimationFrame、I/O 操作等。

  • 更新渲染(Render): 在执行宏任务后,如果需要进行页面的渲染,浏览器会执行渲染操作,更新页面的视图。

  • 重复上述步骤: 事件循环会一直重复以上步骤,保持页面的响应性和流畅性。

使用TS声明数组类型

使用元素类型 + 方括号 []:

// 声明一个只包含数字类型的数组
let numbers: number[] = [1, 2, 3, 4, 5];

// 声明一个只包含字符串类型的数组
let strings: string[] = ['apple', 'banana', 'orange'];

 使用数组泛型 Array<elementType>:

// 声明一个只包含数字类型的数组
let numbers: Array<number> = [1, 2, 3, 4, 5];

// 声明一个只包含字符串类型的数组
let strings: Array<string> = ['apple', 'banana', 'orange'];

使用 Array 类型别名:

// 使用类型别名定义一个数组类型
type NumberArray = number[];

// 声明一个只包含数字类型的数组
let numbers: NumberArray = [1, 2, 3, 4, 5];

使用接口定义数组类型:

// 使用接口定义一个只包含数字类型的数组
interface NumberArray {
    [index: number]: number;
}

// 声明一个只包含数字类型的数组
let numbers: NumberArray = [1, 2, 3, 4, 5];

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿online

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值