1.元素居中的方法
目录
[1. 水平居中](#1. 水平居中)
[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 裁剪)
元素居中可以分为水平居中、垂直居中和水平垂直居中。
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 | 希望组件与路由解耦 |