Vue工程化/TS/ElementPlus

YangeIT大约 40 分钟Maven基础框架私服聚合继承依赖传递

Vue工程化/TS/ElementPlus

今日目标

目标

前面我们在介绍Vue的时候,我们讲到Vue是一款用于构建用户界面的渐进式JavaScript框架 。(官方:https://cn.vuejs.org/)open in new window

image-20231215142214177

那在前面的课程中,我们已经学习了Vue的基本语法、表达式、指令,并基于Vue的核心包,完成了Vue的案例。

今天主要完成如下功能:

基于Vue进行整站开发。🎯

1. TS

1.1 概述以及入门案例 ✏️

概述以及入门案例

  • TypeScript(简称 TS)是JavaScript的超集(继承了JS全部语法),TypeScript = Type + JavaScript。

    image-20231016182655912
  • 简单说,就是在JS的基础上,为JS添加了类型支持。

  • TypeScript是微软开发的开源编程语言,可以在任何运行JavaScript的地方运行。

    image-20231215203524846image-20231215203546276

    类型注解:是指在变量、函数等定义的时候,使用特定语法(: type)来指定其类型,并在代码中限制只能接收特定类型的值。

为什么要用TypeScript ?

  • 动态类型语言

    • 编写bug多,影响开发效率
    • 运行时才会发现问题
    • 开发工具代码提示功能弱
    • 不便项目维护
  • 静态类型语言

    • 有利于发现错误(编写时)
    • 有利于代码的静态分析
    • 便于语法提示和自动补全
    • 利于项目维护

代码操作

  • 准备

    • 以管理员身份运行CMD,安装TS官方提供的编译器:npm install -g typescript (只需要做一次即可)
    image
    image
  • 编码

    • 定义ts文件,定义变量,指定类型注解
    • 编译ts文件,测试程序运行
    image
    image

    编译命令:tsc Helloworld.ts

image
image
编译之后的文件为:`Helloworld.js`

注意 :TS代码编译目标版本为es3(比较低),可以通过参数 –target 指定编译的目标版本。如:es5、es6、es2016... esnext

image
image

总结

课堂作业

  1. 安装TS官方提供的编译器npm install -g typescript (只需要做一次即可)
  2. 完成上述步骤,对比与java运行的异同?🎤
  3. 定义字符串变量 bookname,值为你最喜欢的书籍。然后编译成js,在浏览器中运行!

运行位置:

image
image

1.2 常用类型 🍐

TS常用类型

TS中除了支持JS中的数据类型之外,还提供了新的实用的数据类型。 常见类型如下:

类型例子备注
字符串类型string
数字类型number整数 、小数
布尔类型booleantrue、false
null/undefined类型null / undefined表示null和undefined本身,意义不大
任意类型any没有指定任何类型
数组类型number[] / Array<number>
联合类型numberstring
字面量类型'left''center'
函数类型() => void对函数的参数及返回值指定类型
对象类型限定对象的结构(属性及方法)
复杂类型interface接口
泛型<T>

代码操作

基础类型

基础类型:string,number,boolean,null,undefined,any,数组。

// 基本类型
let uname:string='yange'; // 字符串类型
let age:number=35;// 数字类型
let isStudent:boolean=true;// 布尔类型
let hobbies:string[]=['sing','dance','draw'];// 数组类型
let address:any='beijing';// 任意类型 不推荐
let hobby:null=null;// 空类型 很少用到,作用不大
let abc:undefined=undefined;// 未定义类型 作用不大

原则上,不推荐使用any!!! 这会让TypeScript又回到JavaScript(失去TS类型保护的优势)。

总结

课堂作业

  1. TS中这些类型,和java中的类型对应一下?相似吗?🎤
  2. 定义一个字符串数组,将你的爱好定义在里面
  3. 定义一个对象类型,描述你喜欢的书籍(名字,概要,主角,类型,章节数)
  4. 定义一个方法,求取1-n之和

2. ElementPlus ✏️ ✏️

2.1 介绍和快速入门

ElementPlus快速入门

Element:是饿了么公司前端开发团队提供的一套基于 Vue3 的网站组件库,用于快速构建网页。

Element 提供了很多组件(组成网页的部件)供我们使用。例如 超链接、按钮、图片、表格等等。

官方网站:https://element-plus.org/zh-CN/#/zh-CNopen in new window

如下图所示就是我们开发的页面和ElementUI提供的效果对比:可以发现ElementUI提供的各式各样好看的按钮

image-20231215210448428

ElementPlus的学习方式和我们之前的学习方式不太一样,对于ElementPlus,我们作为一个后台开发者,只需要学会如何从 ElementPlus 的官网拷贝组件到我们自己的页面中,并且做一些修改即可。 我们主要学习的是ElementPlus中提供的常用组件,至于其他组件同学们可以通过我们这几个组件的学习掌握到ElementPlus的学习技巧,然后课后自行学习。

代码操作

准备工作:

1️⃣ 将资料中提供的基础工程(资料/04. ElementPlus基础工程/vue-project02.zip),解压到工作目录中,使用VSCode将其打开。
image-20231215212817741
image-20231215212817741
2️⃣ 参照官方文档,安装ElementPlus的组件库(在当前工程的目录下),执行如下命令:【这一步可以不做,已经安装好了】
npm install element-plus --save
image-20231215212953435
image-20231215212953435
3️⃣ 在main.ts 中引入ElementPlus组件库 (参照官方文档),最终 main.ts 中代码如下:
import { createApp } from 'vue' // 引入createApp方法
// 引入App.vue组件
import App from './App.vue' 
// 引入main.css文件
import './assets/main.css'
// 引入ElementPlus
import ElementPlus from 'element-plus'
// 引入ElementPlus的样式
import 'element-plus/dist/index.css'
// 创建Vue应用
const app = createApp(App)

// 使用ElementPlus
app.use(ElementPlus)

app.mount('#app')

总结

课堂作业

  1. 参考上述步骤,完成入门案例的书写!🎤

2.2 常见组件

常见组件

官网:https://element-plus.org/zh-CN/component/overview.htmlopen in new window

常见组件

代码操作

表格组件

用于展示多条结构类似的数据, 可对数据进行排序、筛选、对比或其他自定义操作。

image-20231215214723765

接下来我们通过代码来演示。

1️⃣ 首先我们需要来到 ElementPlus 的组件库中,找到表格组件,如下图所示:
image-20231215214850778
image-20231215214850778
2️⃣ 然后新建一个组件 Element.vue,组件中,需要注意的是,我们组件包括了3个部分,如果官方有除了template部分之外的style和script都需要复制。具体操作如下图所示:
image-20231215220453492
image-20231215220453492

整体代码如下所示:

<script setup lang="ts">
const tableData = [
  {date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles'},
  {date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles'},
  {date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles'},
  {date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles'}
]
</script>

<template>
  <!-- Button按钮 -->
  <el-row class="mb-4">
    <el-button>Default</el-button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </el-row>
  <br>

  <!-- Table表格 -->
  <el-table :data="tableData" border style="width: 100%">
    <el-table-column prop="date" label="Date" width="180" />
    <el-table-column prop="name" label="Name" width="180" />
    <el-table-column prop="address" label="Address" />
  </el-table>
</template>

<style scoped>
</style>

此时回到浏览器,我们页面呈现如下效果:

image-20231215220919300
image-20231215220919300

Table表格组件,属性说明:

  • data: 主要定义table组件的数据模型
  • prop: 定义列的数据应该绑定data中定义的具体的数据模型
  • label: 定义列的标题
  • width: 定义列的宽度

总结

课堂作业

  1. 参考上述步骤,完成组件的显示(CV大法)
  2. 对比上述的组件,主要分为几个部分操作??🎤

2.3 案例

案例

需求:基于ElementPlus组件库制作如下页面,并异步获取数据,完成页面展示。

image-20231215224828379

代码操作

1). 准备工作

由于在案例中,我们需要在vue项目中使用Axios,需要安装axios,需要在当前项目的目录下执行如下命令:

npm install axios
image-20231215225358020
image-20231215225358020

总结

课堂作业

  1. 参考上述步骤,完成案例效果!!🎤

3. 前后端分离开发

前后端分离开发

在之前的课程中,我们介绍过,现在的企业项目开发有2种开发模式:前后台混合开发前后台分离开发

前后台混合开发,顾名思义就是前台后台代码混在一起开发。这种开发模式有如下缺点:

  • 沟通成本高:后台人员发现前端有问题,需要找前端人员修改,前端修改成功,再交给后台人员使用
  • 分工不明确:后台开发人员需要开发后台代码,也需要开发部分前端代码。很难培养专业人才
  • 不便管理:所有的代码都在一个工程中
  • 难以维护:前端代码更新,和后台无关,但是需要整个工程包括后台一起重新打包部署。

所以我们目前基本都是采用的前后台分离开发方式,如下图所示:

image-20231124150213401

我们将原先的工程分为前端工程和后端工程这2个工程,然后前端工程交给专业的前端人员开发,后端工程交给专业的后端人员开发。

问题1 前端页面需要数据,可以通过发送异步请求,从后台工程获取。但是,我们前后台是分开来开发的,那么前端人员怎么知道后台返回数据的格式呢?

问题2 后端人员开发,怎么知道前端人员需要的数据格式呢?

所以针对这个问题,我们前后台统一制定一套规范!我们前后台开发人员都需要遵循这套规范开发,这就是我们的接口文档。接口文档有离线版和在线版本,接口文档示可以查询今天提供资料/接口文档里面的资料。

问题3 那么接口文档的内容怎么来的呢?

是我们后台开发者根据产品经理提供的产品原型和需求文档所撰写出来的,产品原型示例可以参考今天提供资料/页面原型里面的资料。

那么基于前后台分离开发的模式下,我们后台开发者开发一个功能的具体流程如何呢?如下图所示:

image-20231220212542978
  1. 需求分析 :首先我们需要阅读需求文档,分析需求,理解需求。
  2. 接口定义 :查询接口文档中关于需求的接口的定义,包括地址,参数,响应数据类型等等
  3. 前后台并行开发 :各自按照接口文档进行开发,实现需求
  4. 测试 :前后台开发完了,各自按照接口文档进行测试
  5. 前后段联调测试 :前段工程请求后端工程,测试功能

4. 准备工作

准备工作

image
image

代码操作

1️⃣ 创建Vue项目

在自己工作目录下,运行 cmd 打开命令行,运行如下指令,来创建vue项目【这步可以不用操作,直接导入资料中提供的 vue-tlias-management.zip 】。

npm init vue@latest
image-20231220213127902

总结

课堂作业

  1. 根据上述提示,完成准备工作,并运行成功🎤

5. 页面布局

页面布局

我们在制作一个页面的时候,一定是先关注整体的页面布局,然后再关注具体的细节处理 。 所以这一小节,我们就先来完成页面的整体布局。

image-20231220220950569

我们会看到,整个页面分为这么三个部分:

  1. 页头部分
  2. 侧边栏
  3. 主区域

而要完成这样的页面布局,我们其实是可以借助于 ElementPlus 中提供的 Container布局容器 来实现:

image-20231220221807112

Container布局容器,用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>:外层容器。 当子元素中包含 <el-header><el-footer> 时,全部子元素会垂直上下排列, 否则会水平左右排列。

<el-header>:顶栏容器。

<el-aside>:侧边栏容器。

<el-main>:主要区域容器。

<el-footer>:底栏容器。

而针对于我们当前案例的页面布局,基本的结构如下:

image-20231220220902109

提示:当 <el-container> 子元素中包含 <el-header> <el-footer> 时,全部子元素会垂直上下排列, 否则会水平左右排列。

代码操作

我们可以参照 ElementPlus 的官方网站中的 布局,拷贝其源码,然后对其做一个改造。 具体参照的源码如下:

image-20231220222504658
image-20231220222504658

1). 在 src/views 目录下,再创建一个子目录 layout ,在其中新建一个页面,页面命名为:index.vue

2). 在 index.vue 中准备好基础的组件结构后,就可以将代码直接复制到 <template> </template> 标签中。

image
image
<script setup lang="ts">

</script>

<template>
   <div class="common-layout">
    <el-container>
      <!-- 顶栏 - header -->
      <el-header>Header</el-header>

      <!-- 左侧菜单 & 主区域 -->
      <el-container>
        <el-aside width="200px">Aside</el-aside>
        <el-main>Main</el-main>
      </el-container>
    </el-container>
  </div>
</template>

<style scoped>

</style>

然后,我们先根据页面原型中的布局显示进行调整。 先完成顶栏部分的制作,具体的代码如下:

<script setup lang="ts">

</script>

<template>
   <div class="common-layout">
    <el-container>
      <!-- 顶栏 - header -->
      <el-header class="header">
        <span class="title">Yangeit智能学习辅助系统</span>
        <span class="right_tool">
          <a href=""><el-icon><EditPen /></el-icon> 修改密码 &nbsp;&nbsp;&nbsp;&nbsp;</a>
          <a href=""><el-icon><SwitchButton /></el-icon> 退出登录&nbsp;&nbsp;&nbsp;&nbsp;</a>
        </span>
      </el-header>

      <!-- 左侧菜单 & 主区域 -->
      <el-container>
        <el-aside width="200px">Aside</el-aside>
        <el-main>Main</el-main>
      </el-container>
    </el-container>
  </div>
</template>

<style scoped>
.header {
  background-image: linear-gradient(to right, #e70cc5, #e94dcf, #eb6fd8, #ec8bdf, #eea5e6);
  line-height: 60px;
}

.title {
  color: white;
  font-size: 35px;
  font-family: 楷体;
  
}

.right_tool {
  float: right;
}

a {
  text-decoration: none;
  color: white;
}
</style>

最终的顶栏布局效果如下所示:

image
image

index.vue完整代码

👇 👇 👇

点击查看index.vue完整代码

到目前为止,layout/index.vue 中的内容如下:

<script setup lang="ts">

</script>

<template>
   <div class="common-layout">
    <el-container>
      <!-- 顶栏 - header -->
      <el-header class="header">
        <span class="title">Yangeit智能学习辅助系统</span>
        <span class="right_tool">
          <a href=""><el-icon><EditPen /></el-icon> 修改密码 &nbsp;&nbsp;&nbsp;&nbsp;</a>
          <a href=""><el-icon><SwitchButton /></el-icon> 退出登录&nbsp;&nbsp;&nbsp;&nbsp;</a>
        </span>
      </el-header>
      

      <!-- 左侧菜单 & 主区域 -->
      <el-container>
        <!-- 左侧菜单 -->
        <el-aside width="200px" class="aside">
          <el-scrollbar>
            <el-menu router>
              <!-- 首页菜单 -->
              <el-menu-item index="/index">
                <el-icon><Promotion /></el-icon> 首页
              </el-menu-item>
              
              <!-- 班级管理菜单 -->
              <el-sub-menu index="/manage">
                <template #title>
                  <el-icon><Menu /></el-icon> 班级学员管理
                </template>
                <el-menu-item index="/clazz">
                  <el-icon><HomeFilled /></el-icon>班级管理
                </el-menu-item>
                <el-menu-item index="/stu">
                  <el-icon><UserFilled /></el-icon>学员管理
                </el-menu-item>
              </el-sub-menu>
              
              <!-- 系统信息管理 -->
              <el-sub-menu index="/system">
                <template #title>
                  <el-icon><Tools /></el-icon>系统信息管理
                </template>
                <el-menu-item index="/dept">
                  <el-icon><HelpFilled /></el-icon>部门管理
                </el-menu-item>
                <el-menu-item index="/emp">
                  <el-icon><Avatar /></el-icon>员工管理
                </el-menu-item>
              </el-sub-menu>

              <!-- 数据统计管理 -->
              <el-sub-menu index="/report">
                <template #title>
                  <el-icon><Histogram /></el-icon>数据统计管理
                </template>
                <el-menu-item index="/empReport">
                  <el-icon><InfoFilled /></el-icon>员工信息统计
                </el-menu-item>
                <el-menu-item index="/stuReport">
                  <el-icon><Share /></el-icon>学员信息统计
                </el-menu-item>
                <el-menu-item index="/log">
                  <el-icon><Document /></el-icon>日志信息统计
                </el-menu-item>
              </el-sub-menu>

            </el-menu>
          </el-scrollbar>
        </el-aside>


        <el-main>Main</el-main>
      </el-container>
    </el-container>
  </div>
</template>

<style scoped>
.header {
  background-image: linear-gradient(to right, #e70cc5, #e94dcf, #eb6fd8, #ec8bdf, #eea5e6);
  line-height: 60px;
}

.title {
  color: white;
  font-size: 35px;
  font-family: 楷体;
  
}

.right_tool {
  float: right;
}

a {
  text-decoration: none;
  color: white;
}

.aside {
  border: 1px solid #ccc;
  height: 690px;
  width: 220px;
}
</style>

目前,我们点击左侧的菜单,右侧主区域展示的内容,还不能做到动态变化 。 那应该如何做到动态变化呢 ?

image
image

那要完成这个功能效果,我们就需要用到Vue生态中的路由 Vue-Router

6. Vue Router

6.1 路由介绍和入门

路由介绍和入门

image-20231220230246508
image-20231220230246508
  • Vue Router:Vue的官方路由。 为Vue提供富有表现力、可配置的、方便的路由。
  • Vue中的路由,主要定义的是路径与组件之间的对应关系。

比如,我们打开一个网站,点击左侧菜单,地址栏的地址发生变化。 地址栏地址一旦发生变化,在主区域显示对应的页面组件。

image-20231220230500902
image-20231220230500902
image-20231220230547196
image-20231220230547196

VueRouter主要由以下三个部分组成,如下所示:

image-20231220230746358
image-20231220230746358
  • VueRouter:路由器类,根据路由请求在路由视图中动态渲染选中的组件
  • <router-link>:请求链接组件,浏览器会解析成<a>
  • <router-view>:动态视图组件,用来渲染展示与路由路径对应的组件

代码操作

介绍完了VueRouter之后,接下来,我们就通过一个入门程序,来演示一下VueRouter的使用。

1). 安装 vue-router (创建Vue项目时,已经选择)

npm install vue-router@4

2). 在 main.ts 入口文件中进行配置,加入如下配置

import router from './router'

//..... 创建完vue的应用实例后,调用app.use
app.use(router)

3). 在 src/views 目录下再定义一个文件夹,在文件夹中再创建一个 vue 组件文件

image-20231220231313781
image-20231220231313781

4). 定义路由

