vue3+ts+vant4+pinia+axios+scss创建项目基本流程

vue3+ts+vant4+pinia+axios+scss创建项目基本流程

自我记录

一.pnpm介绍&安装&使用 (可以跳过)

1.介绍

本质上他是一个包管理工具,和npm/yarn没有区别,主要优势在于

  • 包安装速度极快
  • 磁盘空间利用效率高
  • pnpm 是一个高效的包管理工具,使用和npm和yarn基本相同

2.安装

npm i pnpm -g

3.使用

npm命令pnpm等效
npm installpnpm install
npm i axiospnpm add axios
npm i webpack -Dpnpm add webpack -D
npm run devpnpm add webpack -D

二.项目创建

1.使用 create-vue 脚手架创建项目

create-vue参考地址:https://github.com/vuejs/create-vue

2.步骤

2.1 使用命令:

pnpm create vue
# or
npm init vue@latest
# or
yarn create vue

下图以pnmp演示(文章同)
在这里插入图片描述

2.2 选择项目依赖内容:

✔ Project name: … czbk-h5-test
✔ Add TypeScript? … No / `Yes`
✔ Add JSX Support? … `No` / Yes
✔ Add Vue Router for Single Page Application development? … No / `Yes`
✔ Add Pinia for state management? … No / `Yes`
✔ Add Vitest for Unit Testing? … `No` / Yes
✔ Add an End-to-End Testing Solution? › `No`
✔ Add ESLint for code quality? … No / `Yes`
✔ Add Prettier for code formatting? … No / `Yes`

Scaffolding project in /Users/sougewang/test/test/czbk-h5-test...

Done. Now run:

  cd czbk-h5-test
  pnpm install
  pnpm format
  pnpm dev

1.项目名称
2.是否支持TS
3.是否支持JSX
4.是否用一个 路由 单文件包?
5.是否使用 Pinia 进行状态管理
6.是否需要单元测试
7.是否需要 端对端 的测试
8.是否需要 ESLint 的验证校验
9.是否需要 Prettier 格式化工具

2.3安装依赖&运行

如下图

在这里插入图片描述
默认的项目目录

正常一共是 5173 因为我已经打开过一个窗口了所以是5174 这个可以忽略 后期也可以配置
说明:后续以czbk-h5为例5174czbk-h5-test 都是一样的上面我是新走了一下创建流程用来截图

三.Vscode 插件安装&eslint预制配置

1.安装:extensions.json里面的必装

Ps: 如果vscode没有安装过,项目打开的时候右下角会有提示安装

  • Vue Language Features (Volar) vue3语法支持
  • TypeScript Vue Plugin (Volar) vue3中更好的ts提示
  • Eslint 代码风格校验

注意:安装过 Prettier 要禁用掉避免和项目里面的 eslint 冲突。

了解:大中型项目建议开启 TS托管模式 , 更好更快的类型提示。

在这里插入图片描述

2.eslint预制配置

使用:eslint的预制配置,且了解配置作用(每个公司都不一样看个人)
常见规则 https://prettier.io/docs/en/options.html

.eslintrc.cjs添加

/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
  root: true,
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/eslint-config-typescript',
    '@vue/eslint-config-prettier/skip-formatting'
  ],
  parserOptions: {
    ecmaVersion: 'latest'
  },
  rules: {
    'prettier/prettier': [
      // 格式:单引号,没有分号,行宽度100字符,没有对象数组最后一个逗号,换行字符串自动(系统不一样换行符号不一样)
      'warn',
      {
        singleQuote: true,
        semi: false,
        printWidth: 80,
        trailingComma: 'none',
        endOfLine: 'auto'
      }
    ],
    'vue/multi-word-component-names': [
      //vue 组件需要大驼峰命名,除去 index 之外,App 是默认支持的
      'warn',
      {
        ignores: ['index']
      }
    ],
    'vue/no-setup-props-destructure': ['off'] //允许对 props 进行解构,我们会开启解构保持响应式的语法糖
  }
}

项目文件会有很多报错目前不用管

3.文件修复格式格式问题

执行命令所有文件修复格式或者每个文件自己去保存一下也可以

