【卷起来】VUE3.0教程-09-整合Element-plus

====最后一次课了,给个关注和赞呗

🌲 简介

Element Plus 是一个基于 Vue 3 的高质量 UI 组件库。它包含了丰富的组件和扩展功能,例如表格、表单、按钮、导航、通知等,让开发者能够快速构建高质量的 Web 应用。Element Plus 的设计理念是:提供开箱即用的 UI 组件和扩展功能,帮助开发者快速构建应用程序,同时提供详细的文档和教程,让开发者更好地掌握和使用 Element Plus。

🌲 安装Element-plus

🌿 安装element-plus

复制代码
npm install element-plus

🌿 完整引用

如果你对打包后的文件大小不是很在乎,那么可以将element-plus所有内容全部导入到项目中(不建议)

java 复制代码
import { createApp } from 'vue'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

🌿 按需导入

按需导入才是我们实际需要用的,毕竟在真实的应用场景中并不是每个组件都会用到,这会造成不小的浪费。

首先我们需要安装 unplugin-vue-components 和 unplugin-auto-import 两款插件

复制代码
npm install -D unplugin-vue-components unplugin-auto-import

然后修改vite.config.js配置文件,在plugins插件中添加AutoImport和Components相关配置

java 复制代码
import { fileURLToPath, URL } from 'node:url'

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'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers:[ElementPlusResolver()],
    }),
    Components({
      resolvers:[ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

最后可以直接在组件中使用了

html 复制代码
<script setup>

</script>

<template>
  <el-button type="primary">Primary</el-button>
</template>

<style scoped>

</style>

🌲 加载Element-plus字体图标

Element 不仅仅是提供了各种组件,同时还提供了一整套的字体图标方便开发者使用。

🌿 安装icons字体图标

复制代码
npm install @element-plus/icons-vue

🌿 全局注册

在根目录下,创建plugins文件夹,在文件夹下创建icons.js文件

javascript 复制代码
import * as components from "@element-plus/icons-vue"

export default{
    install:(app)=>{
        for(const key in components){
            const componentConfig = components[key];
            app.component(componentConfig.name,componentConfig);
        }
    }
}

🌿 引入文件

在main.js引入icons.js

javascript 复制代码
import { createApp } from 'vue'

// import ElementPlus from 'element-plus'
// import 'element-plus/dist/index.css'
import App from './App.vue'

import elementIcon from './plugins/icons'

const app = createApp(App)
// app.use(ElementPlus)
app.use(elementIcon)
app.mount('#app')

🌿 使用方式

接下来,就可以直接在组件中引入使用了

javascript 复制代码
<template>
  <el-button type="primary">Primary</el-button>
  <el-icon class="expand" color="#409efc">
    <expand/>
  </el-icon>
</template>

展示效果:

🌲 表单:登录页面

html 复制代码
<template>

    <div>
        
    </div>
    <el-form :model="form"  style="width:500px" >
        
        <el-text class="mx-1" type="primary" >
            <h2 style="text-align: center;">用户登录</h2>
        </el-text>
        <el-form-item label="账  号">
          <el-input v-model="form.username" />
        </el-form-item>
        <el-form-item label="密  码">
            <!-- 使用 show-password 属性即可得到一个可切换显示隐藏的密码框  -->
          <el-input v-model="form.password" type="password" show-password/>
        </el-form-item>
        <el-form-item label-width="45px">
            <!-- 设置按钮大小时,需要先设置size,然后再设置style中的width和height -->
            <el-button type="primary" @click="onSubmit()" size="large" style="width: 100px;">登录</el-button>
            <el-button type="danger" @click="onReset()" size="large" style="width: 100px;">取消</el-button>
        </el-form-item>
    </el-form>
</template>

<script lang="ts" setup>
    import { reactive } from 'vue'

    // do not use same name with ref
    const form = reactive({
        username: '',
        password: ''
        
    })

    const onSubmit = () => {
        console.log('submit!')
    }

    const onReset = ()=>{
      form.username = ""
      form.password = ""
    }
</script>

🌲 列表:英雄列表

🌿 页面内容

html 复制代码
<template>
    <!-- :data  配置查询到的列表数据源 -->
    <el-table
        ref="multipleTableRef"
        :data="tableData"
        style="width: 100%"
        @selection-change="handleSelectionChange"
    >
        <el-table-column type="selection" width="55" />
        <el-table-column label="序号" width="120">
        
        </el-table-column>
        <!--  -->
        <el-table-column property="hname" label="英雄名称"  />
        <el-table-column property="job" label="英雄职业" />
        <el-table-column property="sex" label="英雄性别"  />
        <el-table-column property="level" label="英雄技能"  />
        <el-table-column label="操作">
            <template #default="scope">
                <el-button size="small" @click="handleEdit(scope.$index, scope.row)">修改</el-button>
                <el-button
                    size="small"
                    type="danger"
                    @click="handleDelete(scope.$index, scope.row)">删除</el-button>
      </template>
    </el-table-column>
    </el-table>
    <div style="margin-top: 20px">
        <el-button @click="toggleSelection([tableData[1], tableData[2]])">Toggle selection status of second and third rows</el-button>
        <el-button @click="toggleSelection()">Clear selection</el-button>
    </div>
</template>
<script setup>
</script>
  • 从scope中可以获取当前行的数据

🌿 异步请求数据

html 复制代码
<script setup>
   import {ref,computed,reactive} from 'vue'
    import axios from 'axios'
    import qs from 'querystring'
    import router from '../router';

    // 此处的tableData是上面模板中table里:data所对应的名称
    const tableData = ref([{}]);// 表格数据实际上是一个对象数组
    

    const load_list = ()=>{
        // 异步请求列表数据
        axios.get("/api/hero").then(res=>{
                console.log(res.data);
                tableData.value = res.data.data;
        });
    }
    load_list()
   
</script>

此处get请求对应的请求地址为之前我们使用SpringBoot编写好的请求。

🌿 修改数据

html 复制代码
<!-- 修改数据对话框 -->
<el-dialog v-model="dialogFormVisible" title="修改英雄数据">
        <el-form :model="form">
            <el-form-item label="英雄名称" :label-width="formLabelWidth">
                <el-input v-model="form.hname" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄职业" :label-width="formLabelWidth">
                <el-input v-model="form.job" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄性别" :label-width="formLabelWidth">
                <el-radio-group v-model="form.sex">
                    <el-radio label="男" />
                    <el-radio label="女" />
                </el-radio-group>
            </el-form-item>
            <el-form-item label="英雄等级" :label-width="formLabelWidth">
                <el-input v-model="form.level" autocomplete="off" />
            </el-form-item>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogFormVisible = false">Cancel</el-button>
                <el-button type="primary" @click="dialogFormVisible = false">
                Confirm
                </el-button>
            </span>
        </template>
  </el-dialog>

这个对话框是通过一个"dialogFormVisible"响应式属性来控制的,在上面点击修改时,可以将这个值设置为true。

而:<el-form :model="form">中的这个响应式属性值form是用来绑定表单的属性值的。

基本逻辑是,点击修改时,将对话框的dialogFormVisible的value值设置为true,并且将从表格中获取到的行数据给到form的value。

html 复制代码
const dialogFormVisible = ref(false); // 弹出对话框
const formLabelWidth = '140px';
const form = ref({}) // 定义表单中的数据
  
const handleEdit = (row)=>{
	console.log(row.id)
  // 显示对话框
  dialogFormVisible.value = true;
  form.value = row
}

实现提交修改按钮中的方法updateHero方法:

javascript 复制代码
 const updateHero = ()=>{
        axios.put('/api/hero',
        qs.stringify(form.value))
            .then(res=>{
                if(res.data.code=='0000'){
                    dialogFormVisible.value = false;
                }else{
                    alert("系统繁忙...请稍后重试")
                }
            });
}

🌿 删除数据

  • 实现删除按钮中的handleDelete方法,打开确认删除对话框
javascript 复制代码
//-----------------------------------------------------
  // 删除数据提醒框
  const centerDialogVisible = ref(false);
  const handleDelete=(row)=>{
    centerDialogVisible.value = true
    form.value = row

  }
  • 删除数据提醒框:
html 复制代码
<!-- 删除数据提醒框 -->
  <el-dialog v-model="centerDialogVisible" title="提示信息" width="30%" center>
    <div align="center">
        是否确定删除此条数据?
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="centerDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="deleteHero(form.id)">
        删除
        </el-button>
      </span>
    </template>
  </el-dialog>
  • deleteHero删除数据的方法
javascript 复制代码
// 删除数据
const deleteHero=(id)=>{

  axios.delete(`/api/hero/${id}`).then(res=>{
    if(res.data.code=='0000'){
      centerDialogVisible.value = false
      load_list()
    }else{
      alert("系统繁忙...请稍后重试")
    }
  })

}

🌿 新增数据

  • 新增数据的对话框
html 复制代码
<!-- 新增数据对话框 -->
<el-dialog v-model="dialogAddHero" title="添加英雄数据">
  <el-form :model="hero">
    <el-form-item label="英雄名称" :label-width="formLabelWidth">
      <el-input v-model="hero.hname" autocomplete="off" />
    </el-form-item>
    <el-form-item label="英雄职业" :label-width="formLabelWidth">
      <el-input v-model="hero.job" autocomplete="off" />
    </el-form-item>
    <el-form-item label="英雄性别" :label-width="formLabelWidth">
      <el-radio-group v-model="hero.sex">
        <el-radio label="男" />
          <el-radio label="女" />
      </el-radio-group>
     </el-form-item>
     <el-form-item label="英雄等级" :label-width="formLabelWidth">
              <el-input v-model="hero.level" autocomplete="off" />
      </el-form-item>
    </el-form>
    <template #footer>
              <span class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取消</el-button>
                <el-button type="primary" @click="addHeroData(hero)">
                  确定
                </el-button>
              </span>
    </template>
</el-dialog>
  • js代码如下
javascript 复制代码
//-----------------------------------------------
// 打开添加英雄数据对话框
const  dialogAddHero = ref(false)
const hero = reactive({})
const isDark = ref(true)
const openAdd = ()=>{
  dialogAddHero.value = true
}
const addHeroData= (hero)=>{
  axios.post("/api/hero",qs.stringify(hero)).then(res=>{
    if(res.data.code=="0000"){
      dialogAddHero.value = false;
      alert("添加成功");
      load_list()
    }else{
      alert("系统繁忙...请稍后重试")
    }
  })

}

🌿 分页查询

  • 添加分页插件
html 复制代码
<!-- 分页 -->
<div>
  <el-pagination 
    style="margin: 30px 180px;"
    :background = 'true'
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="[5, 15, 20, 50,100]"
    :small="true"
    :disabled="false"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    />
</div>
  • 添加更改当前页数,以及每页显示总条目数的方法
javascript 复制代码
const pageSize = ref(5)
const currentPage = ref(1)
const total = ref(0)

const handleSizeChange = (val)=>{
  pageSize.value = val
  load_list();

}
const handleCurrentChange = (val) => {
  currentPage.value = val
  load_list()
}
  • 修改查询异步请求地址
javascript 复制代码
const load_list = ()=>{
  // 异步请求列表数据
  axios.get(`/api/hero/${currentPage.value}/${pageSize.value}`,).then(res=>{
    console.log("..."+res.data.data);
    tableData.value = res.data.data.list;
    total.value = res.data.data.total
  });

}
load_list()
  • 修改后端添加分页插件
html 复制代码
<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper-spring-boot-starter</artifactId>
  <version>1.4.1</version>
</dependency>
  • 添加分页插件配置
html 复制代码
# 数据库方言
pagehelper.helper-dialect=mysql
# 分页合理化
pagehelper.reasonable=true
# 是否支持接口参数来传递分页参数,默认为false
pagehelper.support-methods-arguments=true
# 当设置为true的时候,如果pagesize设置为0(或者RowBounds的limit=0),就不执行分页,查询所有
pagehelper.page-size-zero=true
pagehelper.params=count=countSql
  • 修改接口方法,接收传过来的分页参数
java 复制代码
@Autowired
private IHeroService service;
@GetMapping("/hero/{currentPage}/{pageSize}")
public Result getHeros(@PathVariable int currentPage,@PathVariable int pageSize){
    log.info("查询所有的用户");
    return service.getHeros(currentPage,pageSize);
}
  • 修改Service方法,返回pageInfo对象
java 复制代码
public Result getHeros(int currentPage, int pageSize) {
    currentPage= currentPage ==0?1:currentPage;
    pageSize= pageSize==0?5:pageSize;
    // 设置分页起始页以及每页显示的条目总数量
    PageHelper.startPage(currentPage,pageSize);

    List<Hero> heroList = heroMapper.selectList(null);
    // 调用业务层处理业务逻辑,最终返回一个PageInfo对象,pageInfo对象包含了
    // 分页数据。包括:数据源,总页数,总条目数,当前页数等等
    PageInfo<Hero> pageInfo = new PageInfo<>(heroList);
    return Result.sendResult(ReturnCode.SUCCESS,pageInfo);
}

🌲前端完整代码

🌿 跨域和按需引入EL-PLUS

  • 解决跨域问题:vite.config.js
javascript 复制代码
import { fileURLToPath, URL } from 'node:url'

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'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers:[ElementPlusResolver()],
    }),
    Components({
      resolvers:[ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  server:{
    proxy:{
      // 配置代理请求前缀
      // 当vue发送localhost:5173/api/xxx请求时
      '/api': {
        // 实际上执行的是 http://localhost:8080/xxx
        target: 'http://localhost:8080/',
        changeOrigin: true,
        // 到达真实服务器地址时,去掉请求前缀/api
        // 比如前端发送请求http://localhost:5173/api/hero
        // 经过rewrite重写后会变成:http://localhost:8080/hero
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

🌿 引入EL-PLUS图标

javascript 复制代码
import * as components from "@element-plus/icons-vue"

export default{
    install:(app)=>{
        for(const key in components){
            const componentConfig = components[key];
            app.component(componentConfig.name,componentConfig);
        }
    }
}

🌿 英雄列表页面

html 复制代码
<template>
    <br/>
    <el-button color="#626aef" :dark="isDark" @click="openAdd()">+ 新增英雄</el-button>
    <el-button color="#ff0000" :dark="isDark">- 批量删除</el-button>
    <br/>
    <br/>
    <!-- :data  配置查询到的列表数据源 -->
    <el-table
        ref="multipleTableRef"
        :data="tableData"
        style="width: 100%"
        text-align="center">
        <el-table-column type="selection" width="55" />
        <el-table-column type="index" :index="indexMethod" label="序号" width="120" align="center">
        </el-table-column>
        <!--  -->
        <el-table-column property="hname" label="英雄名称"  align="center"/>
        <el-table-column property="job" label="英雄职业" align="center"/>
        <el-table-column property="sex" label="英雄性别"  align="center"/>
        <el-table-column property="level" label="英雄技能"  align="center"/>
        <el-table-column label="操作" align="center">
            <template #default="scope">
                <el-button size="small" @click="handleEdit(scope.row)">修改</el-button>
                <el-button
                    size="small"
                    type="danger"
                    @click="handleDelete(scope.row)">删除</el-button>
            </template>
        </el-table-column>
       
    </el-table>
       <!-- 分页 -->
       <div>
            <el-pagination 
                style="margin: 30px 180px;"
                :background = 'true'
                v-model:current-page="currentPage"
                v-model:page-size="pageSize"
                :page-sizes="[5, 15, 20, 50,100]"
                :small="true"
                :disabled="false"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
                />
        </div>
   
<!-- 修改数据对话框 -->
    <el-dialog v-model="dialogFormVisible" title="修改英雄数据">
        <el-form :model="form">
            <el-form-item label="英雄名称" :label-width="formLabelWidth">
                <el-input v-model="form.hname" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄职业" :label-width="formLabelWidth">
                <el-input v-model="form.job" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄性别" :label-width="formLabelWidth">
                <el-radio-group v-model="form.sex">
                    <el-radio label="男" />
                    <el-radio label="女" />
                </el-radio-group>
            </el-form-item>
            <el-form-item label="英雄等级" :label-width="formLabelWidth">
                <el-input v-model="form.level" autocomplete="off" />
            </el-form-item>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取消</el-button>
                <el-button type="primary" @click="updateHero">
                确定
                </el-button>
            </span>
        </template>
  </el-dialog>

<!-- 删除数据提醒框 -->
  <el-dialog v-model="centerDialogVisible" title="提示信息" width="30%" center>
    <div align="center">
        是否确定删除此条数据?
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="centerDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="deleteHero(form.id)">
        删除
        </el-button>
      </span>
    </template>
  </el-dialog>

    <!-- 新增数据对话框 -->
    <el-dialog v-model="dialogAddHero" title="添加英雄数据">
        <el-form :model="hero">
            <el-form-item label="英雄名称" :label-width="formLabelWidth">
                <el-input v-model="hero.hname" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄职业" :label-width="formLabelWidth">
                <el-input v-model="hero.job" autocomplete="off" />
            </el-form-item>
            <el-form-item label="英雄性别" :label-width="formLabelWidth">
                <el-radio-group v-model="hero.sex">
                    <el-radio label="男" />
                    <el-radio label="女" />
                </el-radio-group>
            </el-form-item>
            <el-form-item label="英雄等级" :label-width="formLabelWidth">
                <el-input v-model="hero.level" autocomplete="off" />
            </el-form-item>
        </el-form>
        <template #footer>
            <span class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取消</el-button>
                <el-button type="primary" @click="addHeroData(hero)">
                确定
                </el-button>
            </span>
        </template>
  </el-dialog>
</template>
<script setup>
    import {ref,computed,reactive} from 'vue'
    import axios from 'axios'
    import qs from 'querystring'
    import router from '../router';

    // 此处的tableData是上面模板中table里:data所对应的名称
    const tableData = ref([{}]);// 表格数据实际上是一个对象数组
    
    const pageSize = ref(5)
    const currentPage = ref(1)
    const total = ref(0)

    const handleSizeChange = (val)=>{
        pageSize.value = val
        load_list();

    }
    const handleCurrentChange = (val) => {
        currentPage.value = val
        load_list()
    }
    const load_list = ()=>{
        // 异步请求列表数据
        axios.get(`/api/hero/${currentPage.value}/${pageSize.value}`,).then(res=>{
                console.log("..."+res.data.data);
                tableData.value = res.data.data.list;
                total.value = res.data.data.total
        });

    }
    load_list()
   

    const indexMethod = (index)=>{
        return index +1
    }

    //---------------------------------------------
    // 修改数据对话框
    const dialogFormVisible = ref(false); // 弹出对话框
    const formLabelWidth = '140px';
    const form = ref({}) // 定义表单中的数据
    // 弹出修改数据对话框
    const handleEdit = (row)=>{
        // 显示对话框
        dialogFormVisible.value = true;
        form.value = row

    }
    // 修改数据
    const updateHero = ()=>{
        axios.put('/api/hero',
            qs.stringify(form.value)).then(res=>{
                if(res.data.code=='0000'){
                    dialogFormVisible.value = false;
                    
                }else{
                    alert("系统繁忙...请稍后重试")
                }
            });
    }

    //-----------------------------------------------------
    // 删除数据提醒框
    const centerDialogVisible = ref(false);
    const handleDelete=(row)=>{
        centerDialogVisible.value = true
        form.value = row

    }
    // 删除数据
    const deleteHero=(id)=>{
        
        axios.delete(`/api/hero/${id}`).then(res=>{
            if(res.data.code=='0000'){
                centerDialogVisible.value = false
                load_list()
            }else{
                alert("系统繁忙...请稍后重试")
            }
        })

    }

    //-----------------------------------------------
    // 打开添加英雄数据对话框
    const  dialogAddHero = ref(false)
    const hero = reactive({})
    const isDark = ref(true)
    const openAdd = ()=>{
        dialogAddHero.value = true
    }
    const addHeroData= (hero)=>{
        axios.post("/api/hero",qs.stringify(hero)).then(res=>{
            if(res.data.code=="0000"){
                dialogAddHero.value = false;
                alert("添加成功");
                load_list()
            }else{
                alert("系统繁忙...请稍后重试")
            }
        })

    }

</script>

<style scoped>
    .el-button--text {
        margin-right: 15px;
    }
    .el-select {
     width: 300px;
    }
    .el-input {
        width: 300px;
    }
    .dialog-footer button:first-child {
        margin-right: 10px;
    }
</style>
相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
猫头虎5 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端