src/router/index.ts 中定义路由表信息,在其中主要是定义请求路径与组件之间的对应关系。 完整的文件内容如下:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('../views/layout/index.vue')
    },
    {
      path: '/index',
      name: 'index',
      component: () => import('../views/index/index.vue')
    }
  ]
})

export default router

5). 在 App.vue 根组件中,定义 <RouterView></RouterView> 标签

该标签将用于显示,访问的请求路径对应的组件。

<script setup lang="ts">

</script>

<template>
  <RouterView></RouterView>
</template>

<style scoped>

</style>

6). 测试

浏览器访问请求路径 http://127.0.0.1:5173/index,展示如下页面内容(该页面内容,就是我们在 index/index.vue 中定义的页面内容):

image-20231220232129817
image-20231220232129817

浏览器访问请求路径 http://127.0.0.1:5173/,展示如下页面内容 (该页面内容,就是我们在 layout/index.vue 中定义的页面内容):

image-20231220232251233
image-20231220232251233

到此,我们发现,我们请求不同的请求路径,就可以在页面中显示不同的组件。具体的访问流程如下:

image-20231220232422972
image-20231220232422972

总结

课堂作业

  1. 参考上述步骤,完成路由文件index.ts 的创建,以及完成页面的切换🎤

6.2 案例

