Skip to content

Vuex 的基本使用(一) ​

本页对应 Vuex 的基本使用,共 6 段视频,约 1 小时 6 分。

学习目标 ​

  • 能够定位并修复 axios 请求中的常见错误,包括解构大括号缺失、params 拼写错误、请求参数未携带以及重复 key 等问题。
  • 能够使用正则表达式去除面经简介中的 HTML 标签并渲染纯文本,同时说明不使用 v-html 的原因。
  • 能够实现面经列表“推荐/最新”筛选的类名切换、排序参数传递,并在切换时重置页码、清空列表后重新请求数据。
  • 能够解释滚动触底导致重复请求的原因,并通过 loading 状态避免自动重复加载。
  • 能够使用编程式导航以 query 或 params 两种方式传递面经 id,并在详情页正确获取该 id。
  • 能够完成 Vant 的全部导入与按需导入配置,并在项目中配置 vw 适配。

知识点 ​

为什么先学“全部导入” ​

做移动端页面时,按钮、导航、表单、弹层这些基础组件如果都自己写,既慢又容易不统一。Vant 是 Vue 生态里常用的移动端组件库,本节先学最直接的接入方式:把 Vant 的所有组件一次性注册到项目里。

为什么需要:先让组件库跑起来,确认项目能正常使用 Vant 组件,再谈体积优化。
怎么想:转写稿里提到,Vant 文档里有“快速上手”“完整导入”“自动按需导入”等说明;本节对应的是“完整导入”,也就是先把所有组件都导入。它的优点是省事,缺点是打包会变大。
怎么做:安装依赖 → 在 main.js 全量注册 → 在页面里直接写 Vant 组件标签。
易错点:不要一上来就纠结按需导入;先把全量导入跑通。但心里要清楚:全量导入只是入门方式,不是大型项目的最终优化方案。

安装 Vant 2 ​

为什么需要:项目里没有 Vant 包,就无法 import Vant。
怎么想:本节笔记明确使用 vant@latest-v2,说明这是 Vant 2 的安装方式,通常对应 Vue 2 项目。转写稿里也反复提到“安装”“引入方式”“完整导入”,所以第一步是先把依赖装进项目。
怎么做:在项目根目录执行:

bash
yarn add vant@latest-v2
// 或者 npm i vant@latest-v2

易错点:注意版本。latest-v2 是 Vant 2 系列,不要随意换成 Vant 3/4 后还按本节写法使用;另外要确认命令是在项目根目录执行,而不是随便一个文件夹。

在 main.js 中全量注册 ​

为什么需要:Vant 组件要在 Vue 模板里使用,必须先让 Vue 认识这些组件。
怎么想:全量导入的思路是:把 Vant 整个包导入进来,再通过 Vue.use(Vant) 一次性注册所有组件。这样页面里不用逐个 import 组件。
怎么做:在 main.js 中写:

js
import Vant from 'vant';
import 'vant/lib/index.css';
// 把vant中所有的组件都导入了
Vue.use(Vant)

易错点:第一,CSS 不要漏,import 'vant/lib/index.css'; 不引入可能导致组件样式不完整;第二,Vue.use(Vant) 要放在创建 Vue 实例之前;第三,Vue 2 项目才按本节这种 Vue.use 写法理解,不要和 Vue 3 的 app.use 混用。

在组件里使用按钮 ​

为什么需要:注册完成后,要验证组件库是否真的可用。
怎么想:Vant 组件在模板里通常写成 van- 开头的短横线标签,比如按钮就是 van-button。
怎么做:在页面模板中直接使用:

jsx
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>

效果可参考下图:

Vant 按钮示例

易错点:组件标签不要写成 VantButton 或 Button;type 是组件属性,不是随便的 class;如果页面没有样式,优先检查 main.js 里 CSS 是否引入、Vue.use(Vant) 是否执行。

全量导入的代价与后续优化 ​

