vite + vue3創(chuàng)建項目

創(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ù)翻譯课蔬,n囱稽、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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載诽表,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者唉锌。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市竿奏,隨后出現(xiàn)的幾起案子糊秆,更是在濱河造成了極大的恐慌,老刑警劉巖议双,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痘番,死亡現(xiàn)場離奇詭異,居然都是意外死亡平痰,警方通過查閱死者的電腦和手機汞舱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宗雇,“玉大人昂芜,你說我怎么就攤上這事∨馄眩” “怎么了泌神?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵良漱,是天一觀的道長。 經(jīng)常有香客問我欢际,道長母市,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任损趋,我火速辦了婚禮患久,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浑槽。我一直安慰自己蒋失,他們只是感情好,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布桐玻。 她就那樣靜靜地躺著篙挽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镊靴。 梳的紋絲不亂的頭發(fā)上铣卡,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音邑闲,去河邊找鬼。 笑死梧油,一個胖子當著我的面吹牛苫耸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播儡陨,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼褪子,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了骗村?” 一聲冷哼從身側(cè)響起嫌褪,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎胚股,沒想到半個月后笼痛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡琅拌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年缨伊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片进宝。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡刻坊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出党晋,到底是詐尸還是另有隱情谭胚,我是刑警寧澤徐块,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站灾而,受9級特大地震影響胡控,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绰疤,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一铜犬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轻庆,春花似錦癣猾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛾方,卻和暖如春像捶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背桩砰。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工拓春, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亚隅。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓硼莽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親煮纵。 傳聞我的和親對象是個殘疾皇子懂鸵,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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