最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue?3項(xiàng)目中Element?Plus組件庫實(shí)戰(zhàn)技巧與踩坑記錄

 更新時(shí)間:2026年06月17日 11:14:13   作者:晴天丨  
Element Plus是一個(gè)基于Vue3的組件庫,提供了豐富且易于使用的UI組件,用于快速搭建企業(yè)級(jí)桌面和移動(dòng)端的前端應(yīng)用,這篇文章主要介紹了Vue 3項(xiàng)目中Element?Plus組件庫實(shí)戰(zhàn)技巧與踩坑記錄的相關(guān)資料,需要的朋友可以參考下

分享我在Vue 3項(xiàng)目中使用Element Plus的經(jīng)驗(yàn)技巧和踩坑記錄

前言

Element Plus是Vue 3生態(tài)中最流行的UI組件庫之一,提供了豐富的組件和良好的設(shè)計(jì)。在開發(fā)博客項(xiàng)目的過程中,我積累了很多使用Element Plus的經(jīng)驗(yàn)和技巧,也踩過一些坑。本文將分享這些實(shí)戰(zhàn)經(jīng)驗(yàn)。

快速上手

1. 安裝與配置

# 安裝Element Plus
npm install element-plus

# 安裝圖標(biāo)庫
npm install @element-plus/icons-vue
// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'

const app = createApp(App)

// 注冊所有組件
app.use(ElementPlus)

// 注冊所有圖標(biāo)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.mount('#app')

2. 按需引入(推薦)

為了減小包體積,建議按需引入組件:

# 安裝按需引入插件
npm install -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

這樣配置后,使用組件時(shí)會(huì)自動(dòng)按需引入,無需手動(dòng)import。

常用組件技巧

1. 表單組件

el-form深度驗(yàn)證

<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="rules"
    label-width="120px"
  >
    <el-form-item label="標(biāo)題" prop="title">
      <el-input v-model="formData.title" />
    </el-form-item>

    <el-form-item label="郵箱" prop="email">
      <el-input v-model="formData.email" />
    </el-form-item>

    <el-form-item label="密碼" prop="password">
      <el-input
        v-model="formData.password"
        type="password"
        show-password
      />
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="handleSubmit">
        提交
      </el-button>
      <el-button @click="handleReset">
        重置
      </el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'

const formRef = ref<FormInstance>()

const formData = reactive({
  title: '',
  email: '',
  password: ''
})

const rules = reactive<FormRules>({
  title: [
    { required: true, message: '請輸入標(biāo)題', trigger: 'blur' },
    { min: 2, max: 50, message: '長度在 2 到 50 個(gè)字符', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '請輸入郵箱地址', trigger: 'blur' },
    { type: 'email', message: '請輸入正確的郵箱地址', trigger: ['blur', 'change'] }
  ],
  password: [
    { required: true, message: '請輸入密碼', trigger: 'blur' },
    { min: 6, message: '密碼長度不能少于 6 位', trigger: 'blur' }
  ]
})

const handleSubmit = async () => {
  if (!formRef.value) return

  await formRef.value.validate((valid, fields) => {
    if (valid) {
      // 驗(yàn)證通過,提交表單
      console.log('提交:', formData)
    } else {
      console.log('驗(yàn)證失敗:', fields)
    }
  })
}

const handleReset = () => {
  formRef.value?.resetFields()
}
</script>

動(dòng)態(tài)表單

<template>
  <el-form :model="formData">
    <el-form-item
      v-for="(item, index) in formData.items"
      :key="index"
      :label="'項(xiàng)目 ' + (index + 1)"
    >
      <el-input v-model="item.value" />
      <el-button
        @click="removeItem(index)"
        icon="Delete"
        type="danger"
      >
        刪除
      </el-button>
    </el-form-item>

    <el-button @click="addItem" icon="Plus">
      添加項(xiàng)目
    </el-button>
  </el-form>
</template>

<script setup lang="ts">
const formData = reactive({
  items: [{ value: '' }]
})

const addItem = () => {
  formData.items.push({ value: '' })
}

const removeItem = (index: number) => {
  formData.items.splice(index, 1)
}
</script>

