主题
面经 H5 端:Vant 与项目搭建(二)
本页对应 面经 H5 端:Vant 与项目搭建,共 7 段视频,约 1 小时 14 分。
学习目标
- 能够完成 Vant 组件库的安装与导入配置,区分完整导入和自动按需导入两种方式,并检查
package.json与构建配置,确保两种方式不混用。 - 能够使用 ESLint 代码规范检查与自动修复插件修正格式问题,并说明 ESLint 检查与代码格式化插件的区别。
- 能够为移动端项目完成 VW 适配:安装插件、创建适配配置文件、修改配置后重启服务,并通过浏览器检查元素宽度是否转换为
vw单位。 - 能够搭建一级与二级路由结构,在
App.vue和Home.vue中分别配置路由出口,并实现访问根路径重定向到面经列表页。 - 能够使用 Vant Tabbar 组件在主页底部实现 4 个可跳转标签,开启路由模式、配置
to属性并替换内置图标。 - 能够分别在 Vue 组件和 JS 文件中调用 Toast 轻提示,并完成登录/注册页的标题、表单、超链接三区域布局及基础交互数据准备。
知识点
为什么需要代码规范
代码规范是一套写代码的约定规则,例如赋值符号左右是否要空格、一句结束是否要加分号。转写稿里把“ESLint”口误成“ESB/ES令”,这里统一纠正为 ESLint。ESLint 是一个代码检查工具,用来检查代码是否符合指定规则;团队可以自行约定一套规则。创建项目时,我们使用的是 JavaScript Standard Style 代码风格。
为什么需要:没有规矩不成方圆。一个团队里有人用单引号、有人用双引号,有人加分号、有人不加,代码合并和阅读都会增加冲突与成本。
怎么想:规范不是为了刁难人,而是让团队风格统一;ESLint 报错是在帮助我们发现格式问题。
怎么做:先知道项目采用哪套规则,再在写代码时按规则写;遇到报错就查规则。
易错点:ESLint 主要检查代码格式,不是替你检查业务逻辑写没写对;不要一看到报错就烦,心态要好,有错就改。
JavaScript Standard Style 规范要点
建议把 https://standardjs.com/rules-zhcn.html 看一遍,然后在写的时候遇到错误就查询解决。下面是这份规则中的一小部分:
- 字符串使用单引号 – 需要转义的地方除外
- 无分号 – 这没什么不好。不骗你!
- 关键字后加空格
if (condition) { ... } - 函数名后加空格
function name (arg) { ... } - 坚持使用全等
===摒弃==一但在需要检查null || undefined时可以使用obj == null - ......
为什么需要:这些规则决定了代码“长什么样”,也是 ESLint 判断对错的依据。
怎么想:不需要一次背完所有规则,先记住项目常用规则;遇到不认识的报错再查。
怎么做:写代码时按 Standard 风格写,例如字符串优先单引号、不加分号、关键字和函数名后留空格、比较用 ===。
易错点:obj == null 是规则里允许的例外场景,不要机械地把所有 == 都改掉;规则细节以规则页为准。
制造一次规范错误并观察
为了确认 ESLint 是否在工作,可以在 main.js 中随意做一些改动:添加一些空行、空格。
js
import Vue from 'vue'
import App from './App.vue'
import './styles/index.less'
import router from './router'
Vue.config.productionTip = false
new Vue ( {
render: h => h(App),
router
}).$mount('#app')按下保存代码之后,你将会在控制台中看到如下错误:

eslint 是来帮助你的。心态要好,有错,就改。
为什么需要:只看规则不容易建立感觉,故意改出格式问题,能直观看到 ESLint 如何提示。
怎么想:保存后出现错误,说明 ESLint 已经接入项目并在检查代码;错误不是“代码坏了”,而是“格式不符合约定”。
怎么做:在 main.js 中加入多余空行、空格,保存后看控制台输出。
易错点:不要以为控制台报错一定是业务逻辑错误;这里的错误来自格式规则。也不要为了消错直接关规则。
根据错误代码手动修复
根据错误提示来一项一项手动修正。如果你不认识命令行中的语法报错是什么意思,可以根据错误代码(func-call-spacing、space-in-parens 等)去 ESLint 规则列表中查找其具体含义。打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