为什么需要:全量导入虽然方便,但会把 Vant 很多当前页面没用到的组件也带进项目。
怎么想:本节笔记最后明确提醒:“vant-ui提供了很多的组件,全部导入,会导致项目打包变得很大。”转写稿里也提到 Vant 文档中有“完整导入”和“自动按需导入”两种方式。因此学习路径应是:先全量跑通,再按需优化。
怎么做:当前小节先保持全量导入;等页面稳定后,再参考 Vant 文档改为按需引入或自动按需导入。
易错点:不要误以为全量导入“有问题不能用”,它适合入门和快速验证;但正式项目要关注打包体积。也不要自己编造优化步骤,后续优化应回到 Vant 官方文档的“自动按需导入”说明。

先明确:为什么要做按需导入 ​

转写稿里提到,vant 的使用要回到文档看“快速上手”,文档里会涉及“完整导入使用”和“自动按需导入使用”等方式。本节笔记选择的是按需导入。
为什么需要:如果完整引入 vant,项目会把大量未使用组件也打包进来,体积变大。按需导入的目标是“用到哪个组件,才引入哪个组件”。
怎么想:先安装 vant,再借助 babel-plugin-import 让 Babel 在编译时把 import { Button } from 'vant' 转成按需引入,并自动带上对应样式。
怎么做:按下面步骤安装、配置、注册、测试,最后把组件注册抽离成独立文件。
易错点:Vue2 项目要用 vant@latest-v2,不要误装 Vue3 版本;按需导入不是“只写标签不注册”,组件仍要 Vue.use。

安装 vant-ui ​

为什么需要:项目里要使用 van-button、van-icon 等组件,必须先有 vant 依赖。
怎么想:本节是 Vue2 项目,所以笔记指定 vant@latest-v2。
怎么做:

npm i vant@latest-v2  或  yarn add vant@latest-v2

易错点:命令里的 latest-v2 不要漏;如果团队用 yarn,就统一用 yarn,避免锁文件混乱。

安装 babel-plugin-import ​

为什么需要:只安装 vant 还不够。我们希望写 import { Button, Icon } from 'vant' 时,Babel 能自动改成按需加载,而不是把整个库打进去。
怎么想:这个插件是开发依赖,只在构建/编译阶段工作,所以加 -D。
怎么做:

jsd
npm i babel-plugin-import -D

易错点:不要装成生产依赖;装完后要配置 babel.config.js,否则插件不会生效。

配置 babel.config.js ​

为什么需要:告诉 babel-plugin-import:库名是 vant,从 es 目录取模块,并且自动引入样式。
怎么想:libraryName: 'vant' 指定目标库;libraryDirectory: 'es' 指定模块目录;style: true 表示样式也按需处理。
怎么做:

js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
}

易错点:plugins 要放在 module.exports 同级配置里,不要塞进 presets;改完 Babel 配置后要重启开发服务;style: true 不要写成字符串 'true'。

在 main.js 中按需加载并注册 ​

为什么需要:Babel 负责“按需引入”,但组件要在 Vue 里能用,还得注册。
怎么想:只引入当前要用的 Button、Icon,然后 Vue.use 注册。
怎么做:

js
import { Button, Icon } from 'vant'

Vue.use(Button)
Vue.use(Icon)

易错点:组件名要和标签对应;如果页面用了 van-button 却没注册 Button,会提示组件未注册;不要一边按需引入一边又完整 import Vant from 'vant'。

在 app.vue 中做最小验证 ​

为什么需要:配置是否成功,最直接的方式是渲染几个按钮看样式和功能是否正常。
怎么想:用不同 type 的按钮覆盖主要样式,能同时验证组件注册和样式引入。
怎么做:

js
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="default">默认按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>

易错点:如果按钮出现但没样式,优先检查 style: true 和 Babel 配置;如果标签不渲染,检查 Vue.use(Button);改配置后记得重启。

把组件注册抽离到 utils/vant-ui.js ​

