【卷起来】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>
相关推荐
狗头大军之江苏分军16 分钟前
iPhone 17 vs iPhone 17 Pro:到底差在哪?买前别被忽悠了
前端
小林coding16 分钟前
再也不怕面试了!程序员 AI 面试练习神器终于上线了
前端·后端·面试
文心快码BaiduComate28 分钟前
WAVE SUMMIT深度学习开发者大会2025举行 文心大模型X1.1发布
前端·后端·程序员
babytiger29 分钟前
python 通过selenium调用chrome浏览器
前端·chrome
passer98135 分钟前
基于webpack的场景解决
前端·webpack
华科云商xiao徐42 分钟前
Java并发编程常见“坑”与填坑指南
javascript·数据库·爬虫
奶昔不会射手1 小时前
css3之grid布局
前端·css·css3
举个栗子dhy1 小时前
解决在父元素上同时使用 onMouseEnter和 onMouseLeave时导致下拉菜单无法正常展开或者提前收起问题
前端·javascript·react.js