前端面试八股复习心得

这两天复习备战字节跳动一面,虽然知道自己很没有实力,但是必将是自己吹出去的牛,还是一定要做到

一.css布局

弹性布局

javascript 复制代码
.container {
  display: flex; /* 或者 inline-flex */
}

一旦设置了 display: flex,这个容器(.container)的直接子元素就会自动成为 Flex 项目

现在,这些 Flex 项目就不再是普通的块级或行内元素了,它们会遵循 Flexbox 的规则进行排列。

Flex 容器的核心属性(控制项目如何排列)

容器的属性主要用来设置主轴的方向、是否换行以及项目在主轴和交叉轴上的对齐方式。

1. flex-direction- 定义主轴方向

决定项目如何排列(是横着排还是竖着排)。

  • row(默认值):主轴为水平方向,起点在左端。

  • row-reverse:主轴为水平方向,起点在右端。

  • column:主轴为垂直方向,起点在上沿。

  • column-reverse:主轴为垂直方向,起点在下沿。

2. justify-content- 项目在主轴上的对齐方式

如何分配项目之间及其周围的空间。

  • flex-start(默认值):向主轴起点对齐。

  • flex-end:向主轴终点对齐。

  • center: 居中对齐。

  • space-between:两端对齐,项目之间的间隔都相等。

  • space-around:每个项目两侧的间隔相等。所以项目之间的间隔比项目与边框的间隔大一倍。

  • space-evenly:所有间隔都完全相等。

3. align-items- 项目在交叉轴上的对齐方式

(单行情况下)如何对齐一行内的项目。

  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。

  • flex-start:向交叉轴的起点对齐。

  • flex-end:向交叉轴的终点对齐。

  • center: 在交叉轴中居中对齐。

  • baseline: 项目的第一行文字的基线对齐。

4. flex-wrap- 定义是否换行

默认情况下,项目都排在一条轴线上。flex-wrap定义当一条轴线排不下时如何换行。

  • nowrap(默认):不换行。

  • wrap:换行,第一行在上方。

  • wrap-reverse:换行,第一行在下方。

Flex 项目的核心属性(控制项目自身)

项目的属性可以用来控制单个项目在容器中的表现。

1. flex-grow- 放大比例

定义项目的放大能力。默认值为 0,即如果存在剩余空间,也不放大。

如果所有项目的 flex-grow属性都为 1,则它们将等分剩余空间。如果一个项目的 flex-grow属性为 2,其他项目都为 1,则前者占据的剩余空间将比其他项多一倍。

2. flex-shrink- 缩小比例

定义项目的缩小能力。默认值为 1,即如果空间不足,该项目将缩小。

如果所有项目的 flex-shrink属性都为 1,当空间不足时,都将等比例缩小。如果一个项目的 flex-shrink属性为 0,其他项目都为 1,则空间不足时,前者不缩小。

3. flex-basis- 项目占据的主轴空间

定义在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性计算是否有多余空间。它的值可以设为 auto(默认,即项目本来的大小)或一个固定的长度(如 200px)。

4. 简写属性:flex

flex属性是 flex-grow, flex-shrinkflex-basis的简写。强烈推荐使用这个简写

一些最常用的值:

  • flex: 1: 等价于 flex: 1 1 0%。项目会伸缩以填满空间。

  • flex: auto: 等价于 flex: 1 1 auto

  • flex: none: 等价于 flex: 0 0 auto。项目完全不可伸缩。

  • flex: 0 0 200px: 项目基础宽度为 200px,不放大也不缩小(类似固定宽度侧边栏)。

5. align-self- 允许单个项目有不一样的对齐方式

可覆盖容器的 align-items属性。属性值与之相同。


一个经典示例:实现水平垂直居中

在 Flexbox 出现之前,垂直居中是个老大难问题。现在变得非常简单

javascript 复制代码
.container {
  display: flex;
  justify-content: center; /* 主轴(水平)居中 */
  align-items: center;     /* 交叉轴(垂直)居中 */
  height: 300px; /* 给容器一个高度 */
  border: 1px solid #ccc;
}
.centered-item {
  /* 无需任何设置 */
}

网格布局

一、核心概念:它是什么?

CSS 网格布局 ​ 是 CSS 中目前最强大的二维布局系统。与 弹性布局(Flexbox) ​ 主要处理一维布局 (行 列)不同,网格布局被设计用来同时在行和列两个维度上处理布局。

你可以把网格布局想象成一张 或一个表格,你可以在上面精确地放置和排列元素。它让你能够将网页划分成一个个由行和列组成的区域,然后将页面元素放入这些预定义或动态生成的区域中。

