<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          分享一個(gè)剛碼的Vite-Vue3工程化模板項(xiàng)目

          共 8023字,需瀏覽 17分鐘

           ·

          2021-10-15 00:56

          開箱即用的Vite-Vue3工程化模板

          前言

          畢設(shè)采用技術(shù)棧Vue3,Vite,TypeScript,Node,開發(fā)過程中產(chǎn)出了一些其它的東西,預(yù)計(jì)會(huì)出一系列的文章進(jìn)行介紹

          體驗(yàn)?zāi)0?/span>

          • 模板倉庫地址
            • (TS版):https://github.com/ATQQ/vite-vue3-template
            • (JS版):https://github.com/ATQQ/vite-vue3-js-template 兩步到位

          本地引入

          #?方法一
          npx?degit?atqq/vite-vue3-template#main?my-project

          cd?my-project
          #?方法二
          git?clone?https://github.com/ATQQ/vite-vue3-template.git

          cd?vite-vue3-template

          啟動(dòng)

          #?安裝依賴
          yarn?install
          #?運(yùn)行
          yarn?dev

          模板介紹

          已包含特性

          • [x] vite
          • [x] vue3
          • [x] @vue/compiler-sfc
          • [x] TypeScript
          • [x] Vuex4.x
          • [x] Vue-Router4.x
          • [x] Axios
          • [x] Provide/inject
          • [x] polyfill.io
          • [x] Element UI Plus
          • [x] Sass
          • [x] Eslint
          • [x] Jest
          • [x] Tencent CloudBase static page
          • [x] Tencent CloudBase Github Action

          內(nèi)置了常見的工程化項(xiàng)目所用的內(nèi)容,后文只對(duì)其中的一些特性做簡(jiǎn)單介紹,展示部分示例代碼

          目錄介紹

          .
          ├──?__tests__
          ├──?dist????#?構(gòu)建結(jié)果
          ├──?public??#?公共靜態(tài)資源
          ├──?src?????#?源碼目錄
          │???├──?apis
          │???├──?assets
          │???├──?components
          │???├──?pages
          │???├──?router
          │???├──?store
          │???├──?@types
          │???├──?utils
          │???├──?shims-vue.d.ts
          │???├──?env.d.ts
          │???├──?main.ts
          │???└──?App.vue
          ├──?README.md
          ├──?index.html????#?應(yīng)用入口
          ├──?jest.config.ts
          ├──?LICENSE
          ├──?package.json
          ├──?tsconfig.json
          ├──?cloudbaserc.json??#?騰訊云CloudBase相關(guān)配置文件
          ├──?vite.config.ts??#?vite配置文件
          └──?yarn.lock

          Vite

          Vite有多牛牪犇,我就不贅述了

          一個(gè)簡(jiǎn)單的vite.config.ts配置文件

          import?{?defineConfig?}?from?'vite'
          import?vue?from?'@vitejs/plugin-vue'
          import?path?from?'path'

          //?https://vitejs.dev/config/
          export?default?defineConfig({
          ??plugins:?[
          ????vue(),
          ??],
          ??build:?{
          ????target:?'modules',?//?默認(rèn)值
          ????//?sourcemap:?true,
          ??},
          ??server:?{
          ????port:?8080,
          ????proxy:?{
          ??????'/api/':?{
          ????????target:?'http://localhost:3000',
          ????????changeOrigin:?true,
          ????????rewrite:?(p)?=>?p.replace(/^\/api/,?''),
          ??????},
          ??????'/api-prod/':?{
          ????????target:?'http://localhost:3001',
          ????????changeOrigin:?true,
          ????????rewrite:?(p)?=>?p.replace(/^\/api-prod/,?''),
          ??????},
          ????},
          ??},
          ??resolve:?{
          ????alias:?{
          ??????'@':?path.resolve(__dirname,?'./src'),
          ??????'@components':?path.resolve(__dirname,?'./src/components'),
          ????},
          ??},
          })

          @vue/compiler-sfc

          這個(gè)就是前段時(shí)間比較爭(zhēng)議的一個(gè)提案,不過真香,進(jìn)一步了解

          Vuex

          采用分業(yè)務(wù)模塊的方案

          目錄結(jié)構(gòu)

          src/store/
          ├──?index.ts
          └──?modules
          ????└──?module1.ts

          module1.ts

          import?{?Module?}?from?'vuex'

          interface?State?{
          ??count:?number
          }

          const?store:?Module?=?{
          ??namespaced:?true,
          ??state()?{
          ????return?{
          ??????count:?0,
          ????}
          ??},
          ??getters:?{
          ????isEven(state)?{
          ??????return?state.count?%?2?===?0
          ????},
          ??},
          ??//?只能同步
          ??mutations:?{
          ????increase(state,?num?=?1)?{
          ??????state.count?+=?num
          ????},
          ????decrease(state)?{
          ??????state.count?-=?1
          ????},
          ??},
          ??//?支持異步,可以考慮引入API
          ??actions:?{
          ????increase(context,?payload)?{
          ??????context.commit('increase',?payload)
          ??????setTimeout(()?=>?{
          ????????context.commit('decrease')
          ??????},?1000)
          ????},
          ??},
          }

          export?default?store

          index.ts

          import?{?createStore?}?from?'vuex'
          import?module1?from?'./modules/module1'

          //?Create?a?new?store?instance.
          const?store?=?createStore({
          ??modules:?{
          ????m1:?module1,
          ??},
          })

          export?default?store

          main.ts中引入

          import?store?from?'./store'
          app.use(store)

          視圖中調(diào)用

          import?{?computed?}?from?'vue'
          import?{?useStore?}?from?'vuex'

          const?store?=?useStore()

          //?state
          const?count?=?computed(()?=>?store.state.m1.count)
          //?getters
          const?isEven?=?computed(()?=>?store.getters['m1/isEven'])
          //?mutations
          const?add?=?()?=>?store.commit('m1/increase')
          //?actions
          const?asyncAdd?=?()?=>?store.dispatch('m1/increase')

          Vue-Router

          目錄結(jié)構(gòu)

          src/router/
          ├──?index.ts
          ├──?Interceptor
          │???└──?index.ts
          └──?routes
          ????└──?index.ts

          攔截器與頁面路由相分離

          Interceptor/index.ts

          import?{?Router?}?from?'vue-router'

          declare?module?'vue-router'?{
          ????interface?RouteMeta?{
          ????????//?是可選的
          ????????isAdmin?:?boolean
          ????????//?是否需要登錄
          ????????requireLogin?:?boolean
          ????}
          }

          function?registerRouteGuard(router:?Router)?{
          ??/**
          ?????*?全局前置守衛(wèi)
          ?????*/

          ??router.beforeEach((to,?from)?=>?{
          ????if?(to.meta.requireLogin)?{
          ??????if?(from.path?===?'/')?{
          ????????return?from
          ??????}
          ??????return?false
          ????}
          ????return?true
          ??})

          ??/**
          ?????*?全局解析守衛(wèi)
          ?????*/

          ??router.beforeResolve(async?(to)?=>?{
          ????if?(to.meta.isAdmin)?{
          ??????try?{
          ????????console.log(to)
          ??????}?catch?(error)?{
          ????????//?if?(error?instanceof?NotAllowedError)?{
          ????????//?????//?...?處理錯(cuò)誤,然后取消導(dǎo)航
          ????????//?????return?false
          ????????//?}?else?{
          ????????//?????//?意料之外的錯(cuò)誤,取消導(dǎo)航并把錯(cuò)誤傳給全局處理器
          ????????//?????throw?error
          ????????//?}
          ????????console.error(error)
          ??????}
          ????}
          ??})

          ??/**
          ?????*?全局后置守衛(wèi)
          ?????*/

          ??router.afterEach((to,?from,?failure)?=>?{
          ????//?改標(biāo)題,監(jiān)控上報(bào)一些基礎(chǔ)信息
          ????//?sendToAnalytics(to.fullPath)
          ????if?(failure)?{
          ??????console.error(failure)
          ????}
          ??})
          }

          export?default?registerRouteGuard

          routes/index.ts

          import?{?RouteRecordRaw?}?from?'vue-router'
          import?Home?from?'../../pages/home/index.vue'
          import?About?from?'../../pages/about/index.vue'
          import?Dynamic?from?'../../pages/dynamic/index.vue'

          const?NotFind?=?()?=>?import('../../pages/404/index.vue')
          const?Index?=?()?=>?import('../../pages/index/index.vue')
          const?Axios?=?()?=>?import('../../pages/axios/index.vue')
          const?Element?=?()?=>?import('../../pages/element/index.vue')
          const?routes:?RouteRecordRaw[]?=?[
          ??{?path:?'/:pathMatch(.*)*',?name:?'NotFound',?component:?NotFind?},
          ??{
          ????path:?'/',
          ????name:?'index',
          ????component:?Index,
          ????children:?[
          ??????{?path:?'home',?component:?Home,?name:?'home'?},
          ??????{?path:?'about',?component:?About,?name:?'about'?},
          ??????{?path:?'axios',?component:?Axios,?name:?'axios'?},
          ??????{?path:?'element',?component:?Element,?name:?'element'?},
          ??????{
          ????????path:?'dynamic/:id',
          ????????component:?Dynamic,
          ????????meta:?{
          ??????????requireLogin:?false,
          ??????????isAdmin:?true,
          ????????},
          ????????name:?'dynamic',
          ??????},
          ????],
          ??},
          ]

          export?default?routes

          router/index.ts

          import?{?createRouter,?createWebHistory?}?from?'vue-router'
          import?registerRouteGuard?from?'./Interceptor'
          import?routes?from?'./routes'

          const?router?=?createRouter({
          ??history:?createWebHistory(import.meta.env.VITE_ROUTER_BASE?as?string),
          ??routes,
          })

          //?注冊(cè)路由守衛(wèi)
          registerRouteGuard(router)

          export?default?router

          main.ts中引入

          import?router?from?'./router'
          app.use(router)

          Axios

          對(duì)axios的簡(jiǎn)單包裝

          ajax.ts

          import?axios?from?'axios'

          const?instance?=?axios.create({
          ??baseURL:?import.meta.env.VITE_APP_AXIOS_BASE_URL,
          })

          /**
          ?*?請(qǐng)求攔截
          ?*/

          instance.interceptors.request.use((config)?=>?{
          ??const?{?method,?params?}?=?config
          ??//?附帶鑒權(quán)的token
          ??const?headers:?any?=?{
          ????token:?localStorage.getItem('token'),
          ??}
          ??//?不緩存get請(qǐng)求
          ??if?(method?===?'get')?{
          ????headers['Cache-Control']?=?'no-cache'
          ??}
          ??//?delete請(qǐng)求參數(shù)放入body中
          ??if?(method?===?'delete')?{
          ????headers['Content-type']?=?'application/json;'
          ????Object.assign(config,?{
          ??????data:?params,
          ??????params:?{},
          ????})
          ??}

          ??return?({
          ????...config,
          ????headers,
          ??})
          })

          /**
          ?*?響應(yīng)攔截
          ?*/

          instance.interceptors.response.use((v)?=>?{
          ??if?(v.data?.code?===?401)?{
          ????localStorage.removeItem('token')
          ????// alert('即將跳轉(zhuǎn)登錄頁。。。', '登錄過期')
          ????//?setTimeout(redirectHome,?1500)
          ????return?v.data
          ??}
          ??if?(v.status?===?200)?{
          ????return?v.data
          ??}
          ??//?alert(v.statusText,?'網(wǎng)絡(luò)錯(cuò)誤')
          ??return?Promise.reject(v)
          })
          export?default?instance

          api目錄結(jié)構(gòu)

          src/apis/
          ├──?ajax.ts
          ├──?index.ts
          └──?modules
          ????└──?public.ts

          分業(yè)務(wù)模塊編寫接口調(diào)用方法,通過apis/index.ts對(duì)外統(tǒng)一導(dǎo)出

          export?{?default?as?publicApi?}?from?'./modules/public'

          注入全局的Axios實(shí)例,Vue2中通常是往原型(prototype)上掛載相關(guān)方法,在Vue3中由于使用CreateApp創(chuàng)建實(shí)例,所以推薦使用provide/inject 來傳遞一些全局的實(shí)例或者方法

          main.ts

          import?Axios?from?'./apis/ajax'

          const?app?=?createApp(App)

          app.provide('$http',?Axios)

          視圖中使用

          import?{?inject?}?from?'vue'

          const?$http?=?inject('$http')

          polyfill.io

          部分瀏覽器可能對(duì)ES的新語法支持程度不一致,存在一定的兼容問題,此時(shí)就需要使用polyfill(墊片)

          polyfill.io是一個(gè)墊片服務(wù),直接通過cdn按需引入墊片,不影響包體積

          工作原理是通過解析客戶端的UA信息,然后根據(jù)查詢參數(shù),判斷是否需要墊片,不需要?jiǎng)t不下發(fā)

          簡(jiǎn)單使用

          html>
          <html?lang="en">

          <head>
          ??<meta?charset="UTF-8"?/>
          ??<link?rel="icon"?href="/favicon.ico"?/>
          ??<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
          ??<title>Vite?Apptitle>
          ??<script
          ????src="https://polyfill.alicdn.com/polyfill.min.js?features=es2019%2Ces2018%2Ces2017%2Ces5%2Ces6%2Ces7%2Cdefault">
          script>
          head>

          <body>
          ??<div?id="app">div>
          ??<script?type="module"?src="/src/main.ts">script>
          body>

          html>

          查詢參數(shù)在線生成->url-builder

          由于官方服務(wù)是部署在非大陸,所以延遲較高,由于polyfill-service是開源的,所以可以自己進(jìn)行搭建

          國內(nèi)大廠也有一些鏡像:

          • https://polyfill.alicdn.com/polyfill.min.js
          • https://polyfill.meituan.com/polyfill.min.js

          element UI Plus

          Vue3版本的Element UI 組件庫,雖然有些坑,但勉強(qiáng)能用 O(∩_∩)O哈哈~

          按需引入在使用過程中發(fā)現(xiàn)Dev和Prod環(huán)境下的樣式表現(xiàn)有差異,固采用全量引入的方式

          utils/elementUI.ts

          import?{?App?}?from?'@vue/runtime-core'

          //?全量引入
          import?ElementPlus?from?'element-plus'
          import?'element-plus/lib/theme-chalk/index.css'
          import?'dayjs/locale/zh-cn'
          import?locale?from?'element-plus/lib/locale/lang/zh-cn'

          export?default?function?mountElementUI(app:?App)?{
          ??app.use(ElementPlus,?{?locale?})
          }

          main.ts

          import?mountElementUI?from?'./utils/elementUI'

          mountElementUI(app)


          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  影音先锋在线亚洲av | 毛片毛片女人毛片毛片 | 成人午夜剧场视频网站 | 青娱乐99 | 午夜成人性 |