vue前端面试题——记录一次面试当中遇到的题(8)

1.元素居中的方法

目录

1.元素居中的方法

[1. 水平居中](#1. 水平居中)

2.垂直居中

3.水平垂直居中

2.元素显示与隐藏方式?隐藏后还会触发函数吗?

[1. display: none - 完全隐藏](#1. display: none - 完全隐藏)

[2. visibility: hidden - 视觉隐藏](#2. visibility: hidden - 视觉隐藏)

[3. opacity: 0 - 透明度隐藏](#3. opacity: 0 - 透明度隐藏)

[4. 尺寸归零法](#4. 尺寸归零法)

[5. 定位移出屏幕](#5. 定位移出屏幕)

[6. clip-path 裁剪](#6. clip-path 裁剪)

3.箭头函数和普通函数的区别?

4.怎么获取对象当中的某一个值

5.作用域和作用域链

6.怎么判断数组是不是数组?

8.computed和watch和method的区别

9.组件通讯

10.父组件访问子组件的方法?

11.路由懒加载?

12.路由传参?两种方式的区别?


元素居中可以分为水平居中、垂直居中和水平垂直居中。

1. 水平居中

行内/行内块元素

css 复制代码
.parent {
  text-align: center;
}

.child {
  display: inline; /* 或 inline-block */
}

块级元素(固定宽度)

css 复制代码
.child {
  width: 200px;
  margin: 0 auto;
}

任意元素 - Flexbox

css 复制代码
.parent {
  display: flex;
  justify-content: center;
}

任意元素 - Grid

css 复制代码
.parent {
  display: grid;
  justify-content: center;
}
2.垂直居中

单行文本

css 复制代码
.parent {
  height: 100px;
  line-height: 100px; /* 与高度相同 */
}

行内/行内块元素

css 复制代码
.parent {
  height: 200px;
  line-height: 200px; /* 方法一 */
}

.child {
  display: inline-block;
  vertical-align: middle; /* 方法二 */
}

任意元素 - Flexbox

css 复制代码
.parent {
  display: flex;
  align-items: center;
  height: 300px; /* 需要指定高度 */
}

任意元素 - Grid

css 复制代码
.parent {
  display: grid;
  align-items: center;
  height: 300px;
}

绝对定位 + transform

css 复制代码
.parent {
  position: relative;
  height: 300px;
}

.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
3.水平垂直居中

Flexbox(推荐⭐)

css 复制代码
.parent {
  display: flex;
  justify-content: center;  /* 水平居中 */
  align-items: center;      /* 垂直居中 */
  height: 100vh;           /* 需要高度 */
}

/* 或者使用 margin: auto */
.parent {
  display: flex;
  height: 100vh;
}

.child {
  margin: auto;
}

Grid(现代推荐)

css 复制代码
.parent {
  display: grid;
  place-items: center; /* 同时设置水平和垂直居中 */
  height: 100vh;
}

/* 或者分别设置 */
.parent {
  display: grid;
  justify-content: center;
  align-content: center;
  height: 100vh;
}

绝对定位 + transform(经典万能)

css 复制代码
.parent {
  position: relative;
  height: 100vh;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

绝对定位 + margin(已知尺寸)

css 复制代码
.parent {
  position: relative;
  height: 100vh;
}

.child {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 100px;
  margin-top: -50px;  /* height/2 */
  margin-left: -100px; /* width/2 */
}

表格布局(传统方法)

css 复制代码
.parent {
  display: table;
  width: 100%;
  height: 100vh;
}

.child {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
2.元素显示与隐藏方式?隐藏后还会触发函数吗?
1. display: none - 完全隐藏

特点:

  • 元素完全不渲染,不占据任何空间

  • 无法触发任何事件(点击、悬停等)

  • 会导致浏览器重排和重绘

  • 屏幕阅读器无法访问

2. visibility: hidden - 视觉隐藏

特点:

  • 元素不可见,但仍占据布局空间

  • 无法触发鼠标事件(点击、悬停等)

  • 但可以触发键盘事件和焦点事件

  • 会导致浏览器重绘(但不重排)

3. opacity: 0 - 透明度隐藏

特点:

  • 元素完全透明,但仍占据布局空间

  • 可以触发所有事件

  • 元素仍然可交互(可点击、可聚焦)

  • 支持 CSS 过渡动画

4. 尺寸归零法
css 复制代码
.hidden {
  width: 0;
  height: 0;
  overflow: hidden;
}
  • 元素不占据可见空间

  • 通常无法触发鼠标事件(因为没有尺寸)

  • 但元素仍然在 DOM 中

5. 定位移出屏幕
css 复制代码
.hidden {
  position: absolute;
  left: -9999px;
  top: -9999px;
}

特点:

  • 元素在视觉上看不到

  • 可以触发所有事件

  • 屏幕阅读器可以访问

  • 常用于隐藏但需要保持可访问性的元素

6. clip-path 裁剪
css 复制代码
.hidden {
  clip-path: circle(0);
  /* 或者 */
  clip-path: inset(100%);
}

特点:

  • 元素被裁剪到不可见

  • 可以触发事件(在原始位置)

  • 支持动画效果

3.高度塌陷怎么解决?

高度塌陷通常发生在父元素包含浮动子元素时,父元素的高度无法被撑开,导致布局混乱。

方案一:使用清除浮动 - 最常用⭐

(1)使用空元素清除浮动

在浮动元素后添加一个空元素,并设置clear:both。

html 复制代码
<div class="parent">
<div class="child float-left">浮动元素</div>
<div style="clear: both;"></div>
</div>

(2)使用伪元素清除浮动(常用,且可以封装成通用类)

在父元素上添加clearfix类。

css 复制代码
.clearfix::after {
content: "";
display: block;
clear: both;
}

方案二:触发 BFC(块级格式化上下文)

  • 设置overflow不为visible(例如:overflow: auto; 或 overflow: hidden;)

  • 设置display为inline-block、table-cell、table-caption、flow-root等

  • 设置float不为none

  • 设置position为absolute或fixed

注意:触发BFC可能会有一些副作用,比如overflow hidden会剪裁超出部分,float会使父元素宽度变化等。

方案三:给父元素设置固定高度

css 复制代码
.parent {
  border: 2px solid red;
  background: #f0f0f0;
  height: 120px; /* 固定高度 */
}

方案四:使用 Flexbox 或 Grid 布局

**(1)**Flexbox 方案:

css 复制代码
.parent {
  border: 2px solid red;
  background: #f0f0f0;
  display: flex; /* 自动包含浮动元素 */
  flex-wrap: wrap; /* 如果需要换行 */
}

**(2)**Grid 方案:

css 复制代码
.parent {
  border: 2px solid red;
  background: #f0f0f0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
4.箭头函数和普通函数的区别?
  • this继承自定义时的外层作用域 ,且无法被修改
  • 不能作为构造函数 ,使用new会报错
  • 没有arguments对象 ,需通过剩余参数(...args 获取参数
  • 没有prototype属性 ,也不能使用super(因无原型链关联)
5.怎么获取对象当中的某一个值

(1)点符号(Dot Notation):当你知道属性的名称,并且属性名是一个有效的标识符(不包含空格、不以数字开头、不是保留字等)时,可以使用点符号。

javascript 复制代码
let obj = { name: "Alice", age: 30 };
let name = obj.name; // "Alice"

(2)方括号符号(Bracket Notation):当属性名包含空格、特殊字符,或者是一个变量时,可以使用方括号符号。

javascript 复制代码
let obj = { "first name": "Alice", age: 30 };
let firstName = obj["first name"]; // "Alice"

let property = "age";
let age = obj[property]; // 30

(3)解构赋值(Destructuring Assignment):如果你想要从对象中提取多个属性,可以使用解构赋值。

javascript 复制代码
let obj = { name: "Alice", age: 30 };
let { name, age } = obj;
console.log(name); // "Alice"
console.log(age); // 30

(4)使用默认值:如果属性可能不存在,你可以使用解构赋值时设置默认值,或者使用逻辑运算符。

javascript 复制代码
// 解构赋值设置默认值
let { name, age, gender = "unknown" } = obj;

// 使用逻辑运算符
let gender = obj.gender || "unknown";

(5)可选链操作符(Optional Chaining):如果你不确定对象是否存在,或者属性是否存在,可以使用可选链操作符(?.)来安全地访问嵌套属性。

javascript 复制代码
let obj = { person: { name: "Alice" } };
let name = obj.person?.name; // "Alice"
let city = obj.person?.address?.city; // undefined,不会报错

(6)使用in运算符检查属性是否存在 :如果你需要检查对象中是否存在某个属性,可以使用in运算符。

javascript 复制代码
if ("name" in obj) {
  console.log(obj.name);
}

(7)使用hasOwnProperty方法:检查对象自身(非继承)是否具有指定属性。

javascript 复制代码
if (obj.hasOwnProperty("name")) {
  console.log(obj.name);
}

(8)使用Object.values()Object.entries():如果你需要获取对象的所有值或键值对,可以使用这些方法。

javascript 复制代码
let obj = { a: 1, b: 2, c: 3 };
let values = Object.values(obj); // [1, 2, 3]
let entries = Object.entries(obj); // [['a', 1], ['b', 2], ['c', 3]]

(9)使用Object.getOwnPropertyDescriptor():获取对象某个属性的描述符(可配置、可枚举、可写等)。

javascript 复制代码
let descriptor = Object.getOwnPropertyDescriptor(obj, "name");
6.作用域和作用域链

作用域指的是变量的可访问范围,分为全局作用域、函数作用域和块级作用域。

全局作用域在任何地方都可以访问,函数作用域只能在函数内部访问,块级作用域是ES6引入的,用let和const声明的变量在{}内有效。

作用域链是JavaScript查找变量的规则:从当前作用域开始,逐级向上查找,直到全局作用域。JavaScript采用词法作用域,意味着作用域在代码书写阶段就确定了,这形成了闭包的基础。比如内层函数可以访问外层函数的变量,就是因为作用域链的存在。

7.怎么判断数组是不是数组?

(1)Array.isArray()

这是ES5引入的方法,专门用于判断一个值是否为数组。它是最可靠和标准的方法。

javascript 复制代码
const arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true

const notArr = {0: 1, 1: 2, length: 2};
console.log(Array.isArray(notArr)); // false

(2) instanceof运算符

检查对象是否为Array构造函数的实例。但这种方法在多个iframe或window环境中可能失败,因为不同环境的Array构造函数可能不同。

javascript 复制代码
const arr = [1, 2, 3];
console.log(arr instanceof Array); // true

const notArr = {};;
console.log(notArr instanceof Array); // false

(3)Object.prototype.toString.call()

这是一种通用的方法,可以判断任何对象的类型。对于数组,它会返回[object Array]

javascript 复制代码
const arr = [1, 2, 3];
console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

const notArr = {};
console.log(Object.prototype.toString.call(notArr) === '[object Array]'); // false

(4)constructor属性

检查对象的constructor属性是否指向Array。但是,对象的constructor属性可以被修改,所以不可靠。

javascript 复制代码
const arr = [1, 2, 3];
console.log(arr.constructor === Array); // true

// 但是,如果修改了constructor属性,就不准确了
arr.constructor = Object;
console.log(arr.constructor === Array); // false

7.闭包

闭包是指能够访问自由变量的函数。自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。

形成条件:函数嵌套,内部函数引用外部函数变量,内部函数被返回或引用。

作用:可以读取函数内部的变量,并让这些变量始终保持在内存中。

应用场景:封装私有变量、模块化、循环中保存变量等。

优缺点:优点是可以实现封装和数据持久化;缺点是可能引起内存泄露,需要及时释放。

8.computed和watch和method的区别

计算属性(computed)

定义:计算属性是基于它们的响应式依赖进行缓存的。只有在相关响应式依赖发生改变时它们才会重新求值。

使用场景:适用于需要根据现有数据计算得到新数据的场景,且计算过程可能比较耗时或需要复用。

特点

  • 缓存:只要依赖的数据没有发生变化,多次访问计算属性会立即返回之前的计算结果,而不会重新执行函数。

  • 响应式:只有当依赖的响应式数据发生变化时,才会重新计算。

  • 必须返回一个值,并且通常不应该有副作用(如异步操作或改变外部状态)。

侦听器(watch)

定义:watch用于监听特定数据的变化,并在数据变化时执行异步或开销较大的操作。

使用场景:适用于在数据变化后需要执行异步操作或复杂逻辑的场景。

特点

  • 监听数据的变化,执行回调函数。

  • 可以执行异步操作。

  • 不需要返回值,通常用于执行副作用。

方法(methods)

定义:methods是挂载在Vue实例上的函数,可以在模板中调用,也可以在其他方法中调用。

使用场景:适用于需要响应用户事件、执行任意逻辑(包括异步操作)的场景。

特点

  • 不会缓存,每次调用都会执行函数。

  • 可以接受参数。

  • 可以在模板中通过事件绑定调用,也可以在计算属性、侦听器或其他方法中调用。

总结:

computed 是计算属性,有缓存,依赖不变不会重新计算,适合模板中的复杂逻辑。

watch 是侦听器,观察数据变化执行副作用,支持异步,适合搜索、验证等场景。

methods 是方法,无缓存,适合事件处理和通用函数。

简单说:需要缓存的计算用 computed,响应数据变化用 watch,处理事件用 methods

9.组件通讯

|-----------------------------|--------|---------------|------------|
| Props / Events | 父子组件双向 | 直接父子关系 | Vue 2/3 |
| v-model | 父子组件双向 | 表单输入、组件双向绑定 | Vue 2/3 |
| $emit / v-on | 子向父 | 子组件通知父组件 | Vue 2/3 |
| $parent / $children | 父子组件访问 | 直接访问父子实例(不推荐) | Vue 2/3 |
| $refs | 父访问子 | 调用子组件方法、访问DOM | Vue 2/3 |
| Event Bus | 任意组件 | 简单项目、兄弟组件通讯 | Vue 2 |
| Provide / Inject | 跨层级 | 祖先向后代传递数据 | Vue 2.2+/3 |
| Vuex / Pinia | 全局状态 | 复杂应用、多组件共享状态 | Vue 2/3 |
| Local Storage | 数据持久化 | 页面刷新后保持状态 | 所有 |

10.父组件访问子组件的方法?

方法一:使用 ref$refs(最推荐⭐)

方法二:使用 $children(不推荐)

方法三:Vue 3 + <script setup> 使用 defineExpose 暴露方法,父组件才能访问。

11.路由懒加载?

路由懒加载 也叫按需加载,指的是只有当用户访问某个路由时,才加载该路由对应的组件代码,而不是在应用初始化时就加载所有路由组件。

主要通过 ES6 的动态 import() 语法实现,Webpack 或 Vite 会自动将动态导入的组件分割成独立的 chunk 文件。

主要好处:

  • "减小初始包体积,提升首屏加载速度"

  • "按需加载,避免加载用户永远不会访问的页面"

  • "更好的缓存策略,只有修改的页面需要重新加载"

具体用法:

  • "在路由配置中,把静态导入 import Home from '@/views/Home.vue' 改为动态导入 () => import('@/views/Home.vue')"
12.路由传参?两种方式的区别?

路由传参主要有两种方式:查询参数(query)和动态路由参数(params)。此外,还可以通过props配置来传递参数。下面详细说明这几种方式及其区别。

1. 查询参数(query)
  • 使用方式 :在路由路径后面以?开头,使用&分隔多个参数。

  • 特点 :参数会显示在URL中,例如/user?name=john&age=20

  • 适用场景:可选参数,比如过滤条件、分页等。

  • 在Vue Router中的使用

    • 通过this.$route.query访问。

    • 通过<router-link :to="{ path: '/user', query: { name: 'john', age: 20 } }">或编程式导航this.$router.push({ path: '/user', query: { name: 'john', age: 20 } })传递。

2. 动态路由参数(params)
  • 使用方式 :将参数作为路由路径的一部分,例如/user/123,其中123是用户ID。

  • 特点 :参数是路由的一部分,不会显示在?后面,而是直接嵌入在URL路径中。

  • 适用场景:必传参数,比如资源ID。

  • 在Vue Router中的使用

    • 需要在路由配置中定义参数,例如:{ path: '/user/:id', component: User }

    • 通过this.$route.params访问。

    • 通过<router-link :to="{ name: 'user', params: { id: 123 } }">或编程式导航this.$router.push({ name: 'user', params: { id: 123 } })传递。注意:使用params时,不能使用path,必须使用name。

3. 通过props传递参数
  • 使用方式 :在路由配置中设置props: true,可以将params作为组件的props传递。也可以设置为一个函数,返回一个对象作为组件的props。

  • 特点 :使组件与路由解耦,组件内部可以直接使用props接收参数,而不必依赖$route对象。

  • 适用场景:希望组件更独立,不直接与路由耦合。

  • 在Vue Router中的使用

    • 路由配置:{ path: '/user/:id', component: User, props: true },这样在User组件中可以直接定义props: ['id']来接收。

    • 也可以使用函数模式:props: (route) => ({ id: route.params.id, query: route.query })

区别对比
特性 查询参数 (query) 动态路由参数 (params) props传参
URL形式 ?后面,以键值对形式 作为路径的一部分 同params或query,但组件内通过props接收
是否必传 可选 在路由中定义了就是必传(除非设置为可选) 同params或query
路由配置 不需要在路由配置中定义 必须在路由配置中定义参数 需要设置props为true或函数
传递方式 通过query对象传递 通过params对象传递,且必须用name 同params或query,但组件内接收方式不同
组件内获取 this.$route.query this.$route.params 通过props
刷新后 参数保留在URL中,不会丢失 参数保留在URL中,不会丢失 同params或query
使用场景 可选参数,如分页、筛选 必传参数,如资源ID 希望组件与路由解耦
相关推荐
仰望.18 小时前
vue 下拉框 vxe-select 实现人员选择下拉列表
前端·javascript·vue.js·vxe-ui
丘耳18 小时前
@tiptap/vue-2 知识点笔记-03
前端·javascript·vue.js
丘耳19 小时前
@tiptap/vue-2 知识点笔记-05
前端·javascript·vue.js
m0_6161884919 小时前
使用el-table实现行内编辑功能
前端·javascript·vue.js
Mintopia19 小时前
🧬 AIGC 内容溯源技术:Web 平台如何识别 AI 生成内容?
前端·javascript·aigc
.NET修仙日记19 小时前
jQuery面试题精选:从基础到高级
前端·javascript·jquery
Mintopia19 小时前
⚙️ Next.js 缓存 + 分页优化:让你的页面速度快得像量子比特 🧠✨
前端·全栈·next.js
玲小珑19 小时前
LangChain.js 完全开发手册(十五)实战综合项目一:智能文档处理系统
前端·langchain·ai编程
午安~婉19 小时前
硅谷甄选(续2)首页
java·前端·javascript