二、为什么需要它?------ 对比弹性布局

弹性布局(Flexbox)非常出色,但它本质上是"一维"的:

  • 它主要处理一条轴线上的布局(要么是水平的主轴,要么是垂直的交叉轴)。

  • 虽然可以换行(flex-wrap: wrap),但下一行的项目与上一行的项目在列方向上没有对齐关系

网格布局的优势在于"二维"控制:

  • 同时定义行和列:你可以先定义好整个页面的网格结构,然后再将元素放置到这个网格的任意位置。

  • 精确的布局控制:可以轻松实现报纸杂志式的复杂布局,比如一个元素跨越多行多列。

  • 解决等高、精准对齐等难题:网格轨道(行/列)的结构性保证了内容的对齐。

示例:创建一个 3x3 的网格

javascript 复制代码
.container {
  display: grid;
  grid-template-columns: 100px 200px 100px; /* 三列:宽100px, 200px, 100px */
  grid-template-rows: 80px 120px 80px;     /* 三行:高80px, 120px, 80px */
}

常用的单位:

  • 固定单位px

  • 相对单位%, fr关键单位! ), em, rem

  • 灵活单位auto, min-content, max-content

fr单位(片段单位):

这是一个为网格布局而生的单位,代表剩余空间的分配比例 。它类似于 Flexbox 中的 flex-grow

javascript 复制代码
.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr; /* 总宽度分为4份,第二列占2份,第一、三列各占1份 */
}

用于简化重复模式的书写。

2. 网格间距:gap

用于设置网格线之间的间距,是 row-gapcolumn-gap的简写。

javascript 复制代码
.container {
  gap: 20px 10px; /* 行间距20px,列间距10px */
  /* 等同于 */
  /* row-gap: 20px; */
  /* column-gap: 10px; */
}
3. 隐式和显式网格:grid-auto-rowsgrid-auto-columns

当你明确使用 grid-template-rows/columns定义的网格是显式网格 。如果你放置的项目超出了这个显式网格,浏览器会自动创建新的网格轨道,这被称为隐式网格

grid-auto-rows/columns就是用来控制这些隐式网格轨道大小的。


五、网格项目的核心属性(控制项目放置)

这些属性用在网格项目上,用来指定该项目在网格中的具体位置。

1. 基于网格线的放置

网格线是划分网格的线条,有数字索引(从1开始)也可以自定义名称。一个3列的网格有4条垂直的网格线。

网格线是划分网格的线条,有数字索引(从1开始)也可以自定义名称。一个3列的网格有4条垂直的网格线。

  • grid-column-start:项目从第几条垂直网格线开始。

  • grid-column-end:项目到第几条垂直网格线结束。

  • grid-row-start:项目从第几条水平网格线开始。

  • grid-row-end:项目到第几条水平网格线结束。

    示例:让一个项目占据多行多列

    javascript 复制代码
    .item-1 {
      grid-column: 1 / 3;  /* 从第1条垂直线开始,到第3条垂直线结束(占据第1、2列) */
      grid-row: 1 / 2;     /* 从第1条水平线开始,到第2条水平线结束(占据第1行) */
    }
    
    .item-2 {
      grid-column: 2 / 4;  /* 占据第2、3列 */
      grid-row: 2 / 4;     /* 占据第2、3行 */
    }

七、总结:什么时候使用网格布局?

  • 整体页面布局:这是 Grid 最擅长的领域。定义页头、侧边栏、主内容区、页脚等大块区域。

  • 复杂的二维布局:需要元素在行和列两个方向上都保持严格对齐的布局,如图库、仪表盘、卡片网格。

  • 重叠内容:可以轻松地将多个网格项目放置到同一个网格单元格中,实现内容重叠。

二.vue Router 4

1. 什么是 Vue Router 4

Vue Router 4 是 Vue 3 的官方路由管理器,专门为 Vue 3 设计,支持 Composition API。

2. 核心特性在代码中的体现

路由创建方式

javascript 复制代码
// Vue Router 4 的创建方式
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [...]
})

历史记录模式

javascript 复制代码
// 使用 HTML5 History 模式
history: createWebHistory(import.meta.env.BASE_URL)

// 其他可选模式:
// createWebHashHistory() - 哈希模式
// createMemoryHistory() - 内存历史模式

3. 路由配置结构分析

嵌套路由 (Nested Routes)

javascript 复制代码
{
  path: '/',
  component: Layout, // 布局组件
  children: [ // 嵌套子路由
    {
      path: '', // 空路径,默认子路由
      component: Home
    },
    {
      path: 'category/:id', // 动态路由
      component: Category
    }
  ]
}