前言

那接下来,我们就要基于 VueRouter 来完成点击 左侧菜单,动态切换主展示区域内容的动态效果。

代码操作

1). 准备案例的空页面 (资料中已经提供,直接复制到项目的 src/views 目录中即可)

image-20231220232638271

2). 在 src/router/index.ts 中配置路由信息

这里我们用到了Vue中的嵌套路由,具体定义方式,主要是在配置路由信息时,通过children 来描述。如你所见,children 配置只是另一个路由数组,就像 routes 本身一样。因此,你可以根据自己的需要,不断地嵌套视图。

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('../views/layout/index.vue'),
      redirect: '/index',
      children: [
        {
          path: 'index',
          name: 'index',
          component: () => import('../views/index/index.vue') //首页
        },
        {
          path: 'emp',
          name: 'emp',
          component: () => import('../views/emp/index.vue') //员工管理
        },
        {
          path: 'dept',
          name: 'dept',
          component: () => import('../views/dept/index.vue') //部门管理
        },
        {
          path: 'clazz',
          name: 'clazz',
          component: () => import('../views/clazz/index.vue') //班级管理
        },
        {
          path: 'stu',
          name: 'stu',
          component: () => import('../views/stu/index.vue') //学员管理
        }
      ]
    }
  ]
})

export default router

