Vue3實(shí)戰(zhàn)——項(xiàng)目搭建(二)

一包券、全家桶

vue3+vite
vue-router
pinia 狀態(tài)管理乐横、pinia-plugin-persist 數(shù)據(jù)存儲(chǔ)
axios 接口請(qǐng)求
postcss-px-to-viewport 移動(dòng)端適配
vant4 移動(dòng)端UI庫

二、開始

1俭正、創(chuàng)建項(xiàng)目 vue3_h5

yarn create vite vue3_h5 --template vue

2、風(fēng)格規(guī)范

組件名:單文件組件的文件名—單詞大寫開頭 (PascalCase)、橫線連接 (kebab-case)絮吵。
緊密耦合的組件名:子組件應(yīng)該以父組件名作為前綴命名。
Prop名:命名使用 camelCase锡足,在模板中使用 kebab-case波丰。
指令縮寫,用 : 表示 v-bind: 舶得,用 @ 表示 v-on:掰烟。
Props順序:依次指令、屬性和事件扩灯。
組件選項(xiàng)順序:

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

三媚赖、項(xiàng)目配置

1. postcss-px-to-viewport 移動(dòng)端適配

功能:將px單位轉(zhuǎn)換為視口單位的 (vw, vh, vmin, vmax) 的 PostCSS 插件。
postcss-px-to-viewport:插件文檔珠插。
vite postcss:Vite自身已經(jīng)集成PostCSS惧磺。
配置參考:在Vite中配置方法。

// vite.config.js文件
import postcsspxtoviewport from 'postcss-px-to-viewport'
css: {
    postcss: {
      plugins: [
        postcsspxtoviewport({
          unitToConvert: 'px', // 要轉(zhuǎn)化的單位
          viewportWidth: 375, // UI設(shè)計(jì)稿的寬度
          unitPrecision: 6, // 轉(zhuǎn)換后的精度捻撑,即小數(shù)點(diǎn)位數(shù)
          propList: ['*'], // 指定轉(zhuǎn)換的css屬性的單位磨隘,*代表全部css屬性的單位都進(jìn)行轉(zhuǎn)換
          viewportUnit: 'vw', // 指定需要轉(zhuǎn)換成的視窗單位,默認(rèn)vw
          fontViewportUnit: 'vw', // 指定字體需要轉(zhuǎn)換成的視窗單位顾患,默認(rèn)vw
          selectorBlackList: ['ignore-'], // 指定不轉(zhuǎn)換為視窗單位的類名番捂,
          minPixelValue: 1, // 默認(rèn)值1,小于或等于1px則不進(jìn)行轉(zhuǎn)換
          mediaQuery: true, // 是否在媒體查詢的css代碼中也進(jìn)行轉(zhuǎn)換江解,默認(rèn)false
          replace: true, // 是否轉(zhuǎn)換后直接更換屬性值
          // exclude: [/node_modules/], // 設(shè)置忽略文件设预,用正則做目錄名匹配
          exclude: [],
          landscape: false // 是否處理橫屏情況
        })
      ]
    }
  },

2. 配置別名、開發(fā)服務(wù)器配置

// 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, // 服務(wù)器端口
      open: true, // 服務(wù)器啟動(dòng)時(shí)自動(dòng)在瀏覽器中打開
      cors: true // 允許跨域
    },

3. 安裝UI庫-vant3

(1)安裝UI庫vant3 yarn add vant
(2)按需自動(dòng)導(dǎo)入U(xiǎn)I庫組件:見步驟【4】犁河。
(3)直接在模板中使用使用 Vant 組件
<van-button type="primary" /> Vant 中unplugin-vue-components 會(huì)解析模板并自動(dòng)注冊(cè)對(duì)應(yīng)的組件鳖枕。

說明:Vant中個(gè)別組件以函數(shù)的形式提供(Toast,Dialog桨螺,Notify 和 ImagePreview)栏豺,使用 unplugin-vue-components 插件來自動(dòng)引入組件樣式腕唧,則無法正確識(shí)別。

(4)函數(shù)形式組件,使用時(shí)需要在具體頁面引入使用骡尽。

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

  • 還需要引入組件的樣式成洗±ぜ欤【手動(dòng)引入绵载、插件】

    • A. 需要在公共模塊中,手動(dòng)引入組件的樣式煌张。
      import 'vant/es/toast/style';// Toast
      import 'vant/es/dialog/style';// Dialog
      
    • B. 插件vite-plugin-style-import配置自動(dòng)引入樣式:步驟【5】——【不推薦读处!】

4. unplugin-vue-components 按需自動(dòng)導(dǎo)入組件

插件文檔:https://github.com/antfu/unplugin-vue-components
功能:導(dǎo)入自定義組件、自動(dòng)導(dǎo)入U(xiǎn)I庫唱矛。
原理:插件會(huì)生成一個(gè)ui庫組件以及指令路徑components.d.ts文件罚舱。
自動(dòng)導(dǎo)入?yún)⒖迹?a target="_blank">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({
      // 指定組件位置井辜,默認(rèn)是src/components
      dirs: ['src/components'],
      // ui庫解析器,也可以自定義
      resolvers: [
        VantResolver(),
      ],
      // 配置文件生成位置
      dts: 'src/components.d.ts'
    })
  ],

5. vite-plugin-style-import 按需自動(dòng)導(dǎo)入樣式

vite-plugin-style-import:https://github.com/vbenjs/vite-plugin-style-import/blob/main/README.zh_CN.md
功能:按需導(dǎo)入組件庫樣式管闷。
警告:【不推薦粥脚!】vant組件樣式前后存在覆蓋問題。