多级嵌套

javascript 复制代码
{
  path: 'member',
  component: Member,
  children: [ // 第二级嵌套
    {
      path: '',
      component: UserInfo
    },{
      path: 'order',
      component: UserOrder
    }
  ]
}

4. 路由特性详解

动态路由

javascript 复制代码
{
  path: 'detail/:id', // 动态参数
  component: Detail
}
// 访问:/detail/123 → $route.params.id = '123'

命名路由

javascript 复制代码
// 建议的改进:添加 name 属性
{
  path: 'category/:id',
  name: 'category',
  component: Category
}
// 使用时:router.push({ name: 'category', params: { id: 1 } })

滚动行为

javascript 复制代码
scrollBehavior() {
  return { top: 0 } // 路由切换时滚动到顶部
}

5. 路由模式对比

模式 优点 缺点
createWebHistory 干净的URL,SEO友好 需要服务器配置
createWebHashHistory 无需服务器配置 URL中有#,不够美观

6. 在实际项目中的使用

路由导航

javascript 复制代码
// 编程式导航
router.push('/category/1')
router.push({ path: '/detail/123' })

// 声明式导航
<router-link to="/category/1">分类</router-link>

7. 路由结构优势

  1. 清晰的层次结构:使用 Layout 作为根布局

  2. 模块化组织:不同功能模块分开管理

  3. 用户流程完整:从浏览→购物车→结算→支付→会员中心

  4. 嵌套路由合理:会员中心内嵌用户信息和订单页面

Vue Router 4 通过这些特性提供了强大而灵活的路由管理能力,让你的单页面应用具有多页面应用的用户体验。

三.pinia

1. 什么是 Pinia

Pinia 是 Vue 的官方状态管理库,替代了之前的 Vuex,专门为 Vue 3 和 Composition API 设计。

2. Store 定义分析

Store 创建方式

javascript 复制代码
export const useCartStore = defineStore('cart', () => {
  // State, Getters, Actions 都在这里定义
  return {
    // 暴露给组件使用的属性和方法
  }
}, {
  persist: true // 插件配置
})

参数说明:

  • 'cart': Store 的唯一 ID

  • 函数: 使用 Composition API 风格定义 Store

  • 配置对象: 插件配置(这里使用了持久化插件)

3. State (状态) 管理

响应式状态定义

复制代码
const cartList = ref([]) // 购物车列表状态

特点:

  • 使用 ref() 创建响应式数据

  • 状态变化会自动更新依赖的组件

  • 通过 .value 访问和修改

4. Getters (计算属性)

计算属性定义

javascript 复制代码
// 购物车总数量
const allCount = computed(() => cartList.value.reduce((a, b) => a + b.count, 0))

// 购物车总价格
const allPrice = computed(() => cartList.value.reduce((a, b) => a + b.count * b.price, 0))

// 是否全选
const isAll = computed(() => cartList.value.every((item) => item.selected))

// 选中商品数量和价格
const selectedCount = computed(() => cartList.value.filter(item => item.selected).reduce((a, b) => a + b.count, 0))
const selectedPrice = computed(() => cartList.value.filter(item => item.selected).reduce((a, b) => a + b.count * b.price, 0))

作用:

  • 基于状态派生出新数据

  • 自动缓存,依赖的状态变化时才重新计算

  • 在模板中像普通属性一样使用

5. Actions (动作)

同步 Actions

javascript 复制代码
javascript

// 清空购物车
const clearCart = () => {
  cartList.value = []
}

// 单个商品选中状态切换
const singleCheck = (skuId, selected) => {
  const item = cartList.value.find((item) => skuId === item.skuId)
  if (item) {
    item.selected = selected
  }
}

// 全选/取消全选
const allCheck = (selected) => {
  cartList.value.forEach(item => item.selected = selected)
}

异步 Actions

javascript 复制代码
javascript

// 添加商品到购物车
const addCart = async (goods) => {
  if (isLogin.value) { // 已登录 → 调用API
    await insertCartAPI(goods.skuId, goods.count)
    updateNewCartList()
  } else { // 未登录 → 本地操作
    const item = cartList.value.find((item) => goods.skuId === item.skuId)
    if (item) {
      item.count++
    } else {
      cartList.value.push(goods)
    }
  }
}

// 删除购物车商品
const delCart = async (skuId) => {
  if (isLogin.value) {
    await delCartAPI([skuId])
    updateNewCartList()
  } else {
    const idx = cartList.value.findIndex((item) => skuId === item.skuId)
    cartList.value.splice(idx, 1)
  }
}