为什么需要:错误代码就是规则名,查规则表才能知道它到底要求什么。
怎么想:先看错误代码,再查规则含义,最后回到代码定位要改的位置;不要凭感觉乱改。
怎么做:逐条读控制台错误,把 func-call-spacing、space-in-parens 等代码复制到规则表搜索,理解后手动修正。
易错点:不要只改一处就以为全部完成;要按提示逐项修。也不要把“查规则”变成“随手关规则”。
把 ESLint 和格式化工具分开看
转写稿回顾里强调:ESLint 负责检查代码格式并报错;格式化插件负责调整代码格式,二者职责不一样。为了顺利开发,可以配合编辑器保存时的格式化能力,把格式调成符合项目要求;但 ESLint 仍然负责“报不报错”。
为什么需要:很多人把“格式化”和“代码检查”混在一起,结果不知道为什么保存后还有报错。
怎么想:格式化工具帮你把结构调整齐,ESLint 按规则检查是否合格;一个偏自动调整,一个偏检查提示。
怎么做:保存时让格式化工具整理格式,再根据 ESLint 提示手动修复剩余问题。
易错点:不要以为装了格式化插件就等于 ESLint 不会报错;也不要随意改团队规则来掩盖问题。修复后再次保存,确认控制台错误消失,才算完成这一轮手动修复。
先理解:ESLint 插件解决什么问题
为什么需要:团队开发时,单引号还是双引号、缩进几格、要不要分号,这些格式问题如果全靠人盯,很容易漏;代码里出现不符合规则的写法时,也需要编辑器及时提示。本节要解决的就是:让 ESLint 自动高亮错误,并在保存时自动修正能修的部分。
怎么想:ESLint 负责按规则检查代码,VSCode 的 ESLint 插件负责把检查结果带进编辑器。装好插件、配好保存动作后,按 Ctrl+S 保存,ESLint 就会尝试修复。转写稿上午回顾里说的“ESLint 管报不报错”“格式化插件调代码格式”,要区分开:本节重点是让 ESLint 提示并自动修复格式问题,不是让它替你写业务逻辑。
怎么做:先安装 ESLint 插件,再改 VSCode 的 settings.json,让保存时执行 source.fixAll,同时关闭保存自动格式化。
易错点:不要把 ESLint 和 Beautify 等格式化工具混着用;不要以为装了插件就万事大吉,项目打开方式、配置文件位置都会影响生效。
安装 ESLint 插件
为什么需要:没有插件,ESLint 的检查结果不能稳定地在 VSCode 里高亮显示,也不能方便地触发保存修复。
怎么想:先装插件,让编辑器具备“显示 ESLint 错误 + 执行修复”的能力;规则本身仍由项目里的 ESLint 配置决定。
怎么做:在 VSCode 扩展市场安装 ESLint 插件,安装示意如下:

