vue vant4 移动端项目模板

初始化项目

npm create vue@latest
npm i vant@4
cd 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