Initialiser Element Plus
Element Plus est une version améliorée d'Element UI pour Vue 3.
Installer et configurer l'importation automatique à la demande
# 安装
npm install element-plus --save
Il est recommandé d'utiliser l'importation à la demande La recommandation officielle est d'utiliser unplugin-vue-components
et unplugin-auto-import
ces deux plug-ins pour mettre en œuvre l'importation automatique afin de pallier certaines lacunes de l'importation à la demande (enregistrement manuel des composants, etc.).
# 安装插件
npm install -D unplugin-vue-components unplugin-auto-import
Configurez Vite :
// vite.config.ts
...
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {
ElementPlusResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
...
// ElementPlus 自动导入
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
...
})
test:
<el-button type="primary">Primary</el-button>
mondialisation
Les composants Element Plus utilisent l'anglais par défaut, comme le composant date :
Si vous souhaitez utiliser d'autres langues (comme le chinois), vous devez configurer l'internationalisation globalement.
La méthode d'importation complète peut être configurée via les options lors de l'enregistrement locale
.
L'importation à la demande doit être configurée à l'aide des composants Vue fournis officiellement :
<!-- src\App.vue -->
<template>
<el-config-provider :locale="locale">
<router-view />
</el-config-provider>
</template>
<script setup lang="ts">
import locale from 'element-plus/lib/locale/lang/zh-cn'
</script>
Effet (vous devez actualiser la page pour que la configuration prenne effet) :
icône
Si vous souhaitez utiliser l'icône Element Plus directement dans le projet comme le cas officiel, vous devez enregistrer le composant globalement. Le plug-in officiel importé automatiquement est toujours en cours de développement, et l'enregistrement global manuel actuel :
// src\plugins\element-plus.ts
import {
App } from 'vue'
import * as ElIconModules from '@element-plus/icons-vue'
export default {
install(app: App) {
// 批量注册 Element Plus 图标组件
// 或者自定义 ElIconModules 列表
for (const iconName in ElIconModules) {
app.component(iconName, (ElIconModules as any)[iconName])
}
}
}
// src\main.ts
import {
createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import elementPlus from './plugins/element-plus'
// 加载全局样式
import './styles/index.scss'
createApp(App)
.use(router)
.use(store)
.use(elementPlus)
.mount('#app')
Importation automatique d'API et de composants
Les plug-ins pour l'importation et l'installation automatiques d'Element Plus ne sont pas seulement utilisés pour eux-mêmes, en fait, ces deux plug-ins peuvent être appliqués à divers frameworks et bibliothèques.
unplugin-vue-composants
Le plugin unplugin-vue-components est utilisé pour identifier automatiquement les composants utilisés dans le modèle Vue, importer et enregistrer automatiquement à la demande.
Il fournit des analyseurs pour plusieurs bibliothèques d'interface utilisateur configurables, voir la section "Importation à partir de bibliothèques d'interface utilisateur".
Un fichier sera généré dans le projet TypeScript components.d.ts
pour compléter et mettre à jour automatiquement le fichier de déclaration de type du composant.
**Remarque : **Le plug-in reconnaît automatiquement les composants utilisés dans le modèle de modèlecomponents.d.ts
, vous pouvez vérifier pour confirmer s'il a été reconnu.
unplugin-auto-import
Le plugin unplugin-auto-import peut importer automatiquement les API communes des bibliothèques de configuration à la demande dans les environnements Vite, Webpack, Rollup et esbuild, tels que ceux de Vue, ref
sans travail manuel import
.
Vous pouvez imports
configurer l'API importée automatiquement (règles prédéfinies ou personnalisées) via l'élément de configuration, ou resolvers
configurer l'analyseur de la bibliothèque de composants (comme Element Plus).
Dans un projet supportant TypeScript, un fichier sera généré dans le répertoire racine du projet après l'installation du plug-in auto-imports.d.ts
. Lors de l'importation automatique de la configuration, la déclaration de type correspondant à l'API de la bibliothèque de configuration sera automatiquement complétée.
Remarque :
auto-imports.d.ts
Le fichier sera vérifié par ESLint par défaut et une erreur sera signalée<变量> is defined but never used.
. Vous pouvez ignorer la vérification du fichier par ESLint.
Configurer l'importation automatique d'API
Configurez l'importation automatique d'API pour Vue, Vue Router et Pinia :
// vite.config.ts
...
import AutoImport from 'unplugin-auto-import/vite'
...
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
...
AutoImport({
imports: [
// presets
'vue',
'vue-router',
'pinia'
],
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true
},
// ElementPlus 自动导入
resolvers: [ElementPlusResolver()]
}),
...
],
...
})
Après l'enregistrement, auto-imports.d.ts
le contenu sera automatiquement rempli et .eslintrc-auto-import.json
la configuration de la variable globale eslint sera générée dans le répertoire racine du projet.
Ces deux fichiers doivent être ajoutés manuellement aux fichiers de configuration TypeScript et ESLint :
// tsconfig.json
{
...
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts"],
"references": [{
"path": "./tsconfig.node.json" }]
}
// .eslintrc.js
module.exports = {
...
extends: [
...
// unplugin-auto-import
'./.eslintrc-auto-import.json'
],
...
}
Ignore auto-imports.d.ts
la validation ESLint.
# .eslintignore
auto-imports.d.ts
Il est recommandé de redémarrer l'éditeur pour que la configuration prenne effet.
Vous pouvez maintenant utiliser directement l'API de Vue, Vue Router et Pinia sans import
travail manuel.
Par exemple, vous pouvez annoter les importations des API suivantes :
<!-- src\layout\AppHeader\Breadcrumb.vue -->
...
<script setup lang="ts">
// import { useRouter } from 'vue-router'
// import { computed } from 'vue'
const router = useRouter()
const routes = computed(() => {
return router.currentRoute.value.matched.filter(item => item.meta.title)
})
</script>
// src\store\index.ts
// import { defineStore } from 'pinia'
const useStore = defineStore('main', {
...
})
export default useStore
// src\main.ts
// import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// import { createPinia } from 'pinia'
import elementPlus from './plugins/element-plus'
...
Avis:
- Toutes les API , telles que celles de Vue Router,
createRouter
ne seront pas importées. Pour les API spécifiques pouvant être importées automatiquement, reportez-vous à unplugin-auto-import/src/presets.eslintrc-auto-import.json
Si vous n'avez pas besoin d'ajouter de configuration après avoir généré le fichier, il est recommandéenabled: true
de définir surfalse
, sinon ce fichier sera généré à chaque fois.
Référence séparée aux composants ElementPlus
Le principe de l'importation automatique à la demande est d' <template>
importer automatiquement en identifiant les composants utilisés dans , ce qui conduit au fait que si vous utilisez ElMessage
de tels composants qui appellent directement des méthodes dans JS, le plug-in ne reconnaîtra pas et ne terminera pas l'importation automatique.
Par exemple:
<script>
Utilisé dans les composants Vue à fichier unique- Utilisé dans l'intercepteur Axios
Ces composants doivent donc être actionnés manuellement :
- Importer manuellement
import
les composants (l'importation complète nécessite également un manuelimport
) - Importer manuellement les fichiers de style (
element-plus/theme-chalk/xxx.css
)
Par exemple, les composants couramment utilisésElMessage
:
import {
ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
ElMessage.success('成功使用')
Mais il y a toujours un problème avec cela, car certains composants utilisent également d'autres composants Element, comme le ElMessageBox
bouton de confirmation dans utilise ElButton
le composant, bien que le rendu soit réussi, mais comme il n'est pas automatiquement importé via le plug-in, il n'y a pas style.
S'il est utilisé dans un composant Vue à fichier unique et utilisé dans le modèle
<el-button>
, il déclenchera l'importation automatique du fichier de style du composant.
Par conséquent, il est recommandé d'importer à la demande tout en continuant d'importer des fichiers de style complets pour éviter de tels problèmes de limites.
// src\plugins\element-plus.ts
import {
App } from 'vue'
import * as ElIconModules from '@element-plus/icons-vue'
import 'element-plus/theme-chalk/index.css'
export default {
install(app: App) {
// 批量注册 Element Plus 图标组件
// 或者自定义 ElIconModules 列表
for (const iconName in ElIconModules) {
app.component(iconName, (ElIconModules as any)[iconName])
}
}
}
import {
ElMessage } from 'element-plus'
// 不再需要单独引入组件样式
// import 'element-plus/theme-chalk/el-message.css'
ElMessage.success('成功使用')
Propriétés globales de la vue (globalProperties)
Documents officiels :
Dans Vue 2, les variables et les méthodes accessibles Vue.prototype
globalement ( ) pour toutes les instances de Vue peuvent être définies en même temps .this
Vue 3 utilise l'objet sur l'instance racine pour enregistrer les propriétés globales auxquelles accèdent toutes les instances de composant dans app.config.globalProperties
l'instance ( ), au lieu de la méthode de Vue 2 consistant à modifier toutes les instances racine.app
Enregistrer le composant d'invite de message ElementPlus globalement
Si Element Plus est entièrement introduitapp.config.globalProperties
, certaines méthodes globales de composants (telles que , , ElMessage
etc. $message
) ElMessageBox
seront ajoutées automatiquement.$msgbox
$alert
Cependant, si vous utilisez la méthode d'importation à la demande , lorsque vous utilisez ce type de composant, vous devez importer manuellement le composant et le style de composant dans le module utilisé.
Afin de réduire les importations répétées dans les composants Vue, ils peuvent être enregistrés en tant que variables globales de l'instance Vue (le nom de la variable fait référence au nom de l'enregistrement d'importation complet) :
// src\plugins\element-plus.ts
import {
App } from 'vue'
import * as ElIconModules from '@element-plus/icons-vue'
import {
ElMessage, ElMessageBox } from 'element-plus'
import 'element-plus/theme-chalk/index.css'
export default {
install(app: App) {
// 批量注册 Element Plus 图标组件
// 或者自定义 ElIconModules 列表
for (const iconName in ElIconModules) {
app.component(iconName, (ElIconModules as any)[iconName])
}
// 将消息提示组件注册为全局方法
app.config.globalProperties.$message = ElMessage
app.config.globalProperties.$msgBox = ElMessageBox
}
}
utiliser des variables globales
Accessible via des variables globales dans l'API options this.<globalProperty>
, ou directement utilisable dans les templates :
<template>
<button @click="$message.success('可以在模板中直接使用')">
提示
</button>
</template>
<script lang="ts">
export default defineComponent({
mounted() {
this.$message.success('Options API 成功使用')
}
})
</script>
Utiliser des variables globales dans la configuration
L'officiel n'explique pas comment utiliser les variables globales dans setup()
et .<script setup>
Parce que app.config.globalProperties
le but de est de remplacer Vue.prototype
l'utilisation de 2.x, avec la mise à jour de l'API globale, il n'y aura plus une configuration globale unique de Vue, mais une configuration distincte pour chaque instance racine .
Ceci n'est pas destiné à être utilisé dans setup
, vous devez importer le contenu directement ou setup
l'utiliser dans provide/inject
.
Reportez-vous à Problèmes :
mode fournir/injecter
<!-- 父级组件,如 App.vue -->
<script setup>
import {
ElMessage } from 'element-plus'
provide('$message', ElMessage)
</script>
<!-- 子孙组件 -->
<script setup>
const $message = inject('$message')
onMounted(() => {
$message.success('setup - provide/inject 成功使用')
})
</script>
Comment obtenir une instance dans la configuration (non recommandé)
D'une autre manière, Vue expose une API qui getCurrentInstance()
peut accéder aux instances de composants internes, à travers lesquelles les variables globales de l'instance racine sont accessibles :
<script setup lang="ts">
const instance = getCurrentInstance()
onMounted(() => {
instance.proxy.$message.success('setup - getCurrentInstance() 成功使用')
// 也可以使用 appContext
console.log(instance.appContext.config.globalProperties.$message === instance.proxy.$message) // true
})
</script>
<script lang="ts">
export default defineComponent({
mounted() {
console.log(this.instance.proxy === this) // true
}
})
</script>
suggestion
Il existe de nombreuses façons de l'utiliser, et il est recommandé d'utiliser un moyen sûr, comme l'importation directe ou l'utilisation sous les options de l'API.
Déclaration de type TypeScript de variable globale
Ajouter un fichier de déclaration de type :
// src\types\global.d.ts
import {
ElMessage, ElMessageBox } from 'element-plus'
declare module 'vue' {
// vue 全局属性
export interface ComponentCustomProperties {
$message: typeof ElMessage
$msgBox: typeof ElMessageBox
}
}
Module de demande de package basé sur Axios
npm i axios
configuration de base
// src\utils\request.ts
import axios from 'axios'
import {
ElMessage } from 'element-plus'
// 在 plugins/element-plus.ts 引入了全部组件样式,这里不需额外引入
// 创建 axios 实例
const request = axios.create({
baseURL: 'http://localhost:5000/api/admin'
})
// 请求拦截器
request.interceptors.request.use(function (config) {
// 统一设置用户身份 token
return config
}, function (error) {
return Promise.reject(error)
})
// 响应拦截器
request.interceptors.response.use(function (response) {
// 统一处理接口响应错误,如 token 过期无效、服务端异常等
if (response.data.status && response.data.status !== 200) {
ElMessage.error(response.data.msg || '请求失败,请稍后重试')
return Promise.reject(response.data)
}
return response
}, function (error) {
return Promise.reject(error)
})
export default request
Toutes les demandes d'interface sont src/api
organisées sous le répertoire :
// src\api\common.ts
// 公共基础接口封装
import request from '@/utils/request'
export const demo = () => {
return request({
method: 'GET',
url: '/demo'
})
}
utiliser:
<!-- src\views\login\index.vue -->
<template>
<div>
登录
</div>
</template>
<script setup lang="ts">
import {
demo } from '@/api/common'
import {
onMounted } from 'vue'
onMounted(() => {
demo().then(res => {
console.log(res.data)
// {"msg":"ok","status":200,"data":{"title":"Hello World","date":1649412637487}}
})
})
</script>
Le type d'interface qui encapsule les données de réponse
Ce qui est actuellement obtenu res
est l'objet de réponse empaqueté par Axios. Les données réelles renvoyées par le backend n'ont pas de type déclaré, de sorte que l'IDE ne peut pas fournir d'invites intelligentes, de sorte que le type des données de réponse doit être déclaré manuellement.
request
Les génériques de données de réponse ne sont pas pris en charge. Par conséquent, les demandes d'envoi prenant en charge les génériques doivent être utilisées à la place request.<method>
.
export const demo = () => {
return request.get<{
status: number
msg: string
data: {
title: string
date: number
}
}>('/demo')
}
Maintenant, l'IDE peut demander automatiquement res.data
les champs sous .
Mais chaque interface retournera les champs status
, msg
et data
.Afin d'éviter les déclarations répétées, ils peuvent être encapsulés dans un type d'interface (interface), et data
définis comme un type générique :
interface ResponseData<T = any> {
status: number
msg: string
data: T
}
export const demo = () => {
return request.get<ResponseData<{
title: string
date: number
}>>('/demo')
}
Encapsuler les méthodes de requête génériques
Maintenant, l'accès aux champs des données de réponse data
doit être passé res.data.data.title
.
Si vous souhaitez être plus concis, par exemple res.title
, vous pouvez revenir après la demande .then(res => res.data.data)
.
Cette action doit donc être ajoutée après chaque requête.
Habituellement, nous le traitons dans l'intercepteur axios, mais request.get()
le type de retour sera toujours l'objet encapsulé par Axios (AxiosResponse).
S'ils fonctionnent correctement, les Smart Tips ne fonctionneront pas.
Vous pouvez encapsuler une méthode qui reçoit un type générique et l'appeler en interne request()
.
// src\utils\request.ts
import axios, {
AxiosRequestConfig } from 'axios'
...
export default <T = any>(config: AxiosRequestConfig) => {
return request(config).then(res => (res.data.data || res.data) as T)
}
Mais de cette manière, vous ne pouvez pas utiliser request.get()
la méthode pour envoyer la requête :
// 之前定义的 interface ResponseData 就不需要了
interface DemoData {
title: string
date: number
}
export const demo = () => {
return request<DemoData>({
method: 'GET',
url: '/demo'
})
}
Cette méthode ne peut pas être utilisée pour request.<method>
envoyer des demandes, il y a des avantages et des inconvénients, choisissez de l'utiliser en fonction de vos habitudes personnelles.
Extraire le module de type d'interface
Le format des données de réponse de l'interface générale peut être utilisé à plusieurs endroits.Afin de réutiliser leurs types d'interface, il peut être extrait dans un module séparément.
src/api
Créez un dossier sous le répertoire pour types
stocker les modules de type liés à l'API :
// src\api\types\common.ts
export interface DemoData {
title: string
date: number
}
utiliser:
// src\api\common.ts
// 公共基础接口封装
import request from '@/utils/request'
import {
DemoData } from '@/api/types/common'
export const demo = () => {
return request<DemoData>({
method: 'GET',
url: '/demo'
})
}
<!-- src\views\login\index.vue -->
<template>
<div>
登录
</div>
</template>
<script setup lang="ts">
import {
demo } from '@/api/common'
import {
DemoData } from '@/api/types/common'
import {
onMounted, ref } from 'vue'
const data = ref<DemoData>()
onMounted(() => {
demo().then(res => {
data.value = res
console.log(data.value.title)
})
})
</script>
Variables et modèles d'environnement
Variables et modèles d'environnement | Documentation chinoise officielle de Vite
Généralement, l'adresse de base (baseUrl) des différents environnements sera configurée pour l'interface du projet, qui est généralement configurée dans la variable d'environnement.
Vite expose des variables d'environnement sur un import.meta.env.[variable]
objet spécial. Lors de la construction, ces variables d'environnement seront identifiées comme des chaînes et remplacées de manière statique, de sorte que les valeurs de clé dynamiques ne peuvent pas être utilisées, par exemple import.meta.env[variable]
.
Vite prend en charge la même manière que Vue CLI, .env.[mode]
en spécifiant les variables d'environnement via des fichiers.
Contrairement à Vue CLI, les variables personnalisées de ce dernier doivent commencer VUE_APP_
par , tandis que Vite doit VITE_
commencer par .
Configurer les variables d'environnement
Les valeurs sont remplacées sous forme de chaînes et peuvent être sans guillemets sauf si elles sont incluses #
.
# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=http://localhost:5000/api/admin
# .env.production
# 生产模式下加载的环境变量
VITE_API_BASEURL=http://localhost:5000/api/admin
// src\utils\request.ts
import axios, {
AxiosRequestConfig } from 'axios'
// 创建 axios 实例
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASEURL
})
...
Remarque : La modification des variables d'environnement nécessite le redémarrage de Vite ( npm run dev
) pour prendre effet.
Prise en charge des variables d'environnement TypeScript
Vite fournit uniquement des définitions de type TS pour les variables d'environnement par défaut ( MODE
, BASE_URL
, PROD
, DEV
), et les variables d'environnement définies par l'utilisateur doivent ajouter manuellement des définitions de type.
// src\env.d.ts
...
// Vite 环境变量
// eslint-disable-next-line no-unused-vars
interface ImportMetaEnv {
readonly VITE_API_BASEURL: string
}
Étant donné que l'interface est définie mais non utilisée, eslint signalera une erreur et cette règle peut être désactivée pour cette ligne de code.
problèmes inter-domaines
Généralement, le projet frontal et le projet principal sont déployés séparément, et l'interface serveur a des restrictions inter-domaines. Il existe de nombreuses façons de résoudre les problèmes inter-domaines. Les solutions frontales les plus courantes sont au nombre de deux :
environnement de développement | Environnement de production |
---|---|
Configurer CORS sur le serveur | Configurer CORS sur le serveur |
Configurez le proxy du serveur de développement, tel que le server.proxy de vite et les CLI de VuedevServer.proxy |
Configurer le proxy du serveur de production, tel que nginx |
Généralement, le développement back-end est trop paresseux pour configurer CORS. La solution courante pour le front-end est de configurer le serveur proxy inverse (proxy).
Le principe est de construire un serveur de transit pour transmettre les requêtes afin d'éviter les problèmes inter-domaines. L'interface demande une adresse locale, et le serveur exécutant le code frontal la transmet au serveur cible.
Remplacez le chemin de base de la requête par un chemin local (il est convenu que /api
le chemin de la requête au début est une requête d'interface qui doit être transmise) :
# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=/api
N'oubliez pas de redémarrer pour que les variables d'environnement prennent effet.
/api
Proxy inverse configuré :
// vite.config.ts
...
export default defineConfig({
...
server: {
proxy: {
'/api': {
// 目标地址
target: 'http://localhost:5000/api/admin',
// 有的服务器会验证 origin
// 默认接收到的是真实的 origin 即 http://localhost:3000
// 设置 changeOrigin 为 true 后,代理服务器就会把 origin 修改为 target 的 origin(http://localhost:5000)
// 一般建议加上此设置
changeOrigin: true,
// 路径重写
// 路径即请求路径,如 /api/demo
// 默认会这样拼接: <target.path><path> 如 http://localhost:5000/api/admin/api/demo
// 重新后为 http://localhost:5000/api/admin/demo
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
PS : Le code serveur utilisé dans le cas actuel est configuré avec CORS par défaut, qui peut être supprimé
app.use(cors())
pour tester les effets inter-domaines.