pnpm format
or
pnpm lint

四.目录结构调整&路由解读

1.目录调整

./src
├── assets        `静态资源,图片...`
├── components    `通用组件`
├── composable    `组合功能通用函数`
├── icons         `svg图标`
├── router        `路由`
│   └── index.ts
├── services      `接口服务API`
├── stores        `状态仓库`
├── styles        `样式`
│   └── main.scss
├── types         `TS类型`
├── utils         `工具函数`
├── views         `页面`
├── main.ts       `入口文件`
└── App.vue       `根组件`

在这里插入图片描述
创建对应文件夹以及删除多余文件.

2.路由解读

import { createRouter, createWebHistory } from 'vue-router'

// vue2的路由
// 1.import VueRouter from 'vue-router'
// 2.const router = new VueRouter({ routes: [ // 路由规则 ] })
// 3.选择路由模式 hash /#/user   history /user

// 现在vue3的路由
// 1.创建路由实例 createRouter({ //配置对象 })
// 2.配置选项中 routes: [ // 路由规则 ]
// 3.createWebHistory 使用路由history 模式
// 4.createWebHashHistory(), //使用路由hash模式
// 5.import.meta.env.BASE_URL 路由的基准路由 create-vue 脚手架提供的环境变量 ps:在vite.config.ts 文件可以配置base: '/',
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: []
})

export default router

3.使用路由&及守卫

NProgress 请看 另一篇文章 主要就是加载页面的时候实现进度条功能
路由前置首位 后置首位 以及修改 标题

import { useUserStore } from '@/stores'
import { createRouter, createWebHistory } from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/login',
      component: () => import('@/views/Login/index.vue'),
      meta: { title: '登录' }
    },
    {
      path: '/',
      redirect: '/home',
      component: () => import('@/views/Layout/index.vue'),
      children: [
        {
          path: '/home',
          component: () => import('@/views/Home/index.vue'),
          meta: { title: '首页' }
        },
        {
          path: '/user',
          component: () => import('@/views/User/index.vue'),
          meta: { title: '我的' }
        }
      ]
    }
  ]
})
// 修改进度条插件的配置
NProgress.configure({
  showSpinner: false
})
// 前置首位 访问权限控制
router.beforeEach((to) => {
  // 开启页面进度条
  NProgress.start()
  // 用户仓库
  const store = useUserStore()
  // 用户白名单
  const wihteList = ['/login']
  // 没有token 并且 不再白名单 则跳转登录页
  if (!store.user?.token && !wihteList.includes(to.path)) return '/login'
  // 放行 return true  可以不用写
})
// 后置守卫
router.afterEach((to) => {
  // 设置页面标题
  document.title = to.meta.title || '奔跑的代码!'
  NProgress.done()
})
export default router

五.安装Pinia&并使用本地存储

详情请见另一篇文章:Vue3+Pinia+数据持久化 20分钟快速上手

六.安装scss

项目使用sass预处理器,安装sass,即可支持scss语法:

pnpm add sass -D

文件使用:

<style scoped lang="scss"></style>

七.安装使用Vant

1.安装Vant

# Vue 3 项目,安装最新版 Vant
npm i vant
# 通过 yarn 安装
yarn add vant
# 通过 pnpm 安装
pnpm add vant

2.全局引入并使用

src/main.ts 注意全局样式文件要在下方,这样方便后期覆盖vant组件样式

import { createApp } from 'vue'

import App from './App.vue'
import router from './router'
// 引入 pinia
import pinia from './stores'
// 样式全局使用
import 'vant/lib/index.css'
import './styles/main.scss'

const app = createApp(App)

// vue使用pinia插件,use(pinia的插件)
app.use(pinia)
app.use(router)
app.mount('#app')

组件按需手动引入测试是否可用

<script setup lang="ts">
// 组件按需手动引入测试是否可用
import { Button as VanButton } from 'vant'
</script>

<template>
  <van-button>按钮</van-button>
</template>

<style scoped lang="scss"></style>

3.Vant适配移动端 使用vw

3.1 安装插件postcss-px-to-viewport