2. 表格組件

表格排序和篩選

<template>
  <el-table
    :data="filteredData"
    :default-sort="{ prop: 'date', order: 'descending' }"
    @sort-change="handleSortChange"
  >
    <el-table-column prop="title" label="標(biāo)題" sortable />
    <el-table-column
      prop="category"
      label="分類"
      :filters="categoryFilters"
      :filter-method="filterCategory"
    />
    <el-table-column prop="views" label="瀏覽量" sortable />
    <el-table-column prop="date" label="日期" sortable />
  </el-table>
</template>

<script setup lang="ts">
const articles = ref<Article[]>([])

const filteredData = computed(() => {
  return articles.value
})

const categoryFilters = [
  { text: 'Vue', value: 'Vue' },
  { text: 'React', value: 'React' },
  { text: 'TypeScript', value: 'TypeScript' }
]

const filterCategory = (value: string, row: Article) => {
  return row.category === value
}

const handleSortChange = (sort: any) => {
  console.log('排序改變:', sort)
}
</script>

表格分頁

<template>
  <el-table :data="paginatedData">
    <!-- 列定義 -->
  </el-table>

  <el-pagination
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :total="total"
    :page-sizes="[10, 20, 50, 100]"
    layout="total, sizes, prev, pager, next, jumper"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />
</template>

<script setup lang="ts">
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

const paginatedData = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return articles.value.slice(start, end)
})

const handleSizeChange = (size: number) => {
  pageSize.value = size
}

const handleCurrentChange = (page: number) => {
  currentPage.value = page
}
</script>

3. 彈窗組件

對話框嵌套

<template>
  <el-button @click="showDialog = true">打開對話框</el-button>

  <el-dialog v-model="showDialog" title="父對話框">
    <p>這是父對話框的內(nèi)容</p>

    <el-button @click="showChildDialog = true">
      打開子對話框
    </el-button>

    <el-dialog
      v-model="showChildDialog"
      title="子對話框"
      append-to-body
    >
      <p>這是子對話框的內(nèi)容</p>
    </el-dialog>
  </el-dialog>
</template>

<script setup lang="ts">
const showDialog = ref(false)
const showChildDialog = ref(false)
</script>

注意:嵌套對話框時(shí),子對話框需要添加append-to-body屬性。

4. 樹形組件

異步加載樹

<template>
  <el-tree
    :props="defaultProps"
    :load="loadNode"
    lazy
    show-checkbox
  />
</template>

<script setup lang="ts">
const defaultProps = {
  label: 'name',
  children: 'children',
  isLeaf: 'leaf'
}

const loadNode = async (node: Node, resolve: (data: TreeData[]) => void) => {
  if (node.level === 0) {
    // 加載根節(jié)點(diǎn)
    const data = await loadRootNodes()
    resolve(data)
  } else {
    // 加載子節(jié)點(diǎn)
    const data = await loadChildNodes(node.data.id)
    resolve(data)
  }
}

const loadRootNodes = async () => {
  // 異步加載數(shù)據(jù)
  return [
    { name: '節(jié)點(diǎn)1', id: 1 },
    { name: '節(jié)點(diǎn)2', id: 2 }
  ]
}
</script>

主題定制

1. 使用CSS變量

// styles/theme.scss
:root {
  --el-color-primary: #409eff;
  --el-color-success: #67c23a;
  --el-color-warning: #e6a23c;
  --el-color-danger: #f56c6c;
  --el-color-info: #909399;
}

// 使用自定義主題
$--color-primary: var(--el-color-primary);

2. SCSS變量覆蓋

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ElementPlus from 'unplugin-element-plus/vite'

export default defineConfig({
  plugins: [
    vue(),
    ElementPlus({
      // 使用scss樣式
      useSource: true
    })
  ]
})
// styles/element-variables.scss
/* 改變主題色變量 */
$--color-primary: #1890ff;
$--color-success: #52c41a;
$--color-warning: #faad14;
$--color-danger: #f5222d;
$--color-info: #909399;

/* 改變icon字體路徑變量,必需 */
$--font-path: '~element-plus/lib/theme-chalk/fonts';