易错点:插件装完不代表项目一定生效。后面还要检查 ESLint 配置文件是否在项目根目录、项目是否以根目录打开。转写稿里反复强调“别安装错位置”“看项目根目录”,这里同样适用:插件是编辑器级,配置是项目级,两者要配合。
配置保存时自动修复
为什么需要:只高亮错误还不够,手工一个个改很费时间;保存时自动修复能把大量格式问题顺手处理掉。
怎么想:把“保存”这个动作和 ESLint 的修复能力绑在一起。保存时执行 source.fixAll,同时关闭 editor.formatOnSave,避免 VSCode 自带格式化先动手,导致和 ESLint 规则打架。
怎么做:在 VSCode 的 settings.json 中加入:
js
// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {
"source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false易错点:editor.formatOnSave 不要留成 true;如果同时启用了 Beautify 等格式化工具,可能出现“刚修好又被格式化回去”的冲突。转写稿回顾时说“有好多错,按保存好了”,说明生效后的直观表现是:保存后错误提示减少,缩进、引号等被调整。
settings.json 参考与配置位置
为什么需要:实际项目里 VSCode 设置不止这一项,给一份完整参考,便于对照自己是否写错层级、漏逗号。
怎么想:这些配置放在 VSCode 用户设置或工作区设置的 settings.json 中;本节笔记给出的参考如下,保留原代码便于对照。
怎么做:
jsx
{
"window.zoomLevel": 2,
"workbench.iconTheme": "vscode-icons",
"editor.tabSize": 2,
"emmet.triggerExpansionOnTab": true,
// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {
"source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false
}易错点:JSON 里少逗号、多逗号都会导致设置不生效;editor.codeActionsOnSave 是对象,不要把 source.fixAll 写到外层。改完设置后,重新打开或保存文件观察效果。
根目录、项目打开方式与格式化工具冲突
为什么需要:ESLint 插件要靠项目里的 ESLint 配置工作;如果打开位置不对,它可能找不到配置,表现为“装了插件但不高亮/不修复”。
怎么想:ESLint 配置文件必须在项目根目录;VSCode 也要以项目根目录打开,并且一次打开一个项目,避免多项目混在一起导致配置串台。
怎么做:确认项目根目录下有 ESLint 配置文件;用 VSCode 打开这个根目录;不要在一个窗口里同时开多个不相干项目。使用了 ESLint 校验后,把 VSCode 自带的那些格式化工具禁用,尤其是 Beautify。
易错点:常见错误是“打开的是父文件夹”或“一次开好几个项目”,导致插件找不到当前项目的 ESLint 配置;另一个错误是 ESLint 和 Beautify 同时启用,保存后格式来回变。调试时按顺序查:插件是否启用 → 是否根目录打开 → ESLint 配置是否在根目录 → 是否被其他格式化工具抢占 → 再按 Ctrl+S 看错误是否被修复。
本节目标与调整原则
为什么需要:脚手架初始化出来的项目带着演示用的 logo、HelloWorld 组件和 Home/About 页面,这些文件适合“能跑起来”,但不符合企业项目规范。后面要接接口、写页面、拆工具方法,如果还保留默认演示结构,路由表和组件引用会越来越乱。
怎么想:这一节不是“重写项目”,而是做三件事:删掉默认演示文件;把还被入口引用的文件改成干净版本;提前建好分层目录。顺序上要先删、再改、后新增,避免改完路由又忘了删引用。
怎么做:严格按笔记步骤执行。转写稿里反复强调“路由配置要写在 router/index.js,位置不能放错”;另外常说的“慢点DS”就是 main.js,本节明确 main.js 不需要修改。
易错点:不要一边删文件一边全局乱改;删完后要检查是否还有 import 指向已删文件。初始化阶段路由表清空后页面没有内容,是预期结果,不要误判成项目坏了。
先删除默认演示文件
为什么需要:logo.png、HelloWorld.vue、AboutView.vue、HomeView.vue 都是脚手架演示资源。后面我们会有自己的页面和组件,留着它们只会造成引用残留和命名干扰。
怎么想:删除前先明确它们是否还被 App.vue、router/index.js 引用。删除不是目的,清理默认演示依赖才是目的。
怎么做:删除以下文件:
src/assets/logo.pngsrc/components/HelloWorld.vuesrc/views/AboutView.vuesrc/views/HomeView.vue
易错点:删完文件后如果终端报“找不到模块”,优先检查 router/index.js 是否还导入 HomeView、AboutView,以及 App.vue 是否还导入 HelloWorld。不要只删文件不删引用。
修改 router/index.js:清空默认路由
为什么需要:默认路由表指向 HomeView 和 AboutView,这两个文件已经被删除。如果路由表还保留它们,项目启动或编译时就会找不到模块。
怎么想:路由表是“地址 → 组件”的映射。初始化阶段还没有正式页面,先把默认路由配置清空,只保留 VueRouter 的安装和导出,后面再按页面逐个补规则。
怎么做:把 router/index.js 改成:
js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
routes
})
export default router易错点:routes 可以保留为空数组,但不要留下默认的 import HomeView...、import AboutView...。转写稿中强调路由配置位置不能放错,这里就应写在 router/index.js,不要写到 main.js 或组件里。
修改 App.vue:只保留一级路由出口
为什么需要:App.vue 是根组件。默认模板里常带 logo 和 HelloWorld,这些演示内容删除后,根组件应只负责承载路由出口,让页面由路由系统渲染。
怎么想:根组件不写具体业务页面,只保留 <router-view/>。这样登录、注册、主页等一级页面才有地方显示。
怎么做:把 App.vue 改成:
html
<template>
<div id="app">
<router-view/>
</div>
</template>易错点:router-view 不要拼错;不要继续保留 HelloWorld 的引入和注册;笔记只要求改模板,不要额外编造样式或脚本。若页面空白,先看路由表是否为空、地址是否匹配。
新增 api 与 utils 目录
为什么需要:后面会发 ajax 请求,也会封装自己的工具方法。如果都写在组件里,组件会又长又难维护,接口地址和工具函数也无法复用。
怎么想:按职责分层。api 专门放接口模块,也就是发送 ajax 请求接口的模块;utils 放自己封装的方法,例如后续可复用的工具函数。
怎么做:在 src 下新增两个目录:
src/api:存储接口模块src/utils:存储一些工具模块
易错点:目录名保持小写,不要和 views、components 混用;不要一开始就把所有请求和工具都塞进 main.js。目录先建好,后续按模块补文件。
调整后的目录效果与自检
调整完成后,目录效果应如下:

