
为什么选Vite+Vue+Yarn组合?先把基础逻辑讲明白
先别急着写代码,我得先跟你说清楚:这套组合不是随便选的,每一步都有“避坑逻辑”。
首先说Vite——你之前可能用过Webpack,是不是觉得启动项目要等好久?我之前用Webpack搭登录页,每次改一行代码都要等5秒才能刷新,心态都崩了。后来换成Vite,启动只要1秒,改代码瞬间热更新,因为Vite是基于ES Modules的按需编译,不用像Webpack那样先把所有文件打包再启动(Vite官方文档里明确说“针对现代浏览器的轻量构建工具”)。对新手来说,少等时间就是少犯错误的概率,这点太重要了。
然后是Vue——你可能听过React,但Vue的双向绑定(v-model)对新手更友好。比如登录页的输入框,用Vue的话,只要写v-model="username"
,输入的内容直接同步到data里,不用像React那样写onChange事件处理。我之前用React写登录页,光处理输入框就写了10行代码,换成Vue只要1行,效率高太多。
最后是Yarn——别跟我说“npm也行”,我之前用npm装依赖,经常遇到“依赖版本冲突”的问题,比如装vue-router时,npm拉的版本和Vue不兼容,导致项目跑不起来。后来换成Yarn,它的yarn.lock
文件会把每个依赖的版本精确锁定,只要你没删这个文件,不管在哪台电脑上装,依赖版本都一样。我帮朋友搭项目时,用Yarn装依赖,从来没遇到过版本冲突,比npm稳多了——不是说npm不好,只是Yarn的依赖管理对新手更友好。
从0到1搭登录页,每一步都踩过坑的实操指南
接下来进入正题,每一步我都标了“踩过的坑”,你照着做就能避开。
第一步:用Yarn初始化Vite项目,别漏了这几个配置
先打开终端(不管是Windows的cmd还是Mac的Terminal),输入这行命令:
yarn create vite my-login template vue
这里一定要加template vue
!我第一次没加,结果生成的是Vanilla(原生JS)项目,白费了半小时功夫——Vite默认模板是Vanilla,得手动指定Vue模板才行。
然后进入项目文件夹:cd my-login
,再装依赖:yarn install
。等依赖装完,输入yarn dev
启动项目,浏览器打开http://localhost:3000,就能看到Vite的默认页面了。
接下来要配置vue-router(因为登录页要跳转到首页),先装依赖:yarn add vue-router@4
(注意要加@4,因为Vue3对应router4版本)。然后在src文件夹下创建router
文件夹,里面建index.js
文件,写以下代码:
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
import Home from '../views/Home.vue'
const routes = [
{ path: '/', redirect: '/login' }, // 默认跳转到登录页
{ path: '/login', component: Login },
{ path: '/home', component: Home, meta: { requiresAuth: true } } // 需要登录才能进
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL), // 历史模式,避免#号
routes
})
// 路由守卫:未登录的用户不能进首页
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (to.meta.requiresAuth && !token) {
next('/login')
} else {
next()
}
})
export default router
然后在main.js
里引入router:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
我之前没加process.env.BASE_URL
,结果部署到服务器后刷新页面404,后来查Vite文档才知道,历史模式需要配置base URL,不然服务器找不到页面——这坑我踩过,你别再踩了。
第二步:写登录表单组件,重点在实时验证和用户体验
登录页的核心是表单,但别只写个输入框和按钮就完事——用户体验好不好,全在细节里。
首先在src/views下创建Login.vue
组件,模板部分写表单:
用户登录
type="email"
v-model.trim="form.username"
@input="validateField('username')"
placeholder="请输入邮箱"
class="{ 'is-error': errors.username }"
>
type="password"
v-model.trim="form.password"
@input="validateField('password')"
placeholder="请输入密码(6-12位)"
class="{ 'is-error': errors.password }"
>
然后是script部分,处理数据和验证:
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import axios from 'axios'
const router = useRouter()
const form = reactive({
username: '',
password: ''
})
const errors = reactive({
username: '',
password: ''
})
const isLoading = ref(false)
// 实时验证单个字段
const validateField = (field) => {
switch (field) {
case 'username':
errors.username = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/.test(form.username) ? '' '请输入有效的邮箱'
break
case 'password':
errors.password = form.password.length >=6 && form.password.length <=12 ? '' '密码需6-12位'
break
}
}
// 提交表单
const handleLogin = async () => {
// 先验证所有字段
validateField('username')
validateField('password')
if (errors.username || errors.password) return
isLoading.value = true
try {
const res = await axios.post('/api/login', form)
localStorage.setItem('token', res.data.token) // 存token
router.push('/home') // 跳首页
} catch (err) {
alert(err.response.data.message || '登录失败,请重试')
} finally {
isLoading.value = false
}
}
这里有几个我踩过的坑要提醒你:
@input
事件实时验证,每输一个字符就检查,用户边填边改,体验好太多。 isLoading
状态!我之前没加这个,用户点两次提交按钮,导致重复请求后端,返回“重复登录”的错误——现在点击后按钮禁用,显示“登录中…”,完美解决这个问题。 v-model.trim
去掉输入内容的前后空格,比如用户不小心打了个空格在用户名后面,会导致登录失败——这个小细节能减少很多不必要的错误。 第三步:对接后端接口,处理登录状态和跳转
登录页的最后一步是对接后端,但别直接用axios发请求——封装一下,后期维护更方便。
首先装axios:yarn add axios
,然后在src下创建api
文件夹,建request.js
封装axios:
import axios from 'axios'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL, // 从.env文件取baseURL
timeout: 5000
})
// 请求拦截器:加token
request.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = Bearer ${token}
}
return config
}, error => {
return Promise.reject(error)
})
// 响应拦截器:处理token和错误
request.interceptors.response.use(response => {
return response.data
}, error => {
if (error.response.status === 401) { // token过期或无效
localStorage.removeItem('token')
window.location.href = '/login'
}
return Promise.reject(error)
})
export default request
然后在Login.vue
里用这个封装好的request代替axios:
// 把原来的import axios from 'axios'改成
import request from '../api/request'
// 提交函数里改成
const res = await request.post('/login', form)
这里有个关键:用.env文件存环境变量。在项目根目录创建.env.development
文件,写:
VITE_API_BASE_URL = 'http://localhost:8080' // 后端开发接口地址
生产环境创建.env.production
,写生产接口地址。这样打包时自动切换,不用改代码——我之前直接把baseURL写死在request.js里,开发和生产环境要手动改,很麻烦,现在用环境变量,省心多了。
token存在localStorage里比sessionStorage好——sessionStorage关闭页面就没了,用户得重新登录;localStorage能存更久,我一般会加个过期时间,比如:
// 存token时加过期时间
const setToken = (token) => {
const exp = new Date().getTime() + 72460601000 // 7天过期
localStorage.setItem('token', JSON.stringify({ token, exp }))
}
// 取token时检查是否过期
const getToken = () => {
const tokenObj = JSON.parse(localStorage.getItem('token'))
if (!tokenObj) return null
if (new Date().getTime() > tokenObj.exp) {
localStorage.removeItem('token')
return null
}
return tokenObj.token
}
我之前没加过期时间,用户的token永远有效,安全隐患很大——现在加了过期时间,7天后自动失效,更合理。
Vite+Vue+Yarn常用命令汇总
最后给你整理了份常用命令表,方便你查:
命令 | 作用 | 注意事项 |
---|---|---|
yarn create vite my-login template vue | 初始化Vite Vue项目 | 必须加template vue,否则生成Vanilla项目 |
yarn install | 安装项目依赖 | 确保有yarn.lock文件,依赖更稳定 |
yarn dev | 启动开发服务器 | 默认端口3000,可改vite.config.js的server.port |
yarn build | 打包生产环境代码 | 输出到dist文件夹,部署前要检查base URL |
你要是按这些步骤试了,肯定能搭出一个功能完整、体验不错的登录页——我帮朋友搭的那版,上线后用户反馈“登录很顺畅,没遇到奇怪的问题”。如果过程中遇到卡住的地方,比如配置router报错,或者接口对接不上,欢迎回来跟我说,我帮你看看——毕竟我踩过的坑,不想让你再踩一遍!
我之前教过刚学前端的朋友写登录页输入框,他最开始用React的时候,光处理用户名输入就卡了半小时——得给input加onChange事件,函数里还要写event.target.value,再setState更新到state里,结果要么忘写event.preventDefault()导致页面刷新,要么把state的变量名拼错(比如把username写成userName),折腾来折腾去才把“输入内容同步到数据”这件事搞通。后来我让他换Vue试试v-model,就给input加了个v-model=”username”,他输了个测试邮箱,低头看data里的username变量,居然直接跟着变了,当时就说:“这也太省事了吧?我之前写React得写5行代码的事儿,Vue一行就搞定了?”
其实登录页的输入框最需要的就是这种“不用额外操作”的同步——比如密码输入框,你得实时检查用户输的是不是6-12位,要是用React,得先在onChange里更新state,再监听state变化触发验证函数,新手很容易把顺序搞反(比如先验证再更新,结果验证的还是旧密码);但用Vue的v-model,输入的字符一敲进输入框,data里的password就同步变了,再给input加个@input事件调用验证函数,输的时候就能立刻提示“密码需6-12位”。我朋友后来改Vue写登录页,光输入框部分的代码就比React少了三分之二,而且再也没犯过“数据同步延迟”的错——对新手来说,少写点重复代码,就少点出错的机会,v-model刚好帮你把最基础的“输入同步”问题解决了,不用再去纠结事件处理那套逻辑。
为什么选择Yarn而不是npm来管理项目依赖?
文章中提到Yarn的yarn.lock文件会精确锁定每个依赖的版本,避免npm常见的“依赖版本冲突”问题(比如安装vue-router时版本不兼容)。只要保留yarn.lock,不同电脑安装的依赖版本完全一致,对新手更友好、更稳定。
Vite为什么比Webpack启动和热更新速度更快?
Vite基于ES Modules(现代浏览器原生支持)实现按需编译,无需像Webpack那样先打包所有文件再启动项目。 启动时间从Webpack的数秒缩短到1秒内,改代码时也能瞬间热更新,减少新手等待时间和出错概率。
Vue的双向绑定(v-model)对登录页输入框处理有什么帮助?
登录页的输入框(如用户名、密码)需要同步用户输入内容到数据中。用Vue的v-model只需一行代码(如v-model=”username”),就能自动实现“输入内容→数据同步”,无需像React那样写onChange事件处理,减少代码量,对新手更友好。
登录后的token为什么存在localStorage而不是sessionStorage?
sessionStorage关闭页面后会清空,用户需重新登录;localStorage能持久存储(通常结合7天过期时间),用户下次打开页面无需重复登录,体验更流畅。文章中还提到可给localStorage的token加过期时间(如7天),兼顾持久化和安全性。
登录页为什么要做输入实时验证而不是提交时验证?
提交时验证需用户填完所有内容才提示错误(比如用户名格式错了要等点击提交才知道),体验差。实时验证(通过@input事件)能让用户边输入边改,及时纠正错误(如输错邮箱时立刻提示“请输入有效的邮箱”),大幅提升用户体验。