@import "~element-plus/packages/theme-chalk/src/index";

3. 暗黑模式

<template>
  <el-switch
    v-model="isDark"
    @change="toggleDark"
    inline-prompt
    active-text="暗"
    inactive-text="亮"
  />
</template>

<script setup lang="ts">
const isDark = ref(false)

const toggleDark = (value: boolean) => {
  if (value) {
    document.documentElement.classList.add('dark')
  } else {
    document.documentElement.classList.remove('dark')
  }
}
</script>

<style>
/* 暗黑模式樣式 */
html.dark {
  --el-bg-color: #141414;
  --el-text-color-primary: #e5eaf3;
  --el-border-color: #4c4d4f;
  --el-border-color-light: #414243;
}
</style>

性能優(yōu)化

1. 圖標(biāo)按需加載

// utils/icons.ts
import { registerIcons } from 'element-plus/es/components/icon'

// 只注冊需要的圖標(biāo)
export function lazyRegisterIcons() {
  const icons = [
    'Edit',
    'Delete',
    'View',
    'Download',
    'Share',
    'Star',
    'Plus',
    'Search',
    'Home'
  ]

  // 使用requestIdleCallback在空閑時(shí)注冊
  const idleCallback = window.requestIdleCallback || window.setTimeout

  idleCallback(() => {
    registerIcons(icons)
  })
}

// main.ts
import { lazyRegisterIcons } from './utils/icons'
lazyRegisterIcons()

2. 虛擬滾動(dòng)

<template>
  <el-virtual-list
    :data="items"
    :height="400"
    :item-size="50"
  >
    <template #default="{ item, index }">
      <div class="item">
        {{ index }} - {{ item.name }}
      </div>
    </template>
  </el-virtual-list>
</template>

<script setup lang="ts">
import { ElVirtualList } from 'element-plus'

// 生成大量數(shù)據(jù)
const items = Array.from({ length: 10000 }, (_, i) => ({
  id: i,
  name: `Item ${i}`
}))
</script>

踩坑記錄

1. Dialog關(guān)閉不觸發(fā)事件

問題:點(diǎn)擊遮罩層關(guān)閉Dialog時(shí),沒有觸發(fā)關(guān)閉事件。

解決:使用before-close屬性:

<el-dialog
  v-model="visible"
  :before-close="handleClose"
>
  <template #header>
    <span>標(biāo)題</span>
  </template>
</el-dialog>

<script setup lang="ts">
const handleClose = (done: () => void) => {
  // 執(zhí)行關(guān)閉前的邏輯
  done()
}
</script>

2. Table固定列錯(cuò)位

問題:表格固定列在滾動(dòng)時(shí)出現(xiàn)錯(cuò)位。

解決:監(jiān)聽窗口大小變化,調(diào)用doLayout方法:

<template>
  <el-table
    ref="tableRef"
    :data="tableData"
  >
    <el-table-column prop="date" label="日期" fixed />
    <el-table-column prop="name" label="姓名" />
  </el-table>
</template>

<script setup lang="ts">
const tableRef = ref()

onMounted(() => {
  window.addEventListener('resize', () => {
    tableRef.value?.doLayout()
  })
})
</script>

3. Select下拉框顯示位置錯(cuò)誤

問題:Select組件的下拉框在頁面滾動(dòng)后顯示位置錯(cuò)誤。

解決:使用popper-options配置:

<el-select
  v-model="value"
  :popper-options="{
    modifiers: [
      {
        name: 'flip',
        options: {
          fallbackPlacements: ['bottom-start', 'top-start']
        }
      }
    ]
  }"
>
  <el-option
    v-for="item in options"
    :key="item.value"
    :label="item.label"
    :value="item.value"
  />
</el-select>

4. DatePicker時(shí)間格式問題

問題:DatePicker返回的日期格式不符合預(yù)期。

解決:使用value-format屬性:

<el-date-picker
  v-model="date"
  type="datetime"
  value-format="YYYY-MM-DD HH:mm:ss"
  placeholder="選擇日期時(shí)間"
/>

5. Upload組件上傳失敗

問題:Upload組件在某些情況下上傳失敗。

