vite + vue3创建项目

创建项目

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

你可能感兴趣的:(vite + vue3创建项目)