安裝:yarn add vite-plugin-style-import -D
安裝consola:用于 Node.js 和瀏覽器的優(yōu)雅控制臺(tái)記錄器包个。

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

6. unplugin-auto-import 自動(dòng)導(dǎo)入vue3的hooks

功能:支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自動(dòng)引入刷允。
表現(xiàn):不需要引入import { ref, computed } from 'vue'
原理:安裝的時(shí)候會(huì)自動(dòng)生成auto-imports.d文件(默認(rèn)是在根目錄)。

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

7. pinia狀態(tài)管理

  1. 安裝pinia yarn add pinia
    pinia-plugin-persist:持久化存儲(chǔ)插件碧囊。參考

  2. 配置

// 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路由

  1. 安裝vue-router yarn add vue-router

  2. 配置

// 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網(wǎng)絡(luò)請(qǐng)求

  1. 安裝axios npm install axios

  2. 配置

import axios from 'axios';
import { showToast,showLoadingToast,closeToast  } from 'vant';

// 運(yùn)行時(shí)獲取環(huán)境變量糯而,使用import.meta.env
const { VITE_API_BASE_URL, VITE_BASE_URL, VITE_NODE_ENV } = import.meta.env
// 創(chuàng)建實(shí)例時(shí)配置默認(rèn)值
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'
  }
});

// 添加請(qǐng)求攔截器
instance.interceptors.request.use(
  (config) => {
    if(config.url.indexOf('&__act=export_string')>=0){
      config.headers['Content-Type'] = 'application/json';
    }
    // 不傳遞默認(rèn)開啟loading
    if (!config.hideLoading) {
      showLoadingToast({
        forbidClick: true,
      });
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  },
);

// 添加響應(yīng)攔截器
instance.interceptors.response.use(
  (response) => {
    closeToast();
    if(response.data.data == undefined){
      showToast('接口請(qǐng)求失敗天通,請(qǐng)稍后再試!');
    }
    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('請(qǐng)求超時(shí)!');
    }
    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 [網(wǎng)絡(luò)下載問題熄驼,未用到]

功能:組件內(nèi)顯示定義 name 屬性像寒,覆蓋推導(dǎo)出的文件名稱。
參考:https://juejin.cn/post/7142797517355221023

  1. 安裝 yarn add unplugin-vue-define-options -D

  2. 配置 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.編寫定義

// 默認(rèn)寫法
<script>
  export default {
    name: "MyComponent"
  }
</script>

<script setup lang="ts">
</script>

// 添加插件后
<script setup lang="ts">
defineOptions({
  name: "MyComponent"  
})
</script>

11. sass作為css預(yù)處理

  1. 安裝 yarn add sass -D
    Vite提供了對(duì) .scss 文件的內(nèi)置支持瓜贾,沒有必要安裝特定的 Vite 插件诺祸,但必須安裝預(yù)處理器依賴。

  2. 對(duì) variables祭芦、common.scss作全局引入筷笨。

// vite.config.ts
css: {
    preprocessorOptions: {
      // 引入公用的樣式
      scss: {
        additionalData: `@import "@/styles/common.scss";@import "@/styles/variable.scss";`,
      }
    }
  }
  1. 通過 <style lang="sass">自動(dòng)開啟。

12. autoprefixer 瀏覽器前綴處理插件

  1. 安裝
    yarn add autoprefixer

  2. 配置

// 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默認(rèn)打包后龟劲,js 和 css 是全部混在一起的奥秆,將 js 和 css 文件夾分離。

// vite.config.ts
build: {
      brotliSize: false,
      // 消除打包大小超過500kb警告
      chunkSizeWarningLimit: 2000,
      // 在生產(chǎn)環(huán)境移除console.log
      terserOptions: {
        compress: {
          drop_console: true,
          drop_debugger: true
        }
      },
      assetsDir: 'static/assets',
      // 靜態(tài)資源打包到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,否則打包固定文件名侮叮,會(huì)缺少樣式避矢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市囊榜,隨后出現(xiàn)的幾起案子审胸,更是在濱河造成了極大的恐慌,老刑警劉巖卸勺,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砂沛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡曙求,警方通過查閱死者的電腦和手機(jī)碍庵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門映企,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人静浴,你說我怎么就攤上這事堰氓。” “怎么了苹享?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵双絮,是天一觀的道長。 經(jīng)常有香客問我得问,道長囤攀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任宫纬,我火速辦了婚禮焚挠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哪怔。我一直安慰自己宣蔚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布认境。 她就那樣靜靜地躺著胚委,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叉信。 梳的紋絲不亂的頭發(fā)上亩冬,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音硼身,去河邊找鬼硅急。 笑死,一個(gè)胖子當(dāng)著我的面吹牛佳遂,可吹牛的內(nèi)容都是我干的营袜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼丑罪,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼荚板!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吩屹,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤跪另,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后煤搜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體免绿,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年擦盾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘲驾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淌哟。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖距淫,靈堂內(nèi)的尸體忽然破棺而出绞绒,到底是詐尸還是另有隱情,我是刑警寧澤榕暇,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布蓬衡,位于F島的核電站,受9級(jí)特大地震影響彤枢,放射性物質(zhì)發(fā)生泄漏狰晚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一缴啡、第九天 我趴在偏房一處隱蔽的房頂上張望壁晒。 院中可真熱鬧,春花似錦业栅、人聲如沸秒咐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽携取。三九已至,卻和暖如春帮孔,著一層夾襖步出監(jiān)牢的瞬間雷滋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國打工文兢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晤斩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓姆坚,卻偏偏與公主長得像澳泵,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兼呵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容