vue3 + vite + TS + vue-router + vuex + less + 組合式API + 多語言vue-i18n
vue3安裝
安裝最新穩(wěn)定版
$ npm install vue@next
用vite創(chuàng)建項目
vite不需要單獨安裝
npm init vite-app my_project
cd my_project
npm install
npm run dev
// 瀏覽器中打開localhost:3000,即可看到啟動的項目
TypeScript配置
vue3+vite+ts在配置過程中會報錯买乃,找不到App.vue模塊相應的類型聲明剪验,等配置完成即可解決功戚。
- /src/main.js啸臀,重命名為/src/main.ts
- /src/index.html烁落,引入的main.js伤塌,改成main.ts
- /src/App.vue每聪,<script> 修改為 <script lang="ts">
- 安裝TypeScript
$ npm install -D typescript
根目錄創(chuàng)建ts配置文件:tsconfig.json齿风,并修改配置為
{
"compilerOptions": {
// TypeScript 默認會把代碼編譯為 ECMAScript 3
// esnext 表示僅僅校驗轉換 TypeScript 類型,不進行語法編譯
"target": "esnext",
"module": "esnext",
// 開啟嚴格模式真屯,這使得對“this”的數(shù)據(jù)屬性進行更嚴格的推斷成為可能
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"paths": {
"/@/*": [
"./src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"src/types/images.d.ts",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
- 添加類型聲明文件
用來解決前面所說的報錯
創(chuàng)建文件:/src/shims-vue.d.ts讨跟,并修改配置
// /src/shims-vue.d.ts
declare module '*.vue' {
// Vue 3
import { defineComponent } from 'vue'
const Component: ReturnType<typeof defineComponent>
export default Component
}
6 build時添加tsc校驗
/package.json茶袒,修改scripts.build的值為tsc --noEmit && vite build
"build": "tsc --noEmit && vite build"
ts配置完成
路徑別名設置
根目錄vite配置文件,
// vite.config.js
import {resolve} from "path";
export default {
alias: {
'/@/': resolve(__dirname, 'src'),
'/@styles/': resolve(__dirname, 'src/assets/styles'),
'/@components/': resolve(__dirname, 'src/components'),
'/@pages/': resolve(__dirname, 'src/pages'),
'/@store/': resolve(__dirname, 'src/store'),
},
};
// tsconfig.json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es5",
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
"module": "commonjs",
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true,
/* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./",
/* Base directory to resolve non-absolute module names. */
"paths": {
"/@/*": [
"src/*"
],
"/@styles/*": [
"src/assets/styles/*"
],
"/@pages/*": [
"src/pages/*"
],
"/@components/*": [
"src/components/*"
],
"/@store/*": [
"src/store/*"
]
},
/* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true,
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true,
/* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true
/* Disallow inconsistently-cased references to the same file. */
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"src/**/*.less"
],
"exclude": [
"node_modules"
]
}
路由配置vue-router
采用模塊化路由配置
- 安裝路由
npm install vue-router@4
- 創(chuàng)建頁面目錄pages與頁面文件a.vue嗦董,b.vue
script中加入lang='ts'
// a.vue
<template>
<div>page-a</div>
</template>
<script lang="ts">
export default {
name: "a"
}
</script>
<style scoped>
</style>
// b.vue
<template>
<div>page-a</div>
</template>
<script lang="ts">
export default {
name: "b"
}
</script>
<style scoped>
</style>
- 創(chuàng)建路由文件/router.ts
import {createRouter, createWebHistory} from "vue-router";
// 懶加載:component的值是函數(shù)
const routes = [
{path: '/', component: () => import('./pages/a.vue')},
{path: '/b', component: () => import('./pages/b.vue')}
]
const router = createRouter({
history: createWebHistory(),
routes,
// 切換頁面后奇唤,返回頂部
scrollBehavior() {
return {top: 0}
}
});
// 權限檢查
function canUserAccess(){
return new Promise(resolve => {
return resolve(true)
})
}
router.beforeEach(async (to, from,next) => {
// 獲取菜單咬扇、用戶信息廊勃、調用store等異步操作
// 檢查權限,true繼續(xù)梭灿,false進入登錄
let isAllow = await canUserAccess()
isAllow ? next() : next({name:'login'})
})
export default router;
- 掛載到vue
修改/main.ts
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
import './index.css'
const app = createApp(App);
app.use(router)
app.mount('#app')
狀態(tài)管理器配置vuex
- 安裝
npm install vuex@next
- 創(chuàng)建文件
- /src/store/index.ts
*/src/store/modules/users.store.ts
````js
// /src/store/index.ts
import {createStore, useStore as baseUseStore, Store} from "vuex";
import {InjectionKey} from 'vue'
export interface State {
count: number,
name: string
}
export const key: InjectionKey<Store<State>> = Symbol();
const state = {
count: 0,
name: 'cq'
}
const getters = {
name1(state: State) {
return state.name
}
}
const mutations = {
increase(state:State){
state.count++
}
}
const actions = {
// @ts-ignore
add({commit}){
commit('increase');
}
}
export const store = createStore<State>({
state,
getters,
mutations,
actions,
})
export function useStore() {
return baseUseStore(key)
}
// /src/store/modules/users.store.ts
interface IState {}
const state:IState = {}
const getters = {}
const mutations = {}
const actions = {}
export default {
state,
getters,
mutations,
actions
}
- 修改main
import { createApp } from 'vue'
import router from './router'
import {store,key} from './store/index'
import App from './App.vue'
import './index.css'
const app = createApp(App);
app.use(router)
app.use(store,key)
app.mount('#app')
Less
- 安裝
npm install less less-loader --dev
- style標簽加入lang=less
<style lang='less'></style>
未解決的問題:
同一個文件使用@import導入兩個文件,第二個失效
多語言vue-i18n
1. 安裝
npm install vue-i18n@next
2. 創(chuàng)建目錄涕蚤、文件
- /src/language/zh.language/index.ts
中文語言包的輸出文件
- /src/language/zh.language/modules/home-page.language.ts
將內容通過模塊劃分万栅,一個模塊一個文件
- /src/language/en.language/index.ts
- /src/language/en.language/modules/home-page.language.ts
- /src/language/index.ts
整個語言包的輸出文件
// /src/language/zh.language/index.ts
import home_page from './modules/home-page.language'
export default {
example: '語言包示例',
home_page
}
// /src/language/zh.language/modules/home-page.language.ts
export default {
title:'首頁',
// 一個component一個對象
navs:{
list:[],
name:'nav list'
},
}
// /src/language/zh.language/modules/home-page.language.ts
import home_page from './modules/home-page.language'
export default {
example: 'language package example',
home_page
}
// /src/language/en.language/modules/home-page.language.ts
export default {
title:'home page',
navs:{
list:[],
name:'nav list'
}
}
// /src/language/index.ts
import {createI18n} from "vue-i18n";
import zh from './zh.language/index'
import en from './en.language/index'
const messages = {zh, en}
// 判斷當前瀏覽器是哪種語言
const language = (
(navigator.language
? navigator.language
// @ts-ignore
: navigator.userLanguage)
|| 'zh'
).toLowerCase();
const i18n = createI18n({
fallbackLocale: 'zh',
globalInjection: true,
legacy: false,
locale: language.split("-")[0] || 'zh',
messages
})
export default i18n;
3. 引入vue
在mian.ts中引入語言包
import i18n from "/@/language/index";
app.use(i18n);
4. vue頁面中使用
<div>
{{$t(`example`)}}
{{$t(`home_page.title`)}}
</div>
多語言配置完成