为什么需要:项目变大后,main.js 里会堆很多 Vue.use。抽离后入口文件更干净,组件注册集中管理。
怎么想:新建 utils/vant-ui.js,把按需引入和注册放进去;main.js 只负责导入这个文件。
怎么做:

js
import { Button, Icon } from 'vant'

Vue.use(Button)
Vue.use(Icon)

main.js 中导入:

js
// 导入按需导入的配置文件
import '@/utils/vant-ui'

易错点:@ 是 Vue CLI 默认的 src 别名,路径要写对;这个文件只要被执行到就会完成注册,所以 main.js 中导入即可;后续新增组件时,统一在 utils/vant-ui.js 里补引入和 Vue.use,不要到处散落注册代码。

为什么需要做 vw 适配 ​

移动端项目要面对不同宽度的手机屏幕。设计稿通常只有一个固定宽度,如果直接写 px,在小屏上可能显得过大,在大屏上又显得过小。vw 适配的思路是:把设计稿里的 px 按视口宽度换算成 vw,让页面元素随屏幕宽度等比缩放。

转写稿里提到,vant 文档的进阶用法中有“浏览器适配”,其中包含 VW 适配、REM 适配等说明;本节项目选择的是 VW 适配。遇到不确定的配置,先回官方说明核对:

官方说明:https://vant-contrib.gitee.io/vant/v2/#/zh-CN/advanced-usage

怎么想: 先确认两件事——UI 组件库按多宽的设计稿设计、项目自己的设计稿按多宽设计。两者基准一致时,viewportWidth 才好填。

怎么做: 用 PostCSS 插件 postcss-px-to-viewport,在构建时把样式里的 px 转成 vw。

易错点: 不要把 viewportWidth 当成“屏幕宽度”随便写;它对应的是设计稿视口宽度。配置不一致时,页面会整体偏大或偏小。

先确认基准:vant 和项目设计稿都是 375 ​

笔记明确写了:viewportWidth 是设计稿的视口宽度。vant-ui 中的组件就是按照 375 的视口宽度设计的;恰好面经项目中的设计稿也是按照 375 的视口宽度设计的,所以此时只需要配置 375 即可。

为什么需要: 如果 UI 组件库按 375 设计,而项目配置成别的基准,组件和业务样式就会不在同一缩放体系里。

怎么想: 转写稿里也提到 vant 的安装、引入方式、完整导入、自动按需导入等内容,说明项目里会大量使用 vant 组件;因此配置要优先和 vant 的 375 基准对齐。

怎么做: 本项目直接配置:

js
// postcss.config.js
module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375,
    },
  },
};

易错点: 不要看到别的项目写 750 就照抄。先看设计稿和组件库基准,再决定 viewportWidth。

安装 postcss-px-to-viewport ​

为什么需要: 只写配置文件不够,项目里必须先有对应的 PostCSS 插件依赖。

怎么想: 笔记指定了版本 @1.1.1,按笔记命令安装,避免版本差异带来配置行为变化。

怎么做:

js
yarn add postcss-px-to-viewport@1.1.1 -D

易错点: 这是开发依赖,命令里带 -D;不要装成生产依赖。插件名和版本号都要核对,别漏写 postcss- 前缀。

在项目根目录新建 postcss.config.js ​

为什么需要: PostCSS 需要读取配置文件,才能知道要把 px 转成 vw,以及按多宽的设计稿换算。

怎么想: 笔记要求“项目根目录,新建 postcss 的配置文件 postcss.config.js”。配置文件放错位置,构建工具可能读不到。

怎么做: 在根目录创建 postcss.config.js,写入上面的 module.exports 配置。plugins 里注册 'postcss-px-to-viewport',并设置 viewportWidth: 375。

易错点: 文件名不要写成 postcss.config.ts 或随便放到 src 下;plugins 是对象写法,键名是插件名,不要多写空格或拼错。保存配置后,样式中的 px 会由 PostCSS 在构建时转换。

viewportWidth 填 375 还是 750 ​

