創(chuàng)建項目
npm create vite@latest
Vue-router
安裝vue-router
npm i vue-router@4
使用vue-router
// 定義路由文件 src/router/index.js
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
name: 'home',
component: () => import('views/home/index.vue')
},
// 通配符改為正則匹配模式
{
path: '/:pathMatch(.*)*',
redirect: '/',
name: 'not found'
}
]
})
export default router;
// 在main.js中掛載router
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
Vuex
安裝vuex
npm i vuex@next --save
使用vuex
// 定義store文件 /src/store/index.js
// 定義拆分文件 states.js癞尚、actions.js、mutations.js、getters.js
import { createStore } from 'vuex'
import state from './state'
import action from './actions'
import mutations from './mutations'
import getters from './getters'
export const store = createStore({
state,
actions,
mutations,
getters
})
// 在main.js中掛載store
import { store } from './store'
createApp(App).use(router).use(store).mount('#app')
Pinia
安裝
npm i pinia -S
npm i pinia-plugin-persistedstate -S // 持久化插件
使用pinia
// 創(chuàng)建store /src/stores/main.js
import { defineStore } from 'pinia'
export const useMainStore = defineStore('main', {
state: () => {
return {
userInfo: {},
langState: 'zh'
}
},
actions: {
setUserInfo(userInfo) {
this.userInfo = userInfo
}
},
persist: {
key: 'userInfo', // 持久化key
storage: window.sessionStorage, // 持久化對象
paths: ['userInfo', 'langState'], // 需要持久化存儲的key
overwrite: true
}
})
// 在main.js中掛載pinia
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
// 創(chuàng)建pinia實例并使用持久化插件
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
createApp(App).use(pinia)
// 在組件中使用
import { useMainStore } from '@/stores/main'
setup() {
const mainStore = useMainStore()
// 可通過store實例對象直接訪問數(shù)據(jù)
console.log(mainStore.userInfo)
// 也可直接訪問actions
mainStore.setUserInfo({name: '張三'})
}
Element-Plus
安裝
npm i element-plus --save
導入樣式文件
**完整導入**
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 掛載組件庫時還可傳入全局配置對象
createApp(App).use(ElementPlus冯勉, { size: 'small', zIndex: 3000 })
**按需導入**村视,需要安裝額外的插件來導入要使用的組件
自動導入(推薦)
// 1来庭、安裝unplugin-vue-components 和 unplugin-auto-import
npm i -D unplugin-vue-components unplugin-auto-import
// 在 vite.config.js中
import AutoImport from 'unplugin-auto-improt/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
]
}
項目中英文功能
組件庫ElementPlus國際化
// 導入組件庫的中英文文件
import zhCnLocale from 'element-plus/es/locale/lang/zh-cn'
// 掛載組件庫并設(shè)置中文語言包
createApp(app).use(ElementPlus, { locale: zhCnLocale }).mount('#app')
自定義中英文選項
安裝 vue-i18n
npm i vue-i18n@next
使用 vue-i18n
// 自定義語言包
// /src/language/zh.js
export default {
hello: '你好'
}
// /src/language/en.js
export default {
hello: 'hello'
}
// /src/language/index.js
import en from './en'
import zh from './zh'
export default {
en,
zh
}
// src/language/i18n.js
import { createI18n } from 'vue-i18n'
import messages from './index'
const language = ((navigaotr.language ? navigator.language : navigator.userLanguage) || 'zh').toLowerCase();
const i18n = createI18n({
fallbackLocale: 'ch',
globalInjection: true, // 隱式注入組件的屬性和函數(shù)好芭,如$t
legacy: false, // 設(shè)置為false支持組合式API
locale: language.split("-")[0] || "zh",
message: {
...message
}
});
export default i18n;
掛載 vue-i18n挟炬,并通過i18n來動態(tài)設(shè)置組件庫的語言
// main.js
import i18n from './language/i18n'
import zhCnLocale from 'element-plus/es/locale/lang/zh-cn'
import enLocale from 'element-plus/es/locale/lang/en'
let locale = '';
//可根據(jù)使用的i18n插件來動態(tài)改變 element-plus 組件語言
if (i18n.global.fallbackLocale == 'zh') {
locale = zhCnLocale;
} else {
locale = enLocale;
}
createApp(app).use(ElementPlus, { locale }).use(i18n).mount('#app')
// 組件中使用示例 $t為i18n隱式注入函數(shù)焰络,可在模板中直接使用
<div>{{$t(`hello`)}}</div>
// 當中文情況下戴甩,查找中文包下的值,展示效果為
<div>你好</div>
// 當英文情況下闪彼,查找英文包下的值等恐,展示效果為
<div>hello</div>
// 在組件setup中使用,可通過useI18n來獲取t函數(shù),通過setup中返回到模板中使用
import { useI18n } from 'vue-i18n'
setup() {
const { t } = useI18n()
return {
t
}
}
i18n更多功能移步參考文檔 如傳入?yún)?shù)翻譯课蔬,t函數(shù)等。
接口數(shù)據(jù)渲染實現(xiàn)中英文切換功能
// 自定義接口返回數(shù)據(jù)二跋,通過屬性鍵是否以_en結(jié)尾區(qū)分中英文
data = {
title: '中文標題',
title_en: 'English Title'
}
// 組件中通過自定義Hook處理需要的數(shù)據(jù) mineHooks.js
import { computed } from '@vue/runtime-core'
import { getEnData } from './tools'
import { useMainStore } from '@/stores/main'
export function useStoreData(stateKey) {
const mainStore = useMainStore()
return computed(() => {
const lang = mainStore.langState
if(lang == 'zh') {
// 中文直接返回數(shù)據(jù)
return mainStore[stateKey]
}else{
// 英文則進行數(shù)據(jù)處理战惊,將原數(shù)據(jù)對應(yīng)鍵的值換成 對應(yīng)鍵以_en結(jié)尾的值
return getEnData(mainStore[stateKey])
}
})
}
// tools.js 將數(shù)據(jù)處理成一個新數(shù)據(jù)返回
export function getEnData (data) {
if (Object.prototype.toString.call(data) === '[object Object]') {
let keys = Object.keys(data)
let obj = {}
keys.forEach(item => {
let key = item.substring(0, item.length - 3)
if (Object.prototype.toString.call(data[item]) === '[object Object]') {
let res = getEnData(data[item])
if (/(.+(?=(_en)$))/.test(item)) {
obj[key] = getEnData(data[item])
} else {
obj[item] = res
}
} else if (Object.prototype.toString.call(data[item]) === '[object Array]') {
let arr = getEnData(data[item])
if (/(.+(?=(_en)$))/.test(item)) {
obj[key] = arr
}else{
obj[item] = arr
}
} else {
if (/(.+(?=(_en)$))/.test(item)) {
obj[key] = data[item]
}
}
})
let res = Object.assign({}, data, obj)
return res
}
if (Object.prototype.toString.call(data) === '[object Array]') {
let arr = []
data.forEach(item => {
if (Object.prototype.toString.call(item) === '[object Object]') {
let obj = getEnData(item)
arr.push(obj)
} else if (Object.prototype.toString.call(item) === '[object Array]') {
let arr = getEnData(item)
arr.push(arr)
} else {
arr.push(item)
}
})
return arr
}
return data
}
樣式適配(等比縮放)
安裝依賴
npm i postcss-pxtorem -D
npm i amfe-flexible -D
相關(guān)配置
// 在main.js中引入 amfe-flexible
import 'amfe-flexible'
// 在vite.config.js中配置 postcss-pxtorem
import { defineConfig } from 'vite'
import postCssPxToRem from 'postcss-pxtorem'
export default defineConfig({
css: {
postcss: {
plugin: [
postCssPxToRem({
rootValue: 160, // 設(shè)置根字體大小
propList: ['*'], // 需要轉(zhuǎn)換的屬性
})
]
}
}
})
// 剩余的樣式直接根據(jù)設(shè)計稿直接使用px開發(fā)就可以了
vite中引入本地圖片
在vite中是不支持require關(guān)鍵字的,需要使用import扎即,但是import在css in js 中不可用吞获。
vite中將資源引入為URL,會返回解析后的公共路徑谚鄙,因此直接在元素引入相對路徑下的圖片會造成解析錯誤各拷。
1、使用import方式導入圖片闷营,以變量形式賦值給元素烤黍。
import img from '@/assets/imgs/logo.png'
<img :src="img" />
2、使用 newURL(url, import.meta.url) 方式引入靜態(tài)資源URL傻盟。
import.meta.url是ESM原生功能速蕊,會暴露當前模塊的URL。通過 URL構(gòu)造器 組合使用娘赴,在JS模塊中规哲,通過相對路徑就能解析到完整的靜態(tài)資源URL。
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('img').src = imgUrl