为什么需要自检:这一节改动的是项目骨架,骨架错了后面每个页面都会受影响。转写稿里调试路由时也强调:页面空白先看地址和路由规则是否匹配,而不是盲目改代码。
怎么想:按清单核对:默认演示文件是否删净;router/index.js 是否没有默认路由导入;App.vue 是否只剩路由出口;src/api、src/utils 是否已建好;main.js 是否保持原样。
怎么做:启动项目观察是否还有“找不到模块”的报错。若访问根地址没有内容,在路由表为空的情况下属于正常现象,后续配置路由后再验证页面。
易错点:不要忘记 main.js 不需要修改;不要为了“看起来有内容”又临时把默认页面加回来。初始化目录结构的目标是干净、可扩展,而不是保留演示效果。
课件图示








代码示例
示例一:项目骨架(main.js + router/index.js + App.vue)
src/main.js(Vant 完整导入方式)
js
import Vue from 'vue'
import App from './App.vue'
import './styles/index.less'
import router from './router'
// 完整导入 Vant:组件 + 样式 + 注册
import Vant from 'vant'
import 'vant/lib/index.css'
Vue.use(Vant)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router
}).$mount('#app')src/router/index.js
js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
// 一级路由:直接渲染在 App.vue 的 router-view 中
{ path: '/login', component: () => import('@/views/login') },
{ path: '/register', component: () => import('@/views/register') },
{ path: '/detail', component: () => import('@/views/detail') },
{
path: '/',
component: () => import('@/views/home'),
// 访问 / 时重定向到面经列表,避免出现空白页
redirect: '/article',
// 二级路由:渲染在 home/index.vue 的 router-view 中
children: [
{ path: 'article', component: () => import('@/views/article') },
{ path: 'collect', component: () => import('@/views/collect') },
{ path: 'like', component: () => import('@/views/like') },
{ path: 'user', component: () => import('@/views/user') }
]
}
]
const router = new VueRouter({
routes
})
export default routersrc/App.vue
html
<template>
<div id="app">
<!-- 一级路由出口 -->
<router-view />
</div>
</template>要点解释 / 易错点
Vue.use(Vant)是完整导入,好处是“拿来就用”,代价是打包体积大;import 'vant/lib/index.css'这一行样式千万别漏,否则组件没样式。- 完整导入与自动按需导入(babel-plugin-import + babel.config.js 的
plugins: [['import', { libraryName: 'vant', style: true }]])二选一,绝不能混用。切换方案时必须把另一套的配置全部删干净,并且改了配置文件要重启服务。 router/index.js中二级路由的path: 'article'不加斜杠,表示与父级拼接成/article;若写成/article就变成绝对路径,父级嵌套关系失效。- 子路由的出口在
home/index.vue里,不在App.vue里;四个标签按钮也必须写在home中,写在App.vue会导致登录页也出现底部导航。 redirect: '/article'是为了访问/时不出现空白页;不要重复写{ path: '/' }再 redirect,否则路由规则冲突。- 保存时代码格式报错由 ESLint 负责(检查格式,不查业务逻辑),VSCode 里需配置
"editor.codeActionsOnSave": { "source.fixAll": true }、"editor.formatOnSave": false,并禁用 Beautify 等格式化插件;ESLint 配置文件必须在项目根目录,且以根目录打开项目。
示例二:登录页(Vant NavBar + Form)
src/views/login/index.vue
html
<template>
<div class="login">
<!-- 标题区:导航组件当标题栏用,只保留 title 属性 -->
<van-nav-bar title="面经登录" />
<!-- 表单区:@submit 触发提交,values 就是表单里所有字段的值 -->
<van-form @submit="onSubmit">
<van-field
v-model="username"
name="用户名"
label="用户名"
placeholder="用户名"
:rules="[{ required: true, message: '请填写用户名' }]"
/>
<van-field
v-model="password"
type="password"
name="密码"
label="密码"
placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]"
/>
<div style="margin: 16px;">
<!-- 去掉 round 变直角按钮 -->
<van-button block type="info" native-type="submit">登录</van-button>
</div>
</van-form>
<!-- 第三区:超链接 -->
<router-link class="link" to="/register">还没有账号,去注册~</router-link>
</div>
</template>
<script>
export default {
data () {
return {
// v-model 绑定的数据必须先声明,否则一保存就报错
username: '',
password: ''
}
},
methods: {
onSubmit (values) {
console.log('submit', values)
}
}
}
</script>
<style lang="less">
.link {
display: block; /* a 标签默认是行内元素,要变块级才好右对齐 */
text-align: right;
margin-right: 20px;
font-size: 14px;
color: #069;
}
</style>要点解释 / 易错点
van-nav-bar文档示例里带left-text、left-arrow、right-text、@click-left、@click-right,本项目全都不需要,直接只留title;不要连methods里的方法一起抄过来。van-field上的v-model是双向绑定,data里必须提前声明username/password,否则运行时报“属性未定义”——这是复制文档代码后最常见的报错来源。@submit对应的methods必须自己补上,values就是这个表单里的全部字段值(用户名 + 密码)。- 按钮圆角由
round属性控制,删掉即为直角;颜色最后统一调,先别急着改。 router-link需要写display: block才能让text-align: right生效;to="/register"的斜杠不能丢。- 登录页与注册页结构几乎一致,做完一个复制改标题即可;页面里所有标签建议严格按 Vant 文档的写法(单标签自闭合),否则 ESLint 会报
vue/html-self-closing之类的格式错误。
示例三:主页底部标签栏(Vant Tabbar 路由模式)
src/views/home/index.vue
html
<template>
<div class="home">
<!-- 二级路由出口:上面这块区域是变化的 -->
<router-view />
<!-- route 开启路由模式,tabbar-item 用 to 指定跳转地址 -->
<van-tabbar route>
<van-tabbar-item to="/article" icon="notes-o">面经</van-tabbar-item>
<van-tabbar-item to="/collect" icon="star-o">收藏</van-tabbar-item>
<van-tabbar-item to="/like" icon="like-o">喜欢</van-tabbar-item>
<van-tabbar-item to="/user" icon="user-o">我的</van-tabbar-item>
</van-tabbar>
</div>
</template>要点解释 / 易错点
- 文档“基础用法”示例里有
v-model="active",直接复制会报错——两种解决方式:要么在data里补上active,要么直接删掉v-model。本项目走路由模式,所以删掉。 - 给
van-tabbar加route属性开启路由模式,里面每一项加to,就能像超链接一样跳转;只复制标签不加to是点不动的。 - 四个
to必须和router/index.js里的二级路由路径一一对应(/article、/collect、/like、/user),路径对不上就是白屏。 icon值必须是 Vant 内置图标名(如star-o、like-o、user-o),图标名写错不会报错,只是不显示,可到官方“Icon 图标”页复制名字,注意只复制名字,不要把整个标签复制进来。- 页面出现空白先查两件事:① 哈希地址是否与路由规则匹配;② 对应组件里是否有内容——代码没错但组件是空文件,同样是一片空白。
常见错误
- 现象:保存后满屏 ESLint 报错,逐条手改效率低。→ 原因:未启用 ESLint 保存修复,或 VSCode 自带格式化工具与 ESLint 冲突。→ 修法:以项目根目录打开,配置
editor.codeActionsOnSave.source.fixAll,关闭formatOnSave,禁用 Beautify 等冲突格式化工具。 - 现象:Vant 组件能用但样式丢失、构建报错。→ 原因:完整导入与自动按需导入混用,或切换方案时旧配置未清理。→ 修法:二选一;完整导入保留
main.js三行,自动按需保留 Babel 插件配置并删除另一方案代码。 - 现象:改了
babel.config.js或适配配置后不生效。→ 原因:未重启开发服务,或配置文件不在项目根目录。→ 修法:停止并重启服务;确认项目以根目录打开,一次只开一个项目。 - 现象:按需导入后新组件无样式或报错。→ 原因:只写了模板,未导入并注册组件;或同源
import分散未合并。→ 修法:按文档导入该组件并注册;同一来源的导入合并到一条。 - 现象:vw 适配后尺寸与设计稿不符。→ 原因:
viewportWidth未按设计稿倍数换算。→ 修法:750 二倍图写 375,1080 三倍图写 360;改配置后重启,用 375 宽设备验证 100px 盒子。 - 现象:访问
/空白,或 Tabbar 点击不跳转。→ 原因:一级/二级路由出口放错、未配重定向、Tabbar 未开路由模式或to写错。→ 修法:App.vue放一级出口,home放二级出口;/重定向到/article;van-tabbar加route,每项加正确to。 - 现象:登录页表单提交报错或取不到值。→ 原因:复制模板时漏掉
v-model对应数据和submit方法。→ 修法:补齐data与methods;按需删除按钮圆角、修改按钮文字。 - 现象:NavBar 出现多余左右按钮或事件报错。→ 原因:整段示例复制,未删无用属性和方法。→ 修法:只保留
van-nav-bar title,删除left-text、right-text、left-arrow及无用事件。
练习
- 故意写出至少 3 条不符合 Standard 的代码,用 ESLint 规则表定位错误代码并修复;再配置保存自动修复,对比修复前后控制台输出。
- 将项目从 Vant 完整导入切换为自动按需导入,使用 Button 和 Tabbar 验证样式;再切回完整导入,确保旧配置清理且服务已重启。
- 配置 vw 适配,假设设计稿宽度为 750,设置
viewportWidth,创建一个100px盒子,在 375 宽设备下验证实际宽度并说明结果。 - 完成路由骨架:四个一级页面、
home下四个二级页面,/重定向到/article,App.vue与home各放一个router-view,Tabbar 使用route、to、图标完成切换。 - 完成登录页布局:NavBar 标题、Form 用户名密码、登录按钮、注册链接;删除多余 NavBar 属性和按钮圆角,提交时能取到表单值。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | Vant组件库导入使用 | 14:46 |
| 2 | 完成项目适配 | 07:27 |
| 3 | 项目路由搭建 | 13:07 |
| 4 | 主页下面的4个标签 | 12:12 |
| 5 | toast轻提示 | 06:32 |
| 6 | 上午回顾 | 06:33 |
| 7 | 登录注册页布局 | 13:23 |
小结
- ESLint 管报错,保存修复管效率,格式化工具要避免互相打架。
- Vant 使用前先定导入方案;完整导入省事体积大,按需导入体积小但每用组件要导入注册。
- 导入方案切换是“清理旧配置 + 重启服务”,不是叠加配置。
- 适配配置的关键是设计稿倍数换算,验证要看实际设备宽度下的尺寸。
- 路由先画层级再配出口:一级出口在
App.vue,二级出口在home;默认页用重定向消除空白。 - Tabbar 跳转依赖路由模式和正确的
to地址,示例代码不能无脑复制。 - 页面布局按区域拆:标题、表单、链接;示例只取所需,数据和方法必须补齐。
- 根目录打开项目、一次开一个项目、改配置后重启,是本节排错底线。