3). 完善左侧菜单栏 layout/index.vue,菜单栏关联路由

image-20231220233052889

菜单关联了路由之后,我们点击对应的菜单,就会根据菜单的唯一标识 index,在地址栏中请求访问对应的地址。

4). 在Vue组件中,动态展示与路由对应的组件 。

需要在 layout/index.vue 中的 <el-main></el-main> 中添加动态路由视图组件 <RouterView></RouterView> 。如下:

<!-- 主展示区域 -->
<el-main>
	<RouterView></RouterView>
</el-main>

6.3 首页制作🎯

首页制作

其实首页,我们只需要展示一张图片即可。 直接在 index/index.vue 中引入一张图片即可,具体代码如下:

将图片放到assets文件夹中(模版工程中存在)

<script setup lang="ts">

</script>

<template>
    <img src="../../assets/index.png" />
</template>

<style scoped>

</style>

最终效果如下:

image
image

总结

课堂作业

  1. 根据上述提示,完成首页制作🎤

7. 部门管理

部门管理的页面内容,写在 src/views/dept/index.vue 中。

7.1 部门列表

部门列表

  1. 基本布局
  2. 加载数据
  3. 程序优化

代码操作

基本布局

首先,根据页面原型、需求说明、接口文档,先完成页面的基本布局 。 可以参考 ElementPlus 中的组件,拷贝过来适当做一个改造。

image-20231221105804349

部门管理组件 src/views/dept/index.vue 具体的页面布局代码如下:

<script setup lang="ts">
import {ref} from 'vue'
import type { DeptModelArray } from '@/api/model/model'

//声明列表展示数据
let tableData = ref<DeptModelArray>([])
</script>

<template>
  <h1>部门管理</h1>
  <el-button type="primary" style="float: right" @click="">+ 新增</el-button>
  <br><br>

  <!-- 部门数据表格 -->
  <el-table :data="tableData" border style="width: 100%">
    <el-table-column type="index" label="序号"  width="80"  align="center"/>
    <el-table-column prop="name" label="部门名称" width="250"  align="center"/>
    <el-table-column prop="updateTime" label="最后操作时间" width="300"  align="center"/>
    <el-table-column label="操作"  align="center">
      <template #default="scope">
        <el-button size="small" type="primary" @click="">修改</el-button>
        <el-button size="small" type="danger"  @click="">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<style scoped>

</style>

表格中每一列展示的属性 prop 都是根据接口文档来的,接口文档返回什么样的数据,我们就安装对应的数据格式进行解析。

总结

课堂作业

  1. 根据上述提示,完成部门列表的书写🎤