npm install postcss-px-to-viewport -D
# or
yarn add -D postcss-px-to-viewport
# or
pnpm add -D postcss-px-to-viewport

3.2 配置使用插件

czbk-h5/postcss.config.js
在这里插入图片描述

3.3 解决报错问题

3.3.1 编辑器报错[plugin:vite:css] (未报错的可以跳过)

报错:[vite] Internal server error: Failed to load PostCSS config
解决方案:将postcss.config.js 文件名改为 postcss.config.cjs 也就是更改.js文件后缀为.cjs

3.3.2 控制台报错 (不影响使用)

在这里插入图片描述
解决方案:可忽略,或者使用 postcss-px-to-viewport-8-plugin 代替当前插件

4. 自动按需加载组件

手动按需使用组件比较麻烦,需要先导入。配置函数自动按需导入后直接使用即可。 官方文档

4.1 安装
# 通过 npm 安装
npm i unplugin-vue-components -D
# 通过 yarn 安装
yarn add unplugin-vue-components -D
# 通过 pnpm 安装
pnpm add unplugin-vue-components -D
4.2 配置

vite.config.ts

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入按需导入插件
import Components from 'unplugin-vue-components/vite'
// 各种组件库的解析器 //里面还有 ElementUiResolver,ElementPlusResolverOptions,AntDesignVueResolver等常见的组件库
import { VantResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/
export default defineConfig({
  // 默认'/' 是基准地址
  base: '/',
  plugins: [
    // 解析单文件组件的插件
    vue(),
    //使用按需导入插件 默认自动加载 components 下的组件,通用级别组件.
    Components({
      // 默认是true 开启自动生成组件的类型声明文件,vant的组件已经有类型声明文件,只要导入了就会使用类型声明.
      dts: false,
      // 在main.ts 已经引入了所有的组件样式,不需要自动导入样式,只需要自动导入组件即可
      resolvers: [VantResolver({ importStyle: false })]
    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

使用的时候 就不需要在引入了

<script setup lang="ts"></script>
<template>
  <van-button>按钮</van-button>
</template>

<style scoped lang="scss"></style>

在这里插入图片描述

5. css 变量定制主题

src/App.vue 默认样式
在这里插入图片描述
使用css变量定制项目主题,和修改vant主题 官方文档
src/styles/main.scss

// 项目共用的样式文件
:root {
    --cz-primary: #16C2A3;
    --cz-text1: red;
    --cz-text2: pink;
    // 覆盖vant主体色
    --van-primary-color: var(--cz-primary);
}

src/App.vue使用

<script setup lang="ts">
import { Button as VanButton } from 'vant'
</script>

<template>
  <!-- 验证vant颜色被覆盖 -->
  <van-button type="primary">按钮</van-button>
  <a href="#">测试</a>
</template>

<style scoped lang="scss">
// 使用css全局变量
a {
  color: var(--cz-text1);
}
</style>

效果
在这里插入图片描述

6. 二次封装NavBar组件实现公共标题

6.1 布局&功能&使用

src/components/CpNavBar.vue

<script setup lang="ts">
import { useRouter } from 'vue-router'
// 拿路由实例
const router = useRouter()
const props = defineProps<{
  title?: string
  rightText?: string
  back?: () => void
}>()
const emit = defineEmits<{ (e: 'click-right'): void }>()
const onClickLeft = () => {
  // 扩展 back 属性,如果有就执行 back 对应的函数。
  // 给全屏弹出层使用
  if (props.back) {
    return props.back()
  }
  // TODO 点击左侧返回按钮
  // 实现返回 如果有当前网站的上一次历史记录 就执行back返回
  // 没有历史记录则跳转到 首页
  if (history.state?.back) {
    router.back()
  } else {
    router.push('/home')// 为了测试功能时否正常 后续需要换成 '/'
  }
}
const onClickRight = () => {
  // TODO 点击右侧文字按钮
  emit('click-right')
}
</script>

<template>
  <van-nav-bar
    left-arrow
    fixed
    :title="title"
    :right-text="rightText"
    @click-left="onClickLeft"
    @click-right="onClickRight"
  />
</template>

<style lang="scss" scoped>
:deep() {
  .van-nav-bar {
    &__arrow {
      font-size: 18px;
      color: var(--cz-text1);
    }

    &__text {
      font-size: 15px;
    }
  }
}
</style

使用src/views/Login/index.vue
之所以不用引入<Cp-nav-bar /> 组件 就可以使用是因为 4. 自动按需加载组件 里面的配置项 可以回去看看 有注释

<script setup lang="ts">
const fn = () => {
  console.log('点击了右侧')
}
</script>
<template>
  <div class="login-page">
    <cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
  </div>
</template>
<style lang="scss" scoped>
.login {
  &-page {
    padding-top: 46px;
  }
}
</style>

效果
在这里插入图片描述

6.2 给二次封装的组件添加组件类

给组件添加类型,让写属性和事件可以有提示(TS可以去识别) 这里也是模仿Vant组件的源码写法

src/types/components.d.ts

// 给components 下的全局组件设置类型
// 1. 导入组件实例
import CpNavBar from '@/components/CpNavBar.vue'
// 2. 声明 vue 类型模块
declare module 'vue' {
  // 3. 给 vue  添加全局组件类型,interface 和之前的合并
  interface GlobalComponents {
    // 指定组件类型,typeof(从一个JS对象中得到他对应的TS类型) 从组件对象得到类型,设置给全局组件 CpNavBar
    CpNavBar: typeof CpNavBar
  }
}

在这里插入图片描述

八.二次封装axios

1.安装axios&配置

1.中文文档
2.github文档

npm install axios
or
yarn add axios
or
pnpm add axios

src/utils/rquest.ts

// 二次封装axios
import router from '@/router'
import { useUserStore } from '@/stores'
import axios, { type Method } from 'axios'
import { showToast } from 'vant'
// 1. axios的配置
// 1.1 创建一个新的axios实例,配置基准地址,配置响应超时时间
// 1.2 添加请求拦截器,在请求头携带token
// 1.3 添加响应拦截器,判断业务是否成功,剥离无效的数据,401错误拦截去登录页面(删除当前用户信息),
const baseURL = 'xxxxxxxxx'
const instance = axios.create({
  baseURL,
  timeout: 10000
})
// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 修改config,比如:修改请求头
    // 获取token===>就是获取user
    const store = useUserStore()
    if (store.user?.token && config.headers) {
      config.headers.Authorization = `Bearer ${store.user.token}`
    }
    return config
  },
  (err) => Promise.reject(err)
)
// 响应拦截器
// 将来  axios.get()
// .then(res=>{ // res 就是后台的数据,之前的res.data })
// .catch(e=>{ // 200+10001这种情况,e就是res.data , 如果是状态吗的错误 401 403 404 e 就错误对象  })
instance.interceptors.response.use(
  (res) => {
    // status 是200是响应成功的,res.data.code 是10000业务成功
    // 如果不是 10000 呢,使用 vant 的轻提示,报错阻断程序
    if (res.data.code !== 10000) {
      showToast(res.data.message || '网络异常')
      return Promise.reject(res.data)
    }
    // 剥离无效数据
    return res.data
  },
  // 401处理
  (err) => {
    // 请求报错,响应出错
    // 遇见401跳转登录
    // 1. 现在在 /user/patient 页面下,发起一个获取用户信息的请求,但是此时token失效
    // 2. 跳转登录页面,登录成功之后,需要跳转回 /user/patient 页面 (默认跳转 /user 首页)
    // vue2  $router 路由实例,提供路由相关函数操作  $route  路由相关信息,query params path 。。。
    if (err.response.status === 401) {
      // 需要删除用户信息
      const store = useUserStore()
      store.delUser()
      // /user/patient?id=1000
      // path  /user/patient  不带查询参数
      // fullPath  /user/patient?id=1000  完整路径
      // currentRoute 是一个 ref 创建的数据,需要.value
      router.push(`/login?returnUrl=${router.currentRoute.value.fullPath}`)
    }
    return Promise.reject(err)
  }
)
// obj = { name: 'jack', age: 100 }  obj['name'] ===> const name = 'name'  obj[name]

// 2. 请求工具函数
// 2.1 参数:url  method  submitData
// 2.2 返回:instance 调用接口的promise对象
// const request = (url: string, method: string, submitData?: object) => {
//   return instance.request({
//     url,
//     method,
//     // 区分get和其他请求post
//     // get 提交数据,选项:params
//     // 其他请求post 提交数据,选项:data
//     [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
//   })
// }
// res响应数据类型
type Data<T> = {
  code: string
  message: string
  data: T
}
const request = <T>(
  url: string,
  method: Method = 'get', // 默认是get
  submitData?: object // 可以不传
) => {
  // 泛型的第二个参数,可以自定义响应数据类型
  return instance.request<T, Data<T>>({
    url,
    method,
    // 区分get和其他请求post
    // get 提交数据,选项:params
    // 其他请求post 提交数据,选项:data // toLowerCase 将字符串转换为小写字母
    [method.toLowerCase() === 'get' ? 'params' : 'data']: submitData
  })
}
// baseURL 基准地址
// instance 是配置好的axios
// request 用来调用接口
export { baseURL, instance, request }

简单使用测试src/App.vue

<script setup lang="ts">
import { useUserStore } from './stores'
import type { User } from './types/user'

import { request } from './utils/rquest'
const store = useUserStore()
const login = () => {
  // 接口地址(去除基准路径之后的地址), 请求方式 , 请求参数
  request<User>('login/password', 'POST', {
    mobile: '12345678900',
    password: '111111'
  })
    .then((res) => {
      // 存储到本地
      store.setUser(res.data)
    })
    .catch((e) => {
      // 异常捕获
      console.log(e)
    })
}
</script>
<template>
  <van-button type="primary" @click="login">登录</van-button>
</template>

九.图标组件-打包svg地图

实现:根据 icons 文件svg图片打包到项目中,通过组件使用图标

1.安装&配置

参考文档:https://github.com/vbenjs/vite-plugin-svg-icons
icons文件打包的产物?会生成一个 svg 结构(js创建的)包含所有图标,理解为 精灵图
安装

yarn add vite-plugin-svg-icons -D
# or
npm i vite-plugin-svg-icons -D
# or
pnpm install vite-plugin-svg-icons -D

配置 打包svg图标 vite.congfig.ts

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 引入按需导入插件
import Components from 'unplugin-vue-components/vite'
// 各种组件库的解析器 //里面还有 ElementUiResolver,ElementPlusResolverOptions,AntDesignVueResolver 等常见的组件库
import { VantResolver } from 'unplugin-vue-components/resolvers'
// 配置svg精灵图插件
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
  // 默认'/' 是基准地址
  base: '/',
  plugins: [
    // 解析单文件组件的插件
    vue(),
    //使用按需导入插件 默认自动加载 components 下的组件,通用级别组件.
    Components({
      // 默认是true 开启自动生成组件的类型声明文件,vant的组件已经有类型声明文件,只要导入了就会使用类型声明.
      dts: false,
      // 在main.ts 已经引入了所有的组件样式,不需要自动导入样式,只需要自动导入组件即可
      resolvers: [VantResolver({ importStyle: false })]
    }),
+    // 打包svg图标目录
+    createSvgIconsPlugin({
+      // 指定需要缓存的图标文件夹 (打包指定svg图标的目录) //路径转换为绝对路径
+      iconDirs: [path.resolve(process.cwd(), 'src/icons')]
+    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

src/main.ts 引用

import { createApp } from 'vue'

import App from './App.vue'
import router from './router'
// 引入 pinia
import pinia from './stores'
// 使用svg精灵图
+import 'virtual:svg-icons-register'
// 样式全局使用
import 'vant/lib/index.css'
import './styles/main.scss'

const app = createApp(App)

// vue使用pinia插件,use(pinia的插件)
app.use(pinia)
app.use(router)
app.mount('#app')

2.简单使用

src/views/Login/index.vue

例如: src/icons/user/add.svg
'icon-[dir]-[name]' # 是固定的 icon- 固定开头 dir 图标所在目录 name 图标的名称

<script setup lang="ts">
const fn = () => {
  console.log('点击了右侧')
}
</script>
<template>
  <div class="login-page">
    <cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
    <!-- 测试svg -->
    <svg aria-hidden="true">
      <!-- src/icons/user/add.svg -->
      <!-- 'icon-[dir]-[name]' # 是固定的 icon- 固定开头 dir 图标所在目录 name 图标的名称 -->
      <use href="#icon-user-add" />
    </svg>
  </div>
</template>
<style lang="scss" scoped>
.login {
  &-page {
    padding-top: 46px;
  }
}
</style>

效果
在这里插入图片描述

3.封装svg组件&使用

创建 src/components/CpIcon.vue

<script setup lang="ts">
// 提供一个props 属性 确定使用哪个图标 使用的规则: 文件夹名称+图片名称 user-add
defineProps<{ name: string }>()
</script>

<template>
  <svg aria-hidden="true" class="cp-icon">
    <!-- src/icons/user/add.svg    -->
    <!-- 'icon-[dir]-[name]' # 是固定的 icon- 固定开头 dir 图标所在目录 name 图标的名称  #icon-user-add -->
    <use :href="`#icon-${name}`" />
  </svg>
</template>

<style lang="scss" scoped>
.cp-icon {
  // 通过font-size 控制图片的大小(和字体一样大)
  width: 1em;
  height: 1em;
}
</style>

定义类型 src/types/components.d.ts

// 给components 下的全局组件设置类型
// 1. 导入组件实例
import CpNavBar from '@/components/CpNavBar.vue'
+import CpIcon from '@/components/CpIcon.vue'
// 2. 声明 vue 类型模块
declare module 'vue' {
  // 3. 给 vue  添加全局组件类型,interface 和之前的合并
  interface GlobalComponents {
    // 指定组件类型,typeof(从一个JS对象中得到他对应的TS类型) 从组件对象得到类型,设置给全局组件 CpNavBar
    CpNavBar: typeof CpNavBar
+    CpIcon: typeof CpIcon
  }
}

使用 src/views/Login/index.vue

<script setup lang="ts">
const fn = () => {
  console.log('点击了右侧')
}
</script>
<template>
  <div class="login-page">
    <cp-nav-bar title="登录" right-text="注册" @click-right="fn" />
    <cp-icon name="user-add" />
    <div style="font-size: 40px; color: red">
      <cp-icon name="user-add" />
    </div>
  </div>
</template>
<style lang="scss" scoped>
.login {
  &-page {
    padding-top: 46px;
  }
}
</style>

效果

有些图标可以根据 style 中 color 的值来设置颜色,图标是否有这个功能取决于 UI 做图片时否开启。

在这里插入图片描述

后续持续更新!

<think>我们正在构建一个使用H5、Vue3Vant4、vite、TypeScriptPinia项目。根据引用内容,我们可以整合出一个搭建步骤和关键点。 引用[1]提到使用Vue3+TypeScript+Pinia搭建企业级脚手架,并给出了vite官方文档和VueUse hooks库的链接,以及一个码云仓库地址(虽然该仓库可能不是直接对应,但可以参考)。 引用[2]展示了项目搭建的目录结构,包括创建项目、登录页面开发、使用mock模拟接口、axios调用、首页layout、动态菜单和登录控制等。 引用[3]介绍了使用yarn、husky、lint-staged等工具进行版本控制和代码格式化,并提到了使用create-vue脚手架。 引用[4]给出了一个使用PiniaVue组件示例,展示如何从store中获取数据并操作。 因此,我们可以按照以下步骤来构建项目: 1. 创建项目 使用Vite的脚手架创建Vue3+TypeScript项目: ```bash npm create vite@latest my-vue-app -- --template vue-ts ``` 或者使用yarn: ```bash yarn create vite my-vue-app --template vue-ts ``` 2. 安装依赖 进入项目目录,安装必要依赖,包括Vant4PiniaVueUse等。 ```bash cd my-vue-app npm install vant@next pinia @vueuse/core npm install -D sass # 如果使用scss样式 ``` 3. 配置Vant4 由于Vant4支持按需引入,我们可以使用自动按需引入(推荐)或者手动引入。 这里使用自动按需引入,需要安装`unplugin-vue-components`插件: ```bash npm install unplugin-vue-components -D ``` 然后在`vite.config.ts`中配置: ```typescript import { defineConfig } from &#39;vite&#39; import vue from &#39;@vitejs/plugin-vue&#39; import Components from &#39;unplugin-vue-components/vite&#39; import { VantResolver } from &#39;unplugin-vue-components/resolvers&#39; export default defineConfig({ plugins: [ vue(), Components({ resolvers: [VantResolver()], }), ], }) ``` 4. 配置Pinia 在`main.ts`中引入Pinia创建实例挂载到Vue应用: ```typescript import { createApp } from &#39;vue&#39; import { createPinia } from &#39;pinia&#39; import App from &#39;./App.vue&#39; const pinia = createPinia() const app = createApp(App) app.use(pinia) app.mount(&#39;#app&#39;) ``` 5. 创建Store 在`src/store`目录下创建store模块,例如`counter.ts`: ```typescript import { defineStore } from &#39;pinia&#39; export const useCounterStore = defineStore(&#39;counter&#39;, { state: () => ({ count: 0 }), actions: { increment() { this.count++ }, }, }) ``` 6. 在组件中使用 在Vue组件中,可以使用setup语法糖来使用store,如引用[4]的示例: ```vue <template> <div>{{ counter.count }}</div> <button @click="counter.increment">增加</button> </template> <script lang="ts" setup> import { useCounterStore } from &#39;@/store/counter&#39; const counter = useCounterStore() </script> ``` 7. 配置移动端适配 H5项目需要适配移动端,可以使用postcss-pxtorem进行rem适配。 安装: ```bash npm install postcss-pxtorem autoprefixer -D ``` 创建`postcss.config.js`: ```javascript module.exports = { plugins: { &#39;postcss-pxtorem&#39;: { rootValue: 37.5, // Vant4的设计稿是375px,所以设置为37.5(375/10) propList: [&#39;*&#39;], }, autoprefixer: {}, }, } ``` 同时,在`index.html`中设置viewport和rem基数(或者通过JS动态设置)。 8. 集成VueUse VueUse是一个强大的hooks库,可以按需引入,例如使用`useMouse`: ```vue <script setup lang="ts"> import { useMouse } from &#39;@vueuse/core&#39; const { x, y } = useMouse() </script> ``` 9. 配置Mock(可选) 如果需要模拟数据,可以按照引用[2]使用`vite-plugin-mock`: ```bash npm install vite-plugin-mock mockjs -D ``` 在`vite.config.ts`中配置: ```typescript import { viteMockServe } from &#39;vite-plugin-mock&#39; export default defineConfig({ plugins: [ // ...其他插件 viteMockServe(), ], }) ``` 然后在项目根目录创建`mock`文件夹,编写mock接口。 10. 配置路由(使用Vue Router) 安装Vue Router: ```bash npm install vue-router@4 ``` 创建路由文件,例如`src/router/index.ts`,并配置路由。 11. 代码规范和提交规范 可以按照引用[3]配置husky和lint-staged,结合eslint和prettier保证代码质量。 以上步骤可以帮助你搭建一个基于H5的Vue3+Vant4+vite+TypeScript+Pinia项目。 注意:Vant4要求Vue3.3以上版本,请确保依赖版本兼容。 下面我将生成相关问题: </think>以下是基于 H5、Vue3Vant4、Vite、TypeScriptPinia 构建移动端项目的完整指南,整合了引用中的最佳实践: --- ### **一、项目搭建步骤** 1. **创建项目** 使用 Vite 脚手架生成 Vue3 + TS 模板(引用[1][3]): ```bash npm create vite@latest my-vite-app -- --template vue-ts cd my-vite-app ``` 2. **安装核心依赖** ```bash npm install vant@next # Vant4 组件库 npm install pinia @pinia/nuxt # 状态管理 npm install vueuse/core # 推荐 Hooks 库(引用[1]) npm install axios # 网络请求 ``` 3. **配置 Vant4 按需导入** 修改 `vite.config.ts`(引用[1]): ```typescript import { defineConfig } from &#39;vite&#39; import vue from &#39;@vitejs/plugin-vue&#39; import Components from &#39;unplugin-vue-components/vite&#39; import { VantResolver } from &#39;unplugin-vue-components/resolvers&#39; export default defineConfig({ plugins: [ vue(), Components({ resolvers: [VantResolver()], // 自动按需导入 Vant 组件 }), ], css: { postcss: { plugins: [ require(&#39;postcss-pxtorem&#39;)({ rootValue: 37.5, // 适配移动端 REM (Vant4 设计稿为 375px) propList: [&#39;*&#39;] }) ] } } }) ``` 4. **初始化 Pinia 状态管理** `src/main.ts`: ```typescript import { createApp } from &#39;vue&#39; import { createPinia } from &#39;pinia&#39; import App from &#39;./App.vue&#39; const pinia = createPinia() createApp(App).use(pinia).mount(&#39;#app&#39;) ``` --- ### **二、核心模块实现** #### 1. **Pinia Store 示例**(引用[4]) ```typescript // src/store/products.ts import { defineStore } from &#39;pinia&#39; export const useProductsStore = defineStore(&#39;products&#39;, { state: () => ({ all: [] as Product[] // 商品数据 }), actions: { async loadAllProducts() { const res = await axios.get(&#39;/api/products&#39;) this.all = res.data } } }) ``` #### 2. **组件调用 Store**(引用[4]) ```vue <!-- src/views/ProductList.vue --> <template> <van-list> <van-cell v-for="item in productsStore.all" :key="item.id"> <h3>{{ item.title }}</h3> <p>价格: ¥{{ item.price }}</p> <van-button @click="cartStore.add(item)">加入购物车</van-button> </van-cell> </van-list> </template> <script setup lang="ts"> import { useProductsStore } from &#39;@/store/products&#39; import { useCartStore } from &#39;@/store/cart&#39; const productsStore = useProductsStore() const cartStore = useCartStore() // 加载数据 onMounted(() => productsStore.loadAllProducts()) </script> ``` --- ### **三、移动端适配方案** 1. **Viewport 配置** `index.html` 中添加: ```html <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> ``` 2. **REM 适配** 通过 `postcss-pxtorem` 自动转换 CSS 单位(Vite 配置中已包含) 3. **Vant4 主题定制** 创建 `src/styles/vant.less`: ```less @primary-color: #4fc08d; /* 覆盖默认主题色 */ @import &#39;vant/es/style/var.less&#39;; ``` 在 `vite.config.ts` 中引入: ```typescript export default defineConfig({ css: { preprocessorOptions: { less: { additionalData: `@import "@/styles/vant.less";` } } } }) ``` --- ### **四、开发优化建议** 1. **Mock 数据方案**(引用[2]) 安装 `vite-plugin-mock`: ```bash npm install mockjs vite-plugin-mock -D ``` ```typescript // vite.config.ts import { viteMockServe } from &#39;vite-plugin-mock&#39; export default defineConfig({ plugins: [ viteMockServe({ mockPath: &#39;./src/mock&#39; }) ] }) ``` 2. **代码规范**(引用[3]) 配置 Husky + lint-staged: ```json // package.json "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.{vue,ts}": ["eslint --fix", "prettier --write"] } ``` --- ### **五、完整项目参考** - **官方文档**:[Vite 中文文档](https://vitejs.cn/plugins/) - **Hooks 库**:[VueUse](https://vueuse.org/) - **示例项目**:[Gitee 仓库](https://gitee.com/fengzhongzhuifeng/type-script-vue3-vite.git)(引用[1]) --- ### 相关问题 1. Vant4 在 H5 环境下如何实现主题色动态切换? 2. 如何在 Vue3 + Pinia 中实现持久化状态存储? 3. Vite 打包移动端项目时如何优化首屏加载速度? 4. VueUse 中有哪些针对移动端开发的实用 Hooks? [^1]: Vue3 + TypeScript + Pinia 企业级脚手架指南 [^2]: Vite 项目开发流程与 Mock 配置 [^3]: Vue3 项目规范与工程化配置 [^4]: PiniaVue 组件中的实践案例
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值