创建项目
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
// 创建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'
// 创建pinia实例并使用持久化插件
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
createApp(App).use(pinia)
// 在组件中使用
import { useMainStore } from '@/stores/main'
setup() {
const mainStore = useMainStore()
// 可通过store实例对象直接访问数据
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'
// 挂载组件库并设置中文语言包
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, // 隐式注入组件的属性和函数,如$t
legacy: false, // 设置为false支持组合式API
locale: language.split("-")[0] || "zh",
message: {
...message
}
});
export default i18n;
挂载 vue-i18n,并通过i18n来动态设置组件库的语言
// 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 = '';
//可根据使用的i18n插件来动态改变 element-plus 组件语言
if (i18n.global.fallbackLocale == 'zh') {
locale = zhCnLocale;
} else {
locale = enLocale;
}
createApp(app).use(ElementPlus, { locale }).use(i18n).mount('#app')
// 组件中使用示例 $t为i18n隐式注入函数,可在模板中直接使用
{{$t(`hello`)}}
// 当中文情况下,查找中文包下的值,展示效果为
你好
// 当英文情况下,查找英文包下的值,展示效果为
hello
// 在组件setup中使用,可通过useI18n来获取t函数,通过setup中返回到模板中使用
import { useI18n } from 'vue-i18n'
setup() {
const { t } = useI18n()
return {
t
}
}
i18n更多功能移步参考文档 如传入参数翻译,t函数等。
接口数据渲染实现中英文切换功能
// 自定义接口返回数据,通过属性键是否以_en结尾区分中英文
data = {
title: '中文标题',
title_en: 'English Title'
}
// 组件中通过自定义Hook处理需要的数据 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') {
// 中文直接返回数据
return mainStore[stateKey]
}else{
// 英文则进行数据处理,将原数据对应键的值换成 对应键以_en结尾的值
return getEnData(mainStore[stateKey])
}
})
}
// tools.js 将数据处理成一个新数据返回
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
相关配置
// 在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, // 设置根字体大小
propList: ['*'], // 需要转换的属性
})
]
}
}
})
// 剩余的样式直接根据设计稿直接使用px开发就可以了
vite中引入本地图片
在vite中是不支持require关键字的,需要使用import,但是import在css in js 中不可用。
vite中将资源引入为URL,会返回解析后的公共路径,因此直接在元素引入相对路径下的图片会造成解析错误。
1、使用import方式导入图片,以变量形式赋值给元素。
import img from '@/assets/imgs/logo.png'
2、使用 newURL(url, import.meta.url) 方式引入静态资源URL。
import.meta.url是ESM原生功能,会暴露当前模块的URL。通过 URL构造器 组合使用,在JS模块中,通过相对路径就能解析到完整的静态资源URL。
const imgUrl = new URL('./img.png', import.meta.url).href
document.getElementById('img').src = imgUrl