笔记给出的结论是:本项目设计稿是 375,vant 组件也按 375 设计,所以填 375。如果设计稿不是 375 而是 750,笔记留了一个问题:

那此时这个值该怎么填呢?

为什么需要: viewportWidth 决定换算比例,填错会导致整个页面缩放比例不对。

怎么想: 配置值要跟“设计稿视口宽度”对应;本项目已经确认是 375,所以不要改成 750。若换成 750 设计稿,应按该设计稿基准处理,并注意 vant 组件基准是否仍是 375,避免混用后尺寸不一致。

怎么做: 本项目保持:

js
viewportWidth: 375,

易错点: 不要因为看到 750 设计稿的教程就直接改配置;也不要同时混用多套适配方案。先确认设计稿、组件库基准,再决定配置值。

课件图示 ​

课件第11页:vant 全部导入 和 按需导入 目标:明确 全部导入 和 按需导入 的区别 v

课件第12页:目标:阅读文档,掌握 全部导入 的基本使用 官网:vant-ui 全部导入: ①

课件第13页:目标:阅读文档,掌握 按需导入 的基本使用 按需导入: ① 安装 vant-ui

课件第3页:项目收获 目标:明确做完本项目,能够收获哪些内容 脚手架自定义项目构建 组件库v

课件第2页:项目演示 目标:查看项目效果,明确功能模块 登录 注册 首页 面经详情 面经 收

课件第4页:创建项目 目标:基于 VueCli 自定义创建项目架子 安装脚手架 (√) 创建

课件第14页:目标:基于 postcss 插件 实现项目 vw 适配 官方配置 ① 安装插件

课件第15页:目标:分析项目页面,设计路由,配置一级路由 路由设计配置 登录 注册 首页 面经

代码示例 ​

1. Vant 按需导入 + vw 适配(配置类文件,放在 Vue CLI 项目根目录) ​

js
// ① babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant']
  ]
}
js
// ② postcss.config.js
module.exports = {
  plugins: {
    'postcss-px-to-viewport': {
      viewportWidth: 375,
    },
  },
};
js
// ③ src/utils/vant-ui.js
import Vue from 'vue'
import { Button, Icon } from 'vant'

Vue.use(Button)
Vue.use(Icon)
js
// ④ src/main.js
import Vue from 'vue'
import App from './App.vue'
// 导入按需导入的配置文件
import '@/utils/vant-ui'

new Vue({
  render: h => h(App)
}).$mount('#app')
vue
<!-- ⑤ src/App.vue -->
<template>
  <div id="app">
    <van-button type="primary">主要按钮</van-button>
    <van-button type="info">信息按钮</van-button>
    <van-button type="default">默认按钮</van-button>
    <van-button type="warning">警告按钮</van-button>
    <van-button type="danger">危险按钮</van-button>
  </div>
</template>

要点与易错点

  • 全部导入只写 Vue.use(Vant) 最省事,但会把所有组件打进包里,项目体积变大,正式项目一律用按需导入。
  • 按需导入必须装 babel-plugin-import -D,并在 babel.config.js 的 plugins 里配置 libraryName / libraryDirectory: 'es' / style: true,少写 style: true 样式就不生效。
  • postcss.config.js 必须放在项目根目录,viewportWidth 填设计稿宽度(Vant 组件按 375 设计,本项目设计稿也是 375,所以填 375);设计稿是 750 时要换算。
  • 改完 babel.config.js / postcss.config.js 一定要重启项目,热更新不会读取新配置。
  • 把 Vue.use(...) 抽到 utils/vant-ui.js 后,main.js 只需 import '@/utils/vant-ui',后续新增组件只改这一个文件。

2. 面经列表:去 HTML 标签 + 推荐/最新切换 + 获取数据 ​

js
// src/utils/request.js
import axios from 'axios'

// 相当于克隆一份 axios,起名 request,以后都把它当 axios 用
const request = axios.create({
  baseURL: '接口基地址,以接口文档为准'
})

