精彩文章免费看

Vue3实战——项目搭建(二)

一、全家桶

vue3+ vite
vue-router
pinia 状态管理、pinia-plugin-persist 数据存储
axios 接口请求
postcss-px-to-viewport 移动端适配
vant4 移动端UI库

1、创建项目 vue3_h5

yarn create vite vue3_h5 --template vue

2、风格规范

组件名:单文件组件的文件名—单词大写开头 (PascalCase)、横线连接 (kebab-case)。
紧密耦合的组件名:子组件应该以父组件名作为前缀命名。
Prop名:命名使用 camelCase,在模板中使用 kebab-case。
指令缩写,用 : 表示 v-bind: ,用 @ 表示 v-on:
Props顺序:依次指令、属性和事件。
组件选项顺序:

export default {
  name: '',
  components: {},
  props: {},
  data() {},
  computed: {},
  watch: {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {},

三、项目配置

1. postcss-px-to-viewport 移动端适配

功能:将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件。
postcss-px-to-viewport:插件文档。
vite postcss:Vite自身已经集成PostCSS。
配置参考:在Vite中配置方法。

// vite.config.js文件
import postcsspxtoviewport from 'postcss-px-to-viewport'
css: {
    postcss: {
      plugins: [
        postcsspxtoviewport({
          unitToConvert: 'px', // 要转化的单位
          viewportWidth: 375, // UI设计稿的宽度
          unitPrecision: 6, // 转换后的精度,即小数点位数
          propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
          viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
          fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
          selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名,
          minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
          mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
          replace: true, // 是否转换后直接更换属性值
          // exclude: [/node_modules/], // 设置忽略文件,用正则做目录名匹配
          exclude: [],
          landscape: false // 是否处理横屏情况

2. 配置别名、开发服务器配置

// vite.config.js文件
import { resolve } from 'path';
import postcsspxtoviewport from 'postcss-px-to-viewport'
  resolve:{
    alias:{
      '@':resolve('./src')
  server:{
      proxy: {
        [VITE_API_BASE_URL]: {
          target: VITE_BASE_URL,
          changeOrigin: true,
          rewrite: (path) => {
            return path.replace('/api/', '/');
      port:8000, // 服务器端口
      open: true, // 服务器启动时自动在浏览器中打开
      cors: true // 允许跨域

3. 安装UI库-vant3

(1)安装UI库vant3 yarn add vant
(2)按需自动导入UI库组件:见步骤【4】。
(3)直接在模板中使用使用 Vant 组件
<van-button type="primary" /> Vant 中unplugin-vue-components 会解析模板并自动注册对应的组件。

说明:Vant中个别组件以函数的形式提供(Toast,Dialog,Notify 和 ImagePreview),使用 unplugin-vue-components 插件来自动引入组件样式,则无法正确识别。

(4)函数形式组件,使用时需要在具体页面引入使用。

  • 引入组件:import { Toast,Dialog } from 'vant';

  • 还需要引入组件的样式。【手动引入、插件】

  • A. 需要在公共模块中,手动引入组件的样式。
    import 'vant/es/toast/style';// Toast
    import 'vant/es/dialog/style';// Dialog
    
  • B. 插件vite-plugin-style-import配置自动引入样式:步骤【5】——【不推荐!】
  • 4. unplugin-vue-components 按需自动导入组件

    插件文档:https://github.com/antfu/unplugin-vue-components
    功能:导入自定义组件、自动导入UI库。
    原理:插件会生成一个ui库组件以及指令路径components.d.ts文件。
    自动导入参考:https://juejin.cn/post/7012446423367024676#heading-8

    安装:yarn add unplugin-vue-components -D

    // vite.config.js文件
    import Components from 'unplugin-vue-components/vite'
    import {VantResolver} from 'unplugin-vue-components/resolvers'
      plugins: [
        Components({
          // 指定组件位置,默认是src/components
          dirs: ['src/components'],
          // ui库解析器,也可以自定义
          resolvers: [
            VantResolver(),
          // 配置文件生成位置
          dts: 'src/components.d.ts'
    

    5. vite-plugin-style-import 按需自动导入样式

    vite-plugin-style-import:https://github.com/vbenjs/vite-plugin-style-import/blob/main/README.zh_CN.md
    功能:按需导入组件库样式。
    警告:【不推荐!】vant组件样式前后存在覆盖问题。

    安装:yarn add vite-plugin-style-import -D
    安装consola:用于 Node.js 和浏览器的优雅控制台记录器。

    import {createStyleImportPlugin, VantResolve} from 'vite-plugin-style-import'
    // vite.config.js文件
    createStyleImportPlugin({
          resolves: [
            VantResolve(),
          // 自定义规则
          libs: [
              libraryName: 'vant',
              esModule: true,
              resolveStyle: (name) => {
                return `../es/${name}/style/index`
    

    6. unplugin-auto-import 自动导入vue3的hooks

    功能:支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入。
    表现:不需要引入import { ref, computed } from 'vue'
    原理:安装的时候会自动生成auto-imports.d文件(默认是在根目录)。

    // vite.config.js文件
    import AutoImport from 'unplugin-auto-import/vite';
    AutoImport({
          dts: 'src/auto-imports.d.ts',
          imports: [
            'vue',
            'pinia',
            'vue-router',
    

    7. pinia状态管理

  • 安装pinia yarn add pinia
    pinia-plugin-persist:持久化存储插件。参考

  • // store/index.js
    import { createPinia } from 'pinia'
    import piniaPersist from 'pinia-plugin-persist'
    const store = createPinia()
    store.use(piniaPersist)
    export default store
    // main.js
    import store from './store'
    app.use(store)
    

    8. vue-router路由

  • 安装vue-router yarn add vue-router

  • // router/index.js
    import { createRouter, createWebHashHistory } from 'vue-router';
    const routes = [
        path: '/',
        redirect: '/home',
        component: () => import('@/views/home/index.vue'),
        name: 'home',
        path: '/home',
        component: () => import('@/views/home/index.vue'),
          name: 'detail',
          path: '/detail',
          component: () => import('@/views/detail/index.vue'),
    const router = createRouter({
      history: createWebHashHistory('/'),
      routes: routes,
    export default router;
    // main.js
    import router from './router/index'
    app.use(router)
    

    注意:使用createWebHashHistory模式,在浏览器访问链接才能找到正确路径。

    9. axios网络请求

  • 安装axios npm install axios

  • import axios from 'axios';
    import { showToast,showLoadingToast,closeToast  } from 'vant';
    // 运行时获取环境变量,使用import.meta.env
    const { VITE_API_BASE_URL, VITE_BASE_URL, VITE_NODE_ENV } = import.meta.env
    // 创建实例时配置默认值
    const instance = axios.create({
      baseURL: VITE_NODE_ENV === 'production' ? VITE_BASE_URL : VITE_API_BASE_URL,
      withCredentials: true,
      timeout: 5000,
      headers:{
        'Content-Type': 'application/x-www-form-urlencoded'
    // 添加请求拦截器
    instance.interceptors.request.use(
      (config) => {
        if(config.url.indexOf('&__act=export_string')>=0){
          config.headers['Content-Type'] = 'application/json';
        // 不传递默认开启loading
        if (!config.hideLoading) {
          showLoadingToast({
            forbidClick: true,
        return config;
      (error) => {
        return Promise.reject(error);
    // 添加响应拦截器
    instance.interceptors.response.use(
      (response) => {
        closeToast();
        if(response.data.data == undefined){
          showToast('接口请求失败,请稍后再试!');
        const res = response.data.data[0];
        if (res.code !== 200) {
          showToast(res.errmsg);
          return Promise.reject(res.errmsg || 'Error');
        } else {
          return Promise.resolve(response);
      (error) => {
        if (error.message?.includes('timeout')) {
          showToast('请求超时!');
        return Promise.reject(error.message);
    const request = (config)=> {
      return new Promise((resolve, reject) => {
        instance
          .request(config)
          .then((res) => resolve(res.data))
          .catch((err) => reject(err));
    export default request;
    

    10. unplugin-vue-define-options [网络下载问题,未用到]

    功能:组件内显示定义 name 属性,覆盖推导出的文件名称。
    参考:https://juejin.cn/post/7142797517355221023

  • 安装 yarn add unplugin-vue-define-options -D

  • 配置 vite

  • // vite.config.ts
    import DefineOptions from 'unplugin-vue-define-options/vite'
    import Vue from '@vitejs/plugin-vue'
    export default defineConfig({
      plugins: [Vue(), DefineOptions()],
    

    3.编写定义

    // 默认写法
    <script>
      export default {
        name: "MyComponent"
    </script>
    <script setup lang="ts">
    </script>
    // 添加插件后
    <script setup lang="ts">
    defineOptions({
      name: "MyComponent"  
    </script>
    

    11. sass作为css预处理

  • 安装 yarn add sass -D
    Vite提供了对 .scss 文件的内置支持,没有必要安装特定的 Vite 插件,但必须安装预处理器依赖。

  • 对 variables、common.scss作全局引入。

  • // vite.config.ts
    css: {
        preprocessorOptions: {
          // 引入公用的样式
          scss: {
            additionalData: `@import "@/styles/common.scss";@import "@/styles/variable.scss";`,
    
  • 通过 <style lang="sass">自动开启。
  • 12. autoprefixer 浏览器前缀处理插件

    yarn add autoprefixer

  • // vite.config.ts
    import autoprefixer from 'autoprefixer'
    css: {
        postcss: {
          plugins: [
            autoprefixer({
              overrideBrowserslist:[
                "Android > 4.1",
                "iOS >= 7.1",
                'Chrome > 31',
                "ff >= 31",
                'ie>= 8',
              grid:true
    

    13. 打包文件夹分离

    vite默认打包后,js 和 css 是全部混在一起的,将 js 和 css 文件夹分离。

    // vite.config.ts
    build: {
          brotliSize: false,
          // 消除打包大小超过500kb警告
          chunkSizeWarningLimit: 2000,
          // 在生产环境移除console.log
          terserOptions: {
            compress: {
              drop_console: true,
              drop_debugger: true
          assetsDir: 'static/assets',
          // 静态资源打包到dist下的不同目录
          rollupOptions: {
            output: {
              chunkFileNames: 'static/js/[name]-[hash].js',
              entryFileNames: 'static/js/[name]-[hash].js',
              assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
    

    注意:组件xx.vue需要使用不同name命名,不可都用xx/index.vue,否则打包固定文件名,会缺少样式。

    最后编辑于:2022-12-08 17:48