// 更新购物车列表
const updateNewCartList = async () => {
  const res = await fineNewCartListAPI()
  cartList.value = res.result
}

Actions 特点:

  • 可以包含异步操作

  • 直接修改 state

  • 支持 async/await

  • 可以调用其他 actions

6. Store 间通信

使用其他 Store

复制代码
const userStore = useUserStore()
const isLogin = computed(() => userStore.userInfo.token)

说明:

  • 可以在一个 Store 中导入和使用其他 Store

  • 实现 Store 之间的状态依赖和通信

7. 持久化配置

复制代码
{
  persist: true // 启用持久化
}

作用:

  • 页面刷新后状态不丢失

  • 购物车数据会保存在 localStorage

  • 用户体验更好

8. 在组件中的使用方式

基本使用

javascript 复制代码
vue

<template>
  <div>
    <!-- 使用 state -->
    <div v-for="item in cartStore.cartList" :key="item.skuId">
      {{ item.name }} - {{ item.price }}
    </div>
    
    <!-- 使用 getters -->
    <div>总数量: {{ cartStore.allCount }}</div>
    <div>总价格: {{ cartStore.allPrice }}</div>
    <div>选中价格: {{ cartStore.selectedPrice }}</div>
    
    <!-- 使用 actions -->
    <button @click="cartStore.addCart(product)">加入购物车</button>
    <button @click="cartStore.delCart(skuId)">删除</button>
    <button @click="cartStore.allCheck(true)">全选</button>
  </div>
</template>

<script setup>
import { useCartStore } from '@/stores/cart'

const cartStore = useCartStore()

// 在方法中调用 actions
const handleAddCart = (product) => {
  cartStore.addCart({
    skuId: product.id,
    count: 1,
    price: product.price,
    selected: true
  })
}
</script>

结构化使用(保持响应式)

javascript 复制代码
vue

<script setup>
import { useCartStore } from '@/stores/cart'
import { storeToRefs } from 'pinia'

const cartStore = useCartStore()

// 使用 storeToRefs 保持响应式
const { cartList, allCount, allPrice, isAll } = storeToRefs(cartStore)

// Actions 直接解构
const { addCart, delCart, allCheck } = cartStore
</script>

9. 购物车 Store 设计优势

业务逻辑封装完善

javascript 复制代码
javascript

// 1. 登录状态自动处理
if (isLogin.value) {
  // 调用后端 API
} else {
  // 本地操作
}

// 2. 数据同步机制
await insertCartAPI(goods.skuId, goods.count)
updateNewCartList() // 添加后立即同步最新数据

// 3. 完整的购物车功能
- 增删改查商品
- 选中状态管理
- 价格数量计算
- 本地/云端数据同步

用户体验优化

javascript

复制代码
// 持久化:刷新页面购物车数据不丢失
persist: true

// 实时计算:价格数量自动更新
computed(() => cartList.value.reduce((a, b) => a + b.count * b.price, 0))

10. Pinia 相比 Vuex 的优势

  1. 更简单的 API: 没有 mutations,只有 state、getters、actions

  2. TypeScript 支持更好: 完整的类型推断

  3. Composition API 风格: 与 Vue 3 完美契合

  4. 模块化设计: 每个 Store 都是独立的

  5. DevTools 支持: 良好的开发调试体验

总结

购物车 Store 很好地展示了 Pinia 的核心概念:

  • State : cartList 管理购物车数据

  • Getters: 各种计算属性派生数据

  • Actions: 处理业务逻辑和异步操作

  • Store 通信: 与用户 Store 交互

  • 持久化: 数据本地保存

这样的设计让状态管理变得清晰、可维护,并且提供了良好的用户体验!

相关推荐
9***Y481 小时前
前端动画性能优化
前端
网络点点滴1 小时前
Vue3嵌套路由
前端·javascript·vue.js
牧码岛1 小时前
Web前端之Vue+Element打印时输入值没有及时更新dom的问题
前端·javascript·html·web·web前端
代码游侠1 小时前
学习笔记——数据结构学习
linux·开发语言·数据结构·笔记·学习
小二李1 小时前
第8章 Node框架实战篇 - 文件上传与管理
前端·javascript·数据库
沐知全栈开发1 小时前
XML 验证器
开发语言
HIT_Weston1 小时前
45、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 分析(二)
前端·http·gitlab
自学互联网2 小时前
使用Python构建钢铁行业生产监控系统:从理论到实践
开发语言·python
合作小小程序员小小店2 小时前
桌面开发,在线%医院管理%系统,基于vs2022,c#,winform,sql server数据
开发语言·数据库·sql·microsoft·c#