export default request
js
// src/api/article.js
import request from '@/utils/request'

// params: { current 页码, sorter 排序字段 }  地址以接口文档为准
export function getArticles(params) {
  return request({
    url: '/interview/query',
    params
  })
}
vue
<!-- src/views/article/index.vue -->
<template>
  <div class="article-list">
    <!-- 排序:推荐 / 最新 -->
    <div class="sorter">
      <span
        :class="{ active: sorter === 'weight_DESC' }"
        @click="changeSorter('weight_DESC')"
      >推荐</span>
      <span
        :class="{ active: sorter === null }"
        @click="changeSorter(null)"
      >最新</span>
    </div>

    <!-- 列表 -->
    <div
      class="item"
      v-for="item in list"
      :key="item.id"
      @click="goDetail(item.id)"
    >
      <div class="title">{{ item.stem }}</div>
      <div class="content">{{ delHtmlTag(item.content) }}</div>
    </div>
  </div>
</template>

<script>
import { getArticles } from '@/api/article'

export default {
  name: 'ArticleList',
  data() {
    return {
      list: [],
      page: 1,
      sorter: 'weight_DESC', // 控制推荐/最新,同时作为接口排序字段
      loading: false
    }
  },
  created() {
    this.onLoad()
  },
  methods: {
    // 去掉内容里的 html 标签
    delHtmlTag(str) {
      return str.replace(/<[^>]+>/g, '')
    },
    // 获取面经列表数据
    async onLoad() {
      const res = await getArticles({
        current: this.page,
        sorter: this.sorter
      })
      this.list.push(...res.data.rows)
    },
    // 切换 推荐 / 最新
    changeSorter(sorter) {
      this.sorter = sorter
      this.page = 1        // 重置页码
      this.list = []       // 重置数组
      this.loading = true  // 避免滚动条自动触发 onLoad
      this.onLoad()        // 手动调一次
    },
    goDetail(id) {
      this.$router.push(`/detail?id=${id}`)
    }
  }
}
</script>