解決:正確處理on-successon-error回調(diào):

<el-upload
  action="/api/upload"
  :on-success="handleSuccess"
  :on-error="handleError"
  :before-upload="beforeUpload"
>
  <el-button type="primary">上傳文件</el-button>
</el-upload>

<script setup lang="ts">
const handleSuccess = (response: any, file: any) => {
  if (response.code === 200) {
    ElMessage.success('上傳成功')
  } else {
    ElMessage.error(response.message)
  }
}

const handleError = (error: any) => {
  ElMessage.error('上傳失?。? + error.message)
}

const beforeUpload = (file: File) => {
  const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
  const isLt2M = file.size / 1024 / 1024 < 2

  if (!isJPG) {
    ElMessage.error('只能上傳JPG/PNG圖片!')
  }
  if (!isLt2M) {
    ElMessage.error('圖片大小不能超過2MB!')
  }
  return isJPG && isLt2M
}
</script>

最佳實(shí)踐

1. 統(tǒng)一配置

// config/element-plus.ts
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'

export default {
  locale: zhCn,
  size: 'default',
  zIndex: 3000
}
<!-- App.vue -->
<template>
  <el-config-provider :locale="locale">
    <router-view />
  </el-config-provider>
</template>

<script setup lang="ts">
import zhCn from 'element-plus/es/locale/lang/zh-cn'
const locale = zhCn
</script>

2. 封裝常用組件

<!-- components/SearchInput.vue -->
<template>
  <el-input
    v-model="searchText"
    :placeholder="placeholder"
    clearable
    @clear="handleClear"
    @input="handleInput"
  >
    <template #prefix>
      <el-icon><Search /></el-icon>
    </template>
    <template #suffix>
      <el-button
        v-if="searchText"
        link
        icon="Close"
        @click="handleClear"
      />
    </template>
  </el-input>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'

interface Props {
  modelValue: string
  placeholder?: string
}

const props = withDefaults(defineProps<Props>(), {
  placeholder: '請輸入搜索內(nèi)容'
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
  (e: 'search', value: string): void
}>()

const searchText = ref(props.modelValue)

watch(() => props.modelValue, (val) => {
  searchText.value = val
})

watch(searchText, (val) => {
  emit('update:modelValue', val)
})

const handleClear = () => {
  searchText.value = ''
  emit('search', '')
}

const handleInput = debounce((value: string) => {
  emit('search', value)
}, 300)
</script>

3. 全局樣式覆蓋

// styles/element-overrides.scss

// 全局修改el-button樣式
.el-button {
  border-radius: 4px;
  font-weight: 500;

  &--primary {
    background-color: #1890ff;
    border-color: #1890ff;

    &:hover {
      background-color: #40a9ff;
      border-color: #40a9ff;
    }
  }
}

// 修改el-dialog樣式
.el-dialog {
  border-radius: 8px;
  overflow: hidden;

  .el-dialog__header {
    padding: 20px 20px 10px;
    border-bottom: 1px solid #f0f0f0;
  }

  .el-dialog__body {
    padding: 20px;
  }
}

總結(jié)

Element Plus是一個(gè)功能強(qiáng)大、設(shè)計(jì)優(yōu)秀的UI組件庫,掌握以下要點(diǎn)可以更好地使用它:

  1. 按需引入 - 減小包體積
  2. 主題定制 - 符合項(xiàng)目風(fēng)格
  3. 性能優(yōu)化 - 圖標(biāo)懶加載、虛擬滾動(dòng)
  4. 踩坑經(jīng)驗(yàn) - 了解常見問題和解決方案
  5. 最佳實(shí)踐 - 封裝常用組件、統(tǒng)一配置

希望這些經(jīng)驗(yàn)?zāi)軒椭阍赩ue 3項(xiàng)目中更好地使用Element Plus!

到此這篇關(guān)于Vue 3項(xiàng)目中Element Plus組件庫實(shí)戰(zhàn)技巧與踩坑記錄的文章就介紹到這了,更多相關(guān)Element Plus組件庫技巧與踩坑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue如何使用AIlabel標(biāo)注組件

    vue如何使用AIlabel標(biāo)注組件

    這篇文章主要介紹了vue如何使用AIlabel標(biāo)注組件,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue 屬性攔截實(shí)現(xiàn)雙向綁定的實(shí)例代碼

    vue 屬性攔截實(shí)現(xiàn)雙向綁定的實(shí)例代碼

    這篇文章主要介紹了vue 屬性攔截實(shí)現(xiàn)雙向綁定的實(shí)例代碼,代碼簡答易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-10-10
  • vant使用datetime-picker組件設(shè)置maxDate和minDate的坑及解決

    vant使用datetime-picker組件設(shè)置maxDate和minDate的坑及解決

    這篇文章主要介紹了vant使用datetime-picker組件設(shè)置maxDate和minDate的坑及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Vue3中關(guān)于路由規(guī)則的props配置方式

    Vue3中關(guān)于路由規(guī)則的props配置方式

    這篇文章主要介紹了Vue3中關(guān)于路由規(guī)則的props配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue 項(xiàng)目中實(shí)現(xiàn)按鈕防抖方法

    vue 項(xiàng)目中實(shí)現(xiàn)按鈕防抖方法

    這篇文章主要介紹了vue 項(xiàng)目中實(shí)現(xiàn)按鈕防抖方法,首先需要新建 .js文件存放防抖方法,引入防抖文件,methods中添加方法,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • Vue Element前端應(yīng)用開發(fā)之組織機(jī)構(gòu)和角色管理

    Vue Element前端應(yīng)用開發(fā)之組織機(jī)構(gòu)和角色管理

    本篇文章繼續(xù)深化Vue Element權(quán)限管理模塊管理的內(nèi)容,介紹組織機(jī)構(gòu)和角色管理模塊的處理,使得我們了解界面組件化模塊的開發(fā)思路和做法,提高我們界面設(shè)計(jì)的技巧,并減少代碼的復(fù)雜性,提高界面代碼的可讀性,同時(shí)也是利用組件的復(fù)用管理。
    2021-05-05
  • VuePress 快速踩坑小結(jié)

    VuePress 快速踩坑小結(jié)

    VuePress 可以讓您非常方便的在 Markdown 文檔中編寫 Vue 代碼,這篇文章主要介紹了VuePress 快速踩坑小結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-02-02
  • keep-alive緩存某一指定路由實(shí)現(xiàn)方式

    keep-alive緩存某一指定路由實(shí)現(xiàn)方式

    使用路由元信息配合keep-alive實(shí)現(xiàn)條件緩存,通過兩個(gè)router-view和meta變量判斷是否緩存特定路由,注意keep-alive優(yōu)先使用組件的name屬性而非路由name,避免常見錯(cuò)誤
    2025-07-07
  • Vue進(jìn)度條progressbar組件功能

    Vue進(jìn)度條progressbar組件功能

    progressbar組件在一個(gè)可以直接運(yùn)行的npm包,通過Yeoman進(jìn)行構(gòu)建,再通過Gulp+Webpack構(gòu)建工具。這篇文章給大家介紹了Vue進(jìn)度條progressbar組件
    2018-04-04
  • 解決在vue項(xiàng)目中,發(fā)版之后,背景圖片報(bào)錯(cuò),路徑不對的問題

    解決在vue項(xiàng)目中,發(fā)版之后,背景圖片報(bào)錯(cuò),路徑不對的問題

    下面小編就為大家分享一篇解決在vue項(xiàng)目中,發(fā)版之后,背景圖片報(bào)錯(cuò),路徑不對的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03

最新評論

长葛市| 汝阳县| 绩溪县| 葵青区| 广饶县| 乃东县| 黄冈市| 南昌市| 汉川市| 普安县| 明星| 清涧县| 禹州市| 云浮市| 惠来县| 怀柔区| 建宁县| 永泰县| 赫章县| 巫山县| 昌邑市| 拜泉县| 阳高县| 广德县| 大城县| 庆安县| 斗六市| 高雄市| 云南省| SHOW| 井陉县| 西畴县| 康定县| 务川| 图们市| 库尔勒市| 长汀县| 阿图什市| 林周县| 乡城县| 海城市|