vercel vue vant4 移动端项目模板
vue vant4 移动端项目模板
初始化项目
npm create vue@latest
npm i vant@4cd vue-vant4-javascript-template
npm install
npm run format
npm run dev初始化App.vue,支持基本的路由
<template>
<router-view />
</template>
<script setup>
import { useRouter } from 'vue-router'
// 使用router接管路由
const router = useRouter()
// 监听路由变化
router.afterEach((to, from) => {
})
</script>
<style scoped></style>在main.js中引入vant4
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import Vant from 'vant'
import 'vant/lib/index.css'
const app = createApp(App)
app.use(router)
app.use(Vant)
app.mount('#app')创建api
创建src/api目录,用于存放api相关的文件
在src/api目录下创建index.js文件,用于导出api相关的文件
export { http } from './http'创建src/api/http.js文件,用于配置axios拦截
/**
* 使用axios 统一处理请求和响应
*/
import axios from 'axios';
// 创建 axios 实例
export const http = axios.create({
timeout: 30000, // 请求超时30S
headers: {
'Content-Type': 'application/json',
},
});
// 请求拦截器
// 请求拦截器
http.interceptors.request.use(
(config) => {
// 可以在这里添加 token 等
//console.log('Request:', config.method?.toUpperCase(), config.url)
return config
},
(error) => {
console.error('Request Error:', error)
return Promise.reject(error)
}
)
// 响应拦截器
http.interceptors.response.use(
(response) => {
//console.log('Response:', response.status, response.config.url)
return response
},
(error) => {
// 处理错误
if (error.response) {
// 服务器返回了错误状态码
//console.error('Response Error:', error.response.status, error.response.data)
switch (error.response.status) {
case 404:
console.error('请求的资源不存在')
break
case 500:
console.error('服务器内部错误')
break
default:
console.error('请求失败:', error.response.statusText)
}
} else if (error.request) {
// 请求已发出但没有收到响应(可能是 CORS 问题)
//console.error('Network Error:', error.message)
console.error('可能的原因:')
console.error('1. 后端服务未启动')
console.error('2. CORS 配置不正确')
console.error('3. 网络连接问题')
} else {
// 其他错误
console.error('Error:', error.message)
}
return Promise.reject(error)
}
)
export default http视图组件
创建api/views/目录,用于存放视图相关的文件
创建一个HomeView.vue文件,使用vant4组件展示首页
<template>
<div class="home-view">
<!-- 导航栏 -->
<van-nav-bar title="首页" left-arrow @click-left="onClickLeft" />
<!-- 主容器 -->
<div class="home-content">
<!-- 轮播图 -->
<van-swipe class="swipe-banner" :autoplay="3000">
<van-swipe-item>
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/apple-1.jpeg" alt="banner1" />
</van-swipe-item>
<van-swipe-item>
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/apple-2.jpeg" alt="banner2" />
</van-swipe-item>
<van-swipe-item>
<img src="https://fastly.jsdelivr.net/npm/@vant/assets/apple-3.jpeg" alt="banner3" />
</van-swipe-item>
</van-swipe>
<!-- 搜索栏 -->
<van-search
v-model="searchValue"
placeholder="请输入搜索内容"
@search="onSearch"
class="search-bar"
/>
<!-- 功能栅格 -->
<van-grid :column-num="4" class="feature-grid">
<van-grid-item icon="home-o" text="首页" />
<van-grid-item icon="search" text="搜索" />
<van-grid-item icon="shopping-cart-o" text="购物车" />
<van-grid-item icon="user-o" text="我的" />
</van-grid>
<!-- 卡片列表 -->
<div class="card-section">
<h2 class="section-title">推荐商品</h2>
<van-card
v-for="item in productList"
:key="item.id"
:title="item.title"
:desc="item.desc"
:thumb="item.thumb"
:price="item.price"
class="product-card"
/>
</div>
<!-- 按钮组 -->
<div class="button-group">
<van-button type="primary" block @click="handlePrimary"> 主要按钮 </van-button>
<van-button type="success" block class="mt-10"> 成功按钮 </van-button>
<van-button type="warning" block class="mt-10"> 警告按钮 </van-button>
</div>
</div>
</div>
</template>
<script>
import { ref } from 'vue'
import { showToast } from 'vant'
export default {
name: 'HomeView',
setup() {
const searchValue = ref('')
const productList = ref([
{
id: 1,
title: '商品1',
desc: '商品描述',
thumb: 'https://fastly.jsdelivr.net/npm/@vant/assets/iphone.jpeg',
price: '¥2999',
},
{
id: 2,
title: '商品2',
desc: '商品描述',
thumb: 'https://fastly.jsdelivr.net/npm/@vant/assets/iphone.jpeg',
price: '¥3999',
},
])
const onClickLeft = () => {
showToast('返回上一页')
}
const onSearch = (val) => {
showToast(`搜索: ${val}`)
}
const handlePrimary = () => {
showToast('点击了主要按钮')
}
return {
searchValue,
productList,
onClickLeft,
onSearch,
handlePrimary,
}
},
}
</script>
<style scoped>
.home-view {
background-color: #f5f5f5;
min-height: 100vh;
}
.home-content {
padding-bottom: 20px;
}
.swipe-banner {
width: 100%;
height: 200px;
}
.swipe-banner img {
width: 100%;
height: 100%;
object-fit: cover;
}
.search-bar {
margin: 10px 0;
}
.feature-grid {
background-color: #fff;
margin: 10px 0;
}
.card-section {
padding: 15px;
}
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.product-card {
margin-bottom: 10px;
}
.button-group {
padding: 15px;
}
.mt-10 {
margin-top: 10px;
}
</style>
更新vue路由router/index.js,添加首页路由
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
const routes = [
{
path: '/',
name: 'Home',
component: HomeView
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
})
export default router本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 WenYan Blog!
评论