<style scoped>
.sorter span { margin-right: 20px; color: #999; }
.sorter span.active { color: #000; border-bottom: 2px solid #000; }
.item { padding: 12px 0; border-bottom: 1px solid #eee; }
.title { font-size: 16px; font-weight: bold; }
.content { font-size: 14px; color: #666; }
</style>

要点与易错点

  • replace(/<[^>]+>/g, '') 的 g 不能丢,否则只替换第一个标签;这里是把标签替换成空串,而不是渲染标签。
  • 不要用 v-html 代替:它会把内容里的 <h1>、<h2> 解析出来,导致简介的标题比页面标题还大,排版乱掉,而且 v-html 会覆盖元素内部原有内容。
  • :key 用 item.id,如果列表被重复 push 出现重复 key,控制台会报重复 key 的错误——本质是同一个 id 被渲染了两次。
  • 切换排序时三件事缺一不可:page = 1、list = []、loading = true。少了 list = [] 数据会越拼越多;少了 loading = true,滚动条在底部时会自动再触发一次 onLoad,加上手动调用就发了两次请求,页码还是第一页,于是出现重复 key。
  • 请求方法里的 sorter 只做「值」传参,params 这个键名是接口规定的,写错(比如写成 parmas)参数就带不上,后端返回的永远是默认排序。
  • 形参名可以随便起,但传进 request({ params }) 里的键名不能改。

3. 面经详情:列表跳转传 id,详情页接收 id ​

js
// src/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Detail from '@/views/detail/index.vue'

Vue.use(VueRouter)

const routes = [
  // 方案一:query 传参,路由规则不需要改动
  { path: '/detail', component: Detail }

  // 方案二:params 传参,路由规则必须加 /:id
  // { path: '/detail/:id', component: Detail }
]
vue
<!-- 列表项:点击跳转(两种写法任选其一) -->
<script>
export default {
  methods: {
    // 方案一:query 写法,地址栏是 /detail?id=4156
    goDetail(id) {
      this.$router.push(`/detail?id=${id}`)
    }
    // 方案二:params 写法,地址栏是 /detail/4156
    // goDetail(id) {
    //   this.$router.push(`/detail/${id}`)
    // }
  }
}
</script>
vue
<!-- src/views/detail/index.vue -->
<template>
  <div class="detail">
    <h3>面经详情</h3>
    <p>当前文章 id:{{ id }}</p>
  </div>
</template>

<script>
export default {
  name: 'ArticleDetail',
  data() {
    return {
      id: ''
    }
  },
  created() {
    // 方案一:配合 /detail?id=xxx 使用
    this.id = this.$route.query.id

    // 方案二:配合 /detail/:id 使用
    // this.id = this.$route.params.id
  }
}
</script>

要点与易错点

  • 跳转用 this.$router(push/replace),取参用 this.$route(query/params),两个名字差一个 r,写错就报错。
  • query 写法路由规则不用动,取参用 $route.query.id;params 写法必须在路由里写 path: '/detail/:id',取参用 $route.params.id,规则不加 :id 就拿不到值。
  • 模板字符串的反引号和 ${} 不能漏,写成 '/detail?id=' + id 也行,但 '/detail?id=id' 就变成字符串 id 了。
  • 路由里 :id 后面加 ?(/detail/:id?)表示该参数可选,不加则表示必传。
  • 详情页只有拿到 id,才能拿它去请求这一篇面经的详情数据,所以「传 id」这一步是整个详情页的前提。

常见错误 ​

1. 上线后包体积异常、首屏加载慢

  • 现象:dist 体积比预期大很多,未使用的组件和样式也被打进包里。
  • 原因:Vue.use(Vant) + import 'vant/lib/index.css' 全量注册,Vant 所有组件及其样式都进入打包产物。
  • 修法:改按需导入——安装 babel-plugin-import,在 babel.config.js 的 plugins 中配置 libraryName: 'vant'、libraryDirectory: 'es'、style: true,main.js 只注册实际用到的组件,并把注册代码抽到 utils/vant-ui.js 统一维护。

2. 按需导入后组件没样式 / 配置"看起来没生效"

  • 现象:组件结构渲染出来了,但完全没有样式,或者改动 babel.config.js 后行为没变化。
  • 原因:style 没设成 true;插件配置写在了 presets 里而不是 plugins 里;或改完配置没重启 dev server,缓存里还是旧编译结果。
  • 修法:确认 style: true、配置在 plugins 数组内且带 'vant' 这一项;改完配置重启服务,必要时清 node_modules/.cache。

3. ESLint 与格式化插件"打架",保存即报错

  • 现象:手动改好的格式,一保存又被改回去;或格式化后立刻出现一堆 ESLint 报错(分号、引号、空行、import 顺序)。
  • 原因:ESLint 只校验代码风格规范,与格式化器的默认风格不一致,两边规则冲突时必然有一方被覆盖。
  • 修法:右键 →「格式化文档」→「配置默认格式化程序」,选一个与项目规范一致的插件;仍有个别规则冲突时,让其中一方让步——改 .eslintrc 关掉该规则,或调整格式化器配置,关键是把让步结果固化进配置文件,而不是每次手动改。

4. 请求参数"传了但没带上",列表永远停在第一页

  • 现象:滚动加载或切换筛选时,Network 里请求 URL 上看不到预期参数,返回的数据始终是同一批。
  • 原因:axios 配置对象里参数键名拼写错误(如把 params 写成 parom);或组件调用时传了实参,但 API 方法的形参没有透传到 params 上。
  • 修法:配置对象的键名必须严格是 params(POST body 是 data);形参叫什么无所谓,但必须真正被放进 params 再发出去。排查时先看 Network 的请求参数,再看 API 方法体。

5. 控制台满屏 Duplicate keys detected

  • 现象:列表页红字刷屏,渲染结果错乱;Network 中同一页数据被请求了两次。
  • 原因:切换筛选或滚动触底时,把同一页数据重复 push 进已有数组,导致 :key 绑定的 id 重复。
  • 修法:切换条件时做"重置三件套"——list = []、current = 1、loading = true(阻止滚动条处于底部时自动再触发一次 onLoad),然后手动调用一次加载方法。

6. 详情页取不到 id(undefined)

  • 现象:跳转成功但详情页拿不到参数,请求发出去是空 id。
  • 原因:跳转写法与路由规则不匹配——用 ?id= 传参却按 params 取,或用了 /detail/:id 却没在路由规则里加 :id;以及 $router(跳转)与 $route(取参)混用。
  • 修法:两种方式成对使用——?id=xx 配 this.$route.query.id;/detail/:id 配路由规则加 :id 并取 this.$route.params.id。跳转一律 this.$router.push,取参一律 this.$route。

7. 简介区域出现比标题还大的字

  • 现象:列表里某条简介渲染出巨大的 H1/H2,排版完全乱掉。
  • 原因:用 v-html 解析了后端返回的富文本,标签被真实渲染;且 v-html 会覆盖元素内原有内容。
  • 修法:用正则 replace 去掉标签后以普通文本插值渲染,简介场景只需要纯文本。

练习 ​

  1. 有一个只用到了 Button 和 Toast 的 Vue2 项目,目前是全量导入。请列出需要改动/新增的文件清单,并说明每个文件改动的关键点与验证方式(如何确认未使用组件没被打进包里)。

  2. 面经列表从「推荐」切到「最新」后,出现数据翻倍 + Duplicate keys 报错。请写出你的排查顺序(从哪一层看起、看什么证据),以及完整的修复清单。

  3. 设计稿宽度是 750,团队里有人直接照抄了 viewportWidth: 375 的配置。请说明会出现什么现象、正确的配法是什么、以及写业务样式时是否需要跟着改。

  4. 用两种路由传参方式各实现一次"点列表项进详情页",分别写出跳转代码、路由规则、取参代码,并说明什么情况下必须用动态路由(/detail/:id)。

  5. 团队新人的 ESLint 与格式化插件持续冲突,每次保存都要手动回改。请给出两种解决方向,并说明各自的代价和适用场景。

原视频对照 ​

#视频时长
1反馈和回顾19:16
2axios请求方面的错误分享09:24
3面经列表去除html标签07:12
4面经列表-筛选-切换类名08:34
5面经列表-筛选-获取数据10:31
6详情-传递id12:00

小结 ​

  • 引入方式直接决定产物体积:开发期全量导入图快,交付前必须收敛到按需导入,这是流程问题而不只是配置问题。
  • 按需导入是三处联动(插件依赖 → babel 配置 → 注册入口),任何一处缺失的表现都是"没生效"或"没样式",排查时按这三处顺序过一遍最快。
  • ESLint 只负责代码风格,不负责逻辑正确性;它与格式化器的冲突永远靠"一方让步 + 写进配置文件"解决,靠手动改是不可维护的。
  • axios 封装的价值在统一拦截器,但参数最终要落到约定的键名(url / params / data)上——这类拼写错误在语法层完全静默,只能靠看 Network 请求来定位。
  • 分页 + 筛选组合场景有通用解法:切换条件时同时重置页码、清空数组、置 loading 拦截自动请求,然后手动拉一次数据。
  • 路由传参的 query 与 params 必须和路由规则成对设计,$router 负责跳转、$route 负责取参,混用是取不到值的头号原因。
  • 移动端适配是构建期一次性配置,业务代码按设计稿 1:1 写 px 即可,适配出问题先查配置文件位置和 viewportWidth,而不是改样式。
  • 值得把高频报错整理成个人清单(如 Duplicate keys、xxx is not a function 这类往往只有两三个固定成因),排错速度的提升主要来自这种经验沉淀。