エレメントプラスの初期化
Element Plus は、Vue 3 用の Element UI のアップグレード バージョンです。
自動オンデマンドインポートをインストールして構成する
# 安装
npm install element-plus --save
オンデマンド インポートの使用が推奨されています。公式では、unplugin-vue-components
とunplugin-auto-import
これら 2 つのプラグインを使用して自動インポートを実装し、オンデマンド インポートの欠点 (コンポーネントの手動登録など) を補うことが推奨されています。
# 安装插件
npm install -D unplugin-vue-components unplugin-auto-import
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()]
})
],
...
})
テスト:
<el-button type="primary">Primary</el-button>
グローバリゼーション
Element Plus コンポーネントでは、日付コンポーネントなど、デフォルトで英語が使用されます。
他の言語 (中国語など) を使用したい場合は、国際化をグローバルに構成する必要があります。
完全なインポート方法は、登録時のオプションを通じて設定できますlocale
。
オンデマンド インポートは、公式に提供されている Vue コンポーネントを使用して設定する必要があります。
<!-- 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>
効果 (設定を有効にするにはページを更新する必要があります):
アイコン
公式の場合のようにプロジェクト内で Element Plus アイコンを直接使用したい場合は、コンポーネントをグローバルに登録する必要があります。公式の自動インポートされたプラグインはまだ開発中であり、現在の手動グローバル登録は次のとおりです。
// 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')
APIとコンポーネントの自動インポート
Element Plus の自動インポートとインストール用のプラグインは、それ自体で使用されるだけでなく、実際、これら 2 つのプラグインはさまざまなフレームワークやライブラリに適用できます。
unplugin-vue-コンポーネント
unplugin-vue-componentsプラグインは、Vue テンプレートで使用されるコンポーネントを自動的に識別し、オンデマンドで自動的にインポートおよび登録するために使用されます。
いくつかの構成可能な UI ライブラリのパーサーを提供します。「UI ライブラリからのインポート」セクションを参照してください。
TypeScript プロジェクト内にファイルが生成され、components.d.ts
コンポーネントの型宣言ファイルを自動的に補完および更新します。
**注意: **プラグインは、テンプレート templateで使用されているコンポーネントを自動的に認識します。components.d.ts
認識されているかどうかを確認することができます。
アンプラグイン自動インポート
unplugin-auto-importref
プラグインは、手動作業を行わずに、Vite、Webpack、Rollup、および esbuild 環境 (Vue など) にオンデマンドで構成ライブラリの共通 API を自動的にインポートできますimport
。
imports
構成アイテムを通じて自動的にインポートされた API (プリセットまたはカスタム ルール) を構成したり、resolvers
コンポーネント ライブラリ (Element Plus など) のパーサーを構成したりできます。
TypeScript をサポートしているプロジェクトでは、プラグインのインストール後にプロジェクトのルート ディレクトリにファイルが生成され、auto-imports.d.ts
設定が自動インポートされる際に、設定ライブラリの API に対応する型宣言が自動的に補完されます。
注:
auto-imports.d.ts
ファイルはデフォルトで ESLint によって検証され、エラーが報告されます<变量> is defined but never used.
。ESLint によるファイルの検証は無視できます。
API 自動インポートを構成する
Vue、Vue Router、Pinia の API 自動インポートを構成します。
// 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()]
}),
...
],
...
})
保存が有効になると、auto-imports.d.ts
コンテンツが自動的に入力され、.eslintrc-auto-import.json
eslint グローバル変数構成がプロジェクトのルート ディレクトリに生成されます。
これら 2 つのファイルは、TypeScript および 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'
],
...
}
ESLint 検証を無視しますauto-imports.d.ts
。
# .eslintignore
auto-imports.d.ts
設定を有効にするには、エディタを再起動することをお勧めします。
Vue、Vue Router、Pinia の API を手作業なしで直接使用できるようになりましたimport
。
たとえば、次の API のインポートに注釈を付けることができます。
<!-- 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'
...
知らせ:
- Vue Router などのすべての API が
createRouter
インポートされるわけではありません。自動的にインポートできる特定の API については、unplugin-auto-import/src/presetsを参照してください。- ファイルの生成
.eslintrc-auto-import.json
後に設定を追加する必要がない場合は、enabled: true
に設定することをお勧めしますfalse
。そうしないと、このファイルが毎回生成されます。
ElementPlus コンポーネントへの個別の参照
自動オンデマンド インポートの原則は、<template>
で使用されているコンポーネントを識別して自動的にインポートすることです。そのため、ElMessage
JS のメソッドを直接呼び出すコンポーネントを使用すると、プラグインは自動インポートを認識せず、完了できません。
例えば:
- Vue の単一ファイル コンポーネント
<script>
で使用される - Axiosインターセプターで使用
したがって、そのようなコンポーネントは手動で操作する必要があります。
- コンポーネントを手動で
import
インポートします (インポートを完了するには手動も必要ですimport
) - スタイル ファイルを手動でインポートする (
element-plus/theme-chalk/xxx.css
)
たとえば、一般的に使用されるElMessage
コンポーネントは次のとおりです。
import {
ElMessage } from 'element-plus'
import 'element-plus/theme-chalk/el-message.css'
ElMessage.success('成功使用')
しかし、これにはまだ問題があります。一部のコンポーネントは他の Element コンポーネントも使用しているためです。レンダリングは成功しても、ElMessageBox
確認ボタンがそのコンポーネントを使用しているElButton
など、レンダリングは成功しますが、プラグインを通じて自動的にインポートされないため、スタイル。
これが Vue 単一ファイル コンポーネントで使用され、 template で使用される場合
<el-button>
、コンポーネントのスタイル ファイルの自動インポートがトリガーされます。
したがって、このような境界の問題を回避するには、オンデマンドでインポートし、完全なスタイル ファイルをインポートすることをお勧めします。
// 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('成功使用')
Vue グローバル プロパティ (globalProperties)
公式ドキュメント:
Vue 2 では、すべての Vue インスタンスに対してグローバルにアクセスできる変数とメソッドVue.prototype
( ) を一度に設定できます。this
Vue 3 は、Vue 2 のすべてのルート インスタンスを変更する方法の代わりに、ルート インスタンス上のオブジェクトを使用して、app.config.globalProperties
インスタンス ( )app
内のすべてのコンポーネント インスタンスによってアクセスされるグローバル プロパティを登録します。
ElementPlus メッセージ プロンプト コンポーネントをグローバルに登録する
Element Plus が完全に導入されると、app.config.globalProperties
コンポーネントのいくつかのグローバル メソッド ( 、ElMessage
など$message
)が自動的に追加ElMessageBox
されます。$msgbox
$alert
ただし、オンデマンド インポート方法を使用する場合、このタイプのコンポーネントを使用する場合は、使用するモジュールにコンポーネントとコンポーネント スタイルを手動でインポートする必要があります。
Vue コンポーネントでのインポートの繰り返しを減らすために、それらを Vue インスタンスのグローバル変数として登録できます (変数名は完全なインポート登録の名前を指します)。
// 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
}
}
グローバル変数を使用する
オプション API のグローバル変数を介してアクセスすることもthis.<globalProperty>
、テンプレートで直接使用することもできます。
<template>
<button @click="$message.success('可以在模板中直接使用')">
提示
</button>
</template>
<script lang="ts">
export default defineComponent({
mounted() {
this.$message.success('Options API 成功使用')
}
})
</script>
セットアップでグローバル変数を使用する
公式では、setup()
や での<script setup>
グローバル変数の使い方は紹介されていません。
app.config.globalProperties
の目的は、グローバル API の更新によって 2.x の使用を置き換えることであるためVue.prototype
、1 回限りの Vue グローバル設定はなくなり、ルート インスタンスごとに個別の設定が必要になります。
これは で使用することを意図したものではないためsetup
、コンテンツを直接インポートするか、setup
で使用する必要がありますprovide/inject
。
問題を参照してください:
提供/注入モード
<!-- 父级组件,如 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>
セットアップでインスタンスを取得する方法 (非推奨)
別の方法では、Vue は内部コンポーネント インスタンスにアクセスできる API を公開しgetCurrentInstance()
、これを通じてルート インスタンスのグローバル変数にアクセスできます。
<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>
提案
使い方はいろいろありますが、直接インポートしたり、オプションAPIを利用したりするなど、安全な方法を使うことをお勧めします。
グローバル変数 TypeScript の型宣言
型宣言ファイルを追加します。
// src\types\global.d.ts
import {
ElMessage, ElMessageBox } from 'element-plus'
declare module 'vue' {
// vue 全局属性
export interface ComponentCustomProperties {
$message: typeof ElMessage
$msgBox: typeof ElMessageBox
}
}
Axiosベースのパッケージリクエストモジュール
npm i axios
基本構成
// 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
すべてのインターフェース要求は、src/api
次のディレクトリーの下に編成されます。
// src\api\common.ts
// 公共基础接口封装
import request from '@/utils/request'
export const demo = () => {
return request({
method: 'GET',
url: '/demo'
})
}
使用:
<!-- 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>
応答データをカプセル化するインターフェースのタイプ
現在取得されているのはres
、Axios によってパッケージ化された応答オブジェクトです。バックエンドによって返される実際のデータには宣言された型がないため、IDE はスマート プロンプトを提供できないため、応答データの型を手動で宣言する必要があります。
request
応答データのジェネリックはサポートされていないため、代わりにジェネリックをサポートする送信リクエストを使用する必要がありますrequest.<method>
。
export const demo = () => {
return request.get<{
status: number
msg: string
data: {
title: string
date: number
}
}>('/demo')
}
これで、IDE はres.data
の下のフィールドに自動的にプロンプトを表示できるようになりました。
ただし、各インターフェイスはとフィールドを返しますstatus
。宣言の繰り返しを避けるために、これらをインターフェイス型 (インターフェイス) にカプセル化し、ジェネリック型として定義できます。msg
data
data
interface ResponseData<T = any> {
status: number
msg: string
data: T
}
export const demo = () => {
return request.get<ResponseData<{
title: string
date: number
}>>('/demo')
}
汎用リクエストメソッドをカプセル化する
応答データのdata
フィールドにアクセスするには、 を渡す必要がありますres.data.data.title
。
たとえば、より簡潔にしたい場合はres.title
、リクエストの後に return することができます.then(res => res.data.data)
。
したがって、このアクションは各リクエストの後に追加する必要があります。
通常は axios インターセプターで処理しますが、request.get()
戻り値の型は Axios によってカプセル化されたオブジェクト (AxiosResponse) になります。
正常に動作している間は、スマート ヒントは機能しません。
ジェネリック型を受け取るメソッドをカプセル化し、内部で呼び出すことができます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)
}
request.get()
ただし、この方法では、メソッドを使用してリクエストを送信することはできません。
// 之前定义的 interface ResponseData 就不需要了
interface DemoData {
title: string
date: number
}
export const demo = () => {
return request<DemoData>({
method: 'GET',
url: '/demo'
})
}
この方法はリクエストの送信には使用できませんrequest.<method>
。メリットとデメリットがあるため、個人の習慣に応じて使用することを選択してください。
インターフェースタイプモジュールの抽出
一般的なインターフェイスの応答データの形式は複数の場所で使用される可能性があるため、それらのインターフェイスの種類を再利用するために、個別にモジュールに抽出することができます。
API 関連のタイプ モジュールを保存するフォルダーsrc/api
をディレクトリの下に作成します。types
// src\api\types\common.ts
export interface DemoData {
title: string
date: number
}
使用:
// 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>
環境変数とパターン
通常、さまざまな環境のベース アドレス (baseUrl) がプロジェクトのインターフェイスに設定され、通常は環境変数で設定されます。
Vite は特別なimport.meta.env.[variable]
オブジェクトで環境変数を公開します。ビルド時に、これらの環境変数は文字列として識別され、静的に置き換えられるため、動的なキー値は使用できませんimport.meta.env[variable]
。
Vite は Vue CLI と同じ方法をサポートしており、.env.[mode]
ファイルを通じて環境変数を指定します。
Vue CLI とは異なり、後者のカスタム変数はVUE_APP_
で始まる必要がありますが、ViteVITE_
では で始まる必要があります。
環境変数を構成する
値は文字列として置換され、含まれない限り引用符で囲まなくてもかまいません#
。
# .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
})
...
注: 環境変数の変更をnpm run dev
有効にするには、Vite ( ) を再起動する必要があります。
環境変数 TypeScript のサポート
MODE
Vite はデフォルトの環境変数 ( 、BASE_URL
、PROD
、 )の TS タイプ定義のみを提供しておりDEV
、ユーザー定義の環境変数は手動でタイプ定義を追加する必要があります。
// src\env.d.ts
...
// Vite 环境变量
// eslint-disable-next-line no-unused-vars
interface ImportMetaEnv {
readonly VITE_API_BASEURL: string
}
インターフェイスは定義されていますが使用されていないため、eslint はエラーを報告し、このコード行ではこのルールを無効にすることができます。
クロスドメインの問題
通常、フロントエンド プロジェクトとバックエンド プロジェクトは別々にデプロイされ、サーバー インターフェイスにはクロスドメインの制限があります。クロスドメインを解決するには多くの方法があります。最も主流のフロントエンド ソリューションは次の 2 つです:
開発環境 | 本番環境 |
---|---|
サーバー上で CORS を構成する | サーバー上で CORS を構成する |
vite の server.proxyや Vue CLIなどの開発サーバー プロキシを構成します。devServer.proxy |
nginx などの実稼働サーバー プロキシを構成する |
一般に、バックエンドの開発は CORS を構成するには時間がかかるため、フロントエンドの一般的な解決策はサーバー リバース プロキシ (プロキシ) を構成することです。
原則として、クロスドメインの問題を回避するためにリクエストを転送するトランジット サーバーを構築することです。インターフェイスはローカル アドレスをリクエストし、フロントエンド コードを実行しているサーバーはそれをターゲット サーバーに転送します。
/api
リクエストのベース パスをローカル パスに変更します (最初のリクエスト パスは、転送する必要があるインターフェイス リクエストであることが合意されています)。
# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=/api
環境変数を有効にするために、必ず再起動してください。
構成された/api
リバース プロキシ:
// 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/, '')
}
}
}
})
app.use(cors())
PS: 現在のケースで使用されているサーバー コードはデフォルトで CORS で構成されており、クロスドメイン効果をテストするために削除できます。