Vue基础
Vue介绍
原生的JS在程序开发的过程中书写起来是十分麻烦的,因此很多的前端的框架(半成品)就应运而生了,目前比较知名的是下面三个

Vue是一个用于构建用户界面的渐进式框架,目前企业中流行的版本有两个
 
 
入门案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>快速入门</title>
</head>
<body>
    <!--
        3. 使用vue声明一个变量username, 并把它的值显示在div中
    -->
    <div id="app">
        {{username}}
    </div>
    <script type="module">
        // 1. 导入vue的js文件
        import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
        //2. 创建vue对象
        createApp({
            //数据
            data() {
                return {
                    username: "张三"
                }
            }
        }).mount('#app')
    </script>
</body>
</html>
插值表达式是一种Vue的模板语法,用于给页面进行赋值,注意点:
- {{}}除了基本的赋值外,还可以进行简单的方法调用、数学运算、三元运算等等
- {{}}中仅仅支持表达式,不支持语句,比如:if、for
- {{}}中使用的数据必须在data中存在
- {{}}不能为标签的属性进行赋值
Vue指令
Vue的指令就类似于Java的关键字,是Vue内置好一些有特点含义的语法标签,一般格式都是v-xxxx
页面赋值(v-html)
v-html用于将指定变量的值渲染到页面上,如果变量值中有html语法,会进行解析
此标签跟插值表达式功能相似,区别在于插值表达式不会进行html语法的解析
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>快速入门</title>
</head>
<body>
    <!-- 
        v-html用于将指定变量的值渲染到页面上,如果变量值中有html语法,会进行解析
        此标签跟插值表达式功能相似,区别在于插值表达式不会进行html语法的解析
    -->
    <div id="app">
        使用插值表达式的效果: {{str}} <br>
        使用插值v-html的效果: <span v-html="str">好孩子</span>
    </div>
    
    <script type="module">
        /* 1. 导入vueJS的主入口类 */
        import {createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
        //import {createApp} from './js/vue.esm-browser.js';
        /* 2. 创建Vue对象 */
        createApp({
            data(){
                return {
                     str:"我是一个<b>好学生</b>"
                }
            }
        }).mount('#app');
    </script>
</body>
</html>
双向绑定(v-model)
v-model是双向绑定,视图(View)和模型(Model)之间会互相影响
目前v-model的可使用元素有:input、select、textarea
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>双向绑定</title>
</head>
<body>
   <!-- 
       v-model是双向绑定,视图(View)和模型(Model)之间会互相影响
       目前v-model的可使用元素有:input、select、textarea
   -->
   <div id="app">
       <h3>姓名:</h3>
       <input type="text" v-model="username">
       <div>您写的姓名是:{{username}}</div>
       <h3>性别:</h3>
       <input type="radio" value="男" v-model="gender"> 男 <br>
       <input type="radio" value="女" v-model="gender"> 女 <br>
       <div>您选择的性别是:{{gender}}</div>
       <h3>爱好:</h3>
       <input type="checkbox" value="抽烟" v-model="hobby">抽烟<br>
       <input type="checkbox" value="喝酒" v-model="hobby">喝酒<br>
       <input type="checkbox" value="烫头" v-model="hobby">烫头<br>
       <div>您选择的爱好是:{{hobby}}</div>
       <h3>段位:</h3>
       <select v-model="level">
           <option value="">请选择</option>
           <option value="青铜">青铜</option>
           <option value="白银">白银</option>
           <option value="王者">王者</option>
       </select>
       <div>您选择的段位是:{{level}}</div>
   </div>
   <script type="module">
       import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
       createApp({
           data() {
               return {
                   "username": "张三",
                   "gender": "男",
                   "hobby": ["喝酒"],
                   "level": "青铜"
               }
           }
       }).mount('#app');
   </script>
</body>
</html>
属性绑定(v-bind)
对于HTML标签属性,如果想要动态传值,不能使用{{}},而应该使用专门的属性绑定语法
标准语法:v-bind:属性名=“Vue中的变量”
简写语法: :属性名=“Vue中的变量”
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>属性绑定</title>
</head>
<body>
   <!-- 
       对于HTML标签属性,如果想要动态传值,不能使用{{}},而应该使用专门的属性绑定语法
       标准语法:v-bind:属性名="Vue中的变量"
       简写语法:      :属性名="Vue中的变量"
   -->
   <div id="app">
       <h3>属性绑定基本使用</h3>
       有两个图片地址分别是:./img/vue.png 和 ./img/mn.jpg,请在下面输入地址,改变图片:<br>
       图片地址: <input type="text" v-model="imgSrc">
       图片宽度: <input type="text" v-model="imgWidth">
       <br>
       <img v-bind:src="imgSrc" :width="imgWidth">
   </div>
   
   <script type="module">
       import {createApp} from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
       createApp({
           data(){
               return {
                   imgSrc: "./img/vue.png",
                   imgWidth: "100px"
               }
           }
       }).mount('#app');
   </script>
</body>
</html>
列表遍历(v-for)
v-for=“(临时变量,索引) in 数组”
遍历哪个标签,就要将这个指令当成属性写在谁哪个标签上
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>列表遍历</title>
</head>
<body>
    <!-- 
        v-for="(临时变量,索引) in 数组"
        注意:遍历哪个标签,就要将这个指令当成属性写在谁哪个标签上
    -->
    <div id="app">
        <table border="1" cellspacing="0" cellpadding="0" width="500px">
            <tr>
                <th>id</th>
                <th>name</th>
                <th>address</th>
            </tr>
            <tr v-for="(user,item) in users" :key="user.id">
                <td>{{user.id}}</td>
                <td>{{user.name}}</td>
                <td>{{user.address}}</td>
            </tr>
        </table>
    </div>
    <script type="module">
        import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
        createApp({
            data() {
                return {
                    users: [
                        { id: 1, name: 'jack', address: '北京顺义' },
                        { id: 2, name: 'lucy', address: '上海虹桥' },
                        { id: 3, name: 'jerry', address: '天津宝坻' }
                    ]
                }
            }
        }).mount('#app');
    </script>
</body>
</html>
条件判断(v-if/v-show)
语法:
 v-if=布尔值 条件性的创建或者移除某些元素,判定为true时创建,判定为false移除
 v-show=布尔值 条件性的显示或者隐藏某些元素,判定为true时显示,判定为false隐藏
注意:
 1) v-if 一般用于要么显示,要么隐藏的场景;v-show用于频繁切换显示和隐藏的场景
 2) v-if还可以配合v-else以及v-else-if实现多分支条件判断,此时要注意三个标签中间不能有其它内容
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>条件判断</title>
</head>
<body>
   <!-- 
       语法:    
           v-if 条件性的创建或者移除某些元素,判定为true时创建,判定为false移除
           v-show 条件性的显示或者隐藏某些元素,判定为true时显示,判定为false隐藏
       注意:    
           1) v-if 一般用于要么显示,要么隐藏的场景;v-show用于频繁切换显示和隐藏的场景
           2) v-if还可以配合v-else以及v-else-if实现多分支条件判断,此时要注意三个标签中间不能有其它内容
    -->
   <div id="app">
       <!--从文本框输入成绩, 然后判断成绩是否及格  >=60:及格    <60:不及格-->
       请输入成绩:<input type="text" v-model="score"><br>
       <h3>v-if判断考试结果</h3>
       您本次开始成绩:
       <span v-if="score >= 60">及格</span>
       <span v-else-if="score < 60">不及格</span>
       <span v-else>成绩无效</span>
       <!--         
               <span v-if="score >= 60">及格</span>
               <span v-if="score < 60">不及格</span> 
           -->
       <h3>v-show判断考试结果</h3>
       您本次开始成绩:
       <span v-show="score >= 60">及格</span>
       <span v-show="score < 60">不及格</span>
   </div>
   <script type="module">
       import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
       createApp({
           data() {
               return {
                   score: "0",
               }
           }
       }).mount('#app');
   </script>
</body>
</html>
事件绑定(v-on)
事件绑定用于给页面元素添加事件,js支持的事件vue都支持
标准语法 v-on:事件名=“函数名”
简化语法 @事件名=“函数名”
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>事件绑定</title>
</head>
<body>
   <!-- 
       事件绑定用于给页面元素添加事件,js支持的事件vue都支持
       标准语法   v-on:事件名="函数名"
       简化语法   @事件名="函数名"
    -->
   <div id="app">
       <b>数量:</b>
       <button @click="diff()">-</button>
       <input type="text" v-model="num" style="width: 30px;">
       <button v-on:click="add()">+</button>
   </div>
   <script type="module">
       import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
       createApp({
           data() {
               return {
                   num: 1
               }
           },
           methods: {
               add() {
                   this.num++
               },
               diff() {
                   this.num--
               }
           }
       }).mount('#app');
   </script>
</body>
</html>
axios
axios是一个可以从前端向后端发送ajax请求的小框架,为Vue官方所推荐
//axios 发送get请求	
axios.get("url?username=zhangsan&password=123").then(resp=>{
	resp.data;//返回结果
})
// axios发送post请求
axios.post("url",{"username":"zhangsan","password":"123"}).then(resp=>{
	resp.data;//返回结果
})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>vue表格制作</title>
    <!--
        使用Axios向指定后台发送请求,将拉取的数据使用vue技术渲染成HTML表格
        后台的数据地址是:https://mock.apifox.cn/m1/3128855-0-default/emp/list
    -->
</head>
<body>
    <div id="app">
        <table border="1" cellspacing="0" width="60%">
            <tr id="head">
                <th>编号</th>
                <th>姓名</th>
                <th>图像</th>
                <th>性别</th>
                <th>职位</th>
                <th>入职日期</th>
                <th>最后操作时间</th>
            </tr>
            
            <tr v-for="(emp,index) in empList" :key="emp.id">
                <td>{{emp.id}}</td>
                <td>{{emp.name}}</td>
                <td><img :src="emp.image" width="50px"> </td>
                <td>{{emp.gender == 1 ? "男" : "女"}}</td>
                <td>{{emp.job}}</td>
                <td>{{emp.entrydate}}</td>
                <td>{{emp.updateTime}}</td>
            </tr>
        </table>
    </div>
    <script src="./js/axios.js"></script>
    <script type="module">
        import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
        createApp({
            data() {
                return {
                    empList: []
                }
            },
            methods: {
                findList() {
                    axios.get("https://mock.apifox.cn/m1/3128855-0-default/emp/list").then(resp => {
                        this.empList = resp.data.data;
                    })
                }
            },
            created() { // 页面加载完毕后调用findList方法
                this.findList();
            }
        }).mount('#app');
    </script>
</body>
</html>
前端工程化
前端工程化就是在企业级的前端项目开发中,把前端开发所需要的工具、技术、流程、经验进行规范化和标准化
安装NodeJS
在开发项目之前,我们需要安装下NodeJS,它是前端开发的基础环境,相当于Java的JDK
① 双击资料中提供的安装包,启动安装程序

② 选择安装到一个没有中文没有空格的目录下,新建一个文件夹nodejs

③ 安装完毕后,通过node -v验证一下是否安装成功

④ 使用管理员身份运行命令行,执行如下指令配置npm的全局安装路径
npm config set prefix "D:\soft\nodejs"
注意:D:\soft\nodejs\这个目录是NodeJS的安装目录
⑤ 使用管理员身份运行命令行,执行如下指令切换镜像源
npm config set strict-ssl false
npm config set registry https://registry.npm.taobao.org
创建项目
接下来使用npm init vue@latest安装一个vue3的项目,这个过程中它会自动安装脚手架并初始化工程
安装的过程中会提示一些选项如下:

为了接下来的开发,我们还需要安装几个vscode的插件:
- Vue-Official 语法高亮,智能提示,emmet,错误提示,格式化,自动补全
- Vue VSCode Snippets: 快捷键
- Vetur
- VueHelper
启动项目

项目介绍
打开项目会发现很多目录,下面了解下每个目录的作用

我们以main.js作为文件的主入口,此文件会引入我们开发的根组件App.vue
我们可以在根组件中编写代码,也可以在其它自定义组件中开发,再引入到根组件中

组件:我们开发代码的主战场,一般包含三部分:script(定义js)、template(定义HTML)、style(定义css)
修改App.Vue,自定义首页
<!-- 注意: 先删掉script标签的setup属性 -->
<script>
export default {
    data() {
        return {
            message: "Hello"
        }
    }
}
</script>
<template>
    <div>
        <span class="msg">{{ message }}</span>
    </div>
</template>
<style scoped>
.msg {
    color: red;
}
</style>
API风格
在Vue中,有两种不同的风格:选项式API和组合式API
选项式API
选项式API允许导出多个对象(data、methods、mounted)来描述数据、方法、钩子函数

<!-- 注意: 先删掉script标签的setup属性 -->
<script>
export default {
    //数据
    data() {
        return {
            count: 1
        }
    },
    //方法
    methods:{
        increment(){
            this.count++;
        },
        decrement(){
            this.count--;
        }
    }
}
</script>
<template>
    <div>
        <button @click="decrement()">-</button>
        <span class="msg">{{ count }}</span>
        <button @click="increment()">+</button>
    </div>
</template>
<style scoped>
.msg {
    color: red;
    display: inline-block;
    width: 20px;
    text-align: center;
}
</style>
组合式API
组合式API用起来更加的简便

<!-- 
	1. 在script标签上添加setup属性
	2. 变量直接使用ref声明
	3. 方法直接定义
	4. 构造函数 直接写
-->
<script setup>
import { onMounted, ref } from 'vue';
//变量(这样声明出来的count是个对象 使用.value属性可以访问它的值)
const count = ref(1);
//方法
const increment = function () {
	count.value++;
}
const decrement = () => {
	count.value--;
}
//钩子函数
onMounted(() => {
	count.value = 10;
})
</script>
<template>
	<div>
		<button @click="decrement()">-</button>
		<span class="msg">{{ count }}</span>
		<button @click="increment()">+</button>
	</div>
</template>
<style scoped>
.msg {
	color: red;
	display: inline-block;
	width: 20px;
	text-align: center;
}
</style>
组件化
组件就是将一个页面可以拆分成一个个小部分,每个小部分有着自己独立的结构、样式、行为,这一个小部分就称为组件,组件便于维护,利于复用 。

组件分为两类:根组件和普通组件,根组件就一个–App.vue,它用来装载普通组件,普通组件可以有很多个,普通组件也可以装载其它普通组件

局部注册组件
局部注册:只能在注册的组件内使用

① 创建header组件
<script setup>
</script>
<template>
    <div class="header">
        我是hm-header
    </div>
</template>
<style scoped>
    .header{
        width: 500px;
        height: 100px;
        background-color: blueviolet;
        text-align: center;
        font-size: 20px;
        color: aliceblue;
    }
</style>
② 创建main组件
<script setup>
</script>
<template>
    <div class="header">
        我是hm-main
    </div>
</template>
<style scoped>
    .header{
        width: 500px;
        height: 400px;
        background-color:orange;
        text-align: center;
        font-size: 20px;
        color: aliceblue;
    }
</style>
③ 创建footer组件
<script setup>
</script>
<template>
    <div class="footer">
        我是hm-footer
    </div>
</template>
<style scoped>
    .footer{
        width: 500px;
        height: 100px;
        background-color:cornflowerblue;
        text-align: center;
        font-size: 20px;
        color: aliceblue;
    }
</style>
④ 在根组件中导入上面的三个组件并注册使用
<script setup>
//1. 将组件文件导入进来
import HmHeader from './components/HmHeader.vue'
import HmMain from './components/HmMain.vue'
import HmFooter from './components/HmFooter.vue'
components: {
    /* 标签:组件变量名 */
    HmHeader,
    HmMain,
    HmFooter
}
</script>
<template>
    <div>
        <!-- 3. 将组件等价标签写在html中 -->
        <hm-header></hm-header>
        <hm-main></hm-main>
        <hm-footer></hm-footer>
    </div>
</template>
<style scoped>
</style>
全局注册组件
全局注册:在所有组件中都能使用
全局注册跟局部注册的开发步骤很相近,不一样的地方在于注册的时候需要在main.js中注册,这样就可以在任意一个其它组件中使用了

① 创建button组件
<script setup>
</script>
<template>
    <div>
        <button>按钮</button>
    </div>
</template>
<style scoped>
    button{
        width: 100px;
        height: 40px;
        background-color: darkturquoise;
        color: white;
    }
</style>
② 注册全局组件

③ 在任何需要使用组件的时候直接使用标签名调用

ElementPlus
Element是饿了么公司前端开发团队提供的一套基于Vue的网站组件库,作用是帮助开发人员快速搭建网站
Element提供了大量的写好的页面组件,例如按钮、图片、表格、导航条、表单等等,开发人员可以直接复制使用
参考网站:https://element-plus.org/zh-CN/
我们自己编写的按钮

Element提供的按钮

快速入门
-  使用 npm install element-plus --save命令安装element-plus的包
-  在main.js中导入并创建ElementPlus的实例 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')
-  从ElementPlus官方复制代码到App.vue中,查看效果 https://element-plus.org/zh-CN/component/button.html <script lang="ts" setup> </script> <template> <div 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> </div> </template>
容器布局
Element的容器布局将页面分成头部区域、侧边栏区域、主区域、底部区域。
https://element-plus.org/zh-CN/component/container.html

<template>
	<div class="common-layout">
		<el-container>
			<!-- 头部组件 -->
			<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>
水平导航栏
https://element-plus.org/zh-CN/component/menu.html

<template>
	<!-- 
		el-menu: 导航栏
			default-active="activeIndex" 默认选中项(值是最终节点索引)
			mode="vertical(垂直)|horizontal(水平)" 
			@select="handleSelect"  选择其中一项时时间
		el-menu-item 没有下一层
			index 索引
		el-sub-menu 有下一层
	-->
	<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" :ellipsis="false"
		@select="handleSelect">
		<el-menu-item index="0">
			xxxx
		</el-menu-item>
		<el-menu-item index="1">Processing Center</el-menu-item>
		<el-sub-menu index="2">
			<template #title>Workspace</template>
			<el-menu-item index="2-1">item one</el-menu-item>
			<el-menu-item index="2-2">item two</el-menu-item>
			<el-menu-item index="2-3">item three</el-menu-item>
			<el-sub-menu index="2-4">
				<template #title>item four</template>
				<el-menu-item index="2-4-1">item one</el-menu-item>
				<el-menu-item index="2-4-2">item two</el-menu-item>
				<el-menu-item index="2-4-3">item three</el-menu-item>
			</el-sub-menu>
		</el-sub-menu>
	</el-menu>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const activeIndex = ref('2-4-2')
//key 选中项目的索引
const handleSelect = (key: string, keyPath: string[]) => {
	console.log(key, keyPath)
}
</script>
<style>
.el-menu--horizontal>.el-menu-item:nth-child(1) {
	margin-right: auto;
}
</style>
垂直导航栏
垂直菜单,可内嵌子菜单。
https://element-plus.org/zh-CN/component/menu.html

<template>
	<el-row class="tac">
		<!--
			el-menu: 主导航
				class="css样式"
				mode="horizontal|vertical"  导航模式
				background-color="背景色"
				text-color="文字颜色"
				active-text-color="激活文字颜色"
				default-active="3" 激活哪一项 , 激活必须定位到最末级
				@select="选择事件"
			el-menu-item: 子导航(无下级)
				index="2"  索引
			el-submenu: 子导航(有下级)
			@open="handleOpen" @close="handleClose"  开关事件
		-->
		<el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="2"
			text-color="#fff" @open="handleOpen" @close="handleClose">
			<el-sub-menu index="1">
				<template #title>
					<el-icon>
						<location />
					</el-icon>
					<span>Navigator One</span>
				</template>
				<el-menu-item-group title="Group One">
					<el-menu-item index="1-1">item one</el-menu-item>
					<el-menu-item index="1-2">item two</el-menu-item>
				</el-menu-item-group>
				<el-menu-item-group title="Group Two">
					<el-menu-item index="1-3">item three</el-menu-item>
				</el-menu-item-group>
				<el-sub-menu index="1-4">
					<template #title>item four</template>
					<el-menu-item index="1-4-1">item one</el-menu-item>
				</el-sub-menu>
			</el-sub-menu>
			<el-menu-item index="2">
				<el-icon><icon-menu /></el-icon>
				<span>Navigator Two</span>
			</el-menu-item>
			<el-menu-item index="3" disabled>
				<el-icon>
					<document />
				</el-icon>
				<span>Navigator Three</span>
			</el-menu-item>
			<el-menu-item index="4">
				<el-icon>
					<setting />
				</el-icon>
				<span>Navigator Four</span>
			</el-menu-item>
		</el-menu>
	</el-row>
</template>
<script lang="ts" setup>
import {
	Document,
	Menu as IconMenu,
	Location,
	Setting,
} from '@element-plus/icons-vue'
const handleOpen = (key: string, keyPath: string[]) => {
	console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
	console.log(key, keyPath)
}
</script>
表格组件
表格组件用于展示多条结构类似的数据,可对数据进行编辑、删除或其他自定义操作
https://element-plus.org/zh-CN/component/table.html

<template>
	<!-- 
		el-table 表格
			data: 表格数据
		el-table-column  列
			prop="从data提供数组的对象中取哪个属性值" 
			label="表头文字"	
	-->
	<el-table :data="tableData" border style="width: 100%">
		<el-table-column prop="date" label="日期" width="180" />
		<el-table-column prop="name" label="Name" width="180" />
		<el-table-column prop="address" label="Address" />
	</el-table>
</template>
<script lang="ts" setup>
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>
分页组件
当数据量过多时,使用分页分解数据。
https://element-plus.org/zh-CN/component/pagination.html

<template>
	<!-- 
		layout 控制显示哪些内容
		disabled 是否禁用
		background 是否加背景
		total 总记录数
		page-size 每页大小
		current-page 当期页码
		:size="size"  总页数
		:page-sizes="[100, 200, 300, 400]" 前端用的每页大小选择框
		@size-change="handleSizeChange"   每页大小改变时触发事件
		@current-change="handleCurrentChange"  页码改变时触发事件
	-->
	<el-pagination 
		layout="total, sizes, prev, pager, next, jumper"
		:disabled="disabled" 
		:background="background" 
		:total="400"
		:page-sizes="[100, 200, 300, 400]"
		:size="size" 
		v-model:current-page="currentPage4" 
		v-model:page-size="pageSize4" 
			
		@size-change="handleSizeChange" 
		@current-change="handleCurrentChange"
	/>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import type { ComponentSize } from 'element-plus'
const currentPage1 = ref(5)
const currentPage2 = ref(5)
const currentPage3 = ref(5)
const currentPage4 = ref(4)
const pageSize2 = ref(100)
const pageSize3 = ref(100)
const pageSize4 = ref(100)
const size = ref<ComponentSize>('default')
const background = ref(false)
const disabled = ref(false)
const handleSizeChange = (val: number) => {
	console.log(`${val} items per page`)
}
const handleCurrentChange = (val: number) => {
	console.log(`current page: ${val}`)
}
</script>
<style scoped>
.demo-pagination-block+.demo-pagination-block {
	margin-top: 10px;
}
.demo-pagination-block .demonstration {
	margin-bottom: 16px;
}
</style>
设置中文: https://blog.csdn.net/m0_56164131/article/details/140198734
对话框
在保留当前页面状态的情况下,弹出一个子窗口,完成操作
https://element-plus.org/zh-CN/component/dialog.html

<template>
	<!-- 按钮 -->
	<el-button plain @click="dialogFormVisible = true">
		Open a Form nested Dialog
	</el-button>
	<!-- 
		dialogFormVisible : 控制对话框是否显示
	-->
	<!-- 对话框 -->
	<el-dialog v-model="dialogFormVisible" title="Shipping address" width="500">
		
		<!-- 表单 -->
		<el-form :model="form">
			<el-form-item label="Promotion name" :label-width="formLabelWidth">
				<el-input v-model="form.name" autocomplete="off" />
			</el-form-item>
			<el-form-item label="Zones" :label-width="formLabelWidth">
				<el-select v-model="form.region" placeholder="Please select a zone">
					<el-option label="Zone No.1" value="shanghai" />
					<el-option label="Zone No.2" value="beijing" />
				</el-select>
			</el-form-item>
		</el-form>
		<!-- 小按钮 -->
		<template #footer>
			<div class="dialog-footer">
				<el-button @click="dialogFormVisible = false">Cancel</el-button>
				<el-button type="primary" @click="dialogFormVisible = false">
					Confirm
				</el-button>
			</div>
		</template>
	</el-dialog>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
const dialogTableVisible = ref(false)
const dialogFormVisible = ref(false)  //控制对话框是否显示
const formLabelWidth = '140px'
const form = reactive({
	name: '',
	region: '',
	date1: '',
	date2: '',
	delivery: false,
	type: [],
	resource: '',
	desc: '',
})
</script>
表单组件
表单组件由输入框、下拉列表、单选框、多选框等控件组成,用以收集、校验、提交数据。
https://element-plus.org/zh-CN/component/form.html

<template>
	<el-form :model="form" label-width="auto" style="max-width: 600px">
		<el-form-item label="Activity name">
			<el-input v-model="form.name" />
		</el-form-item>
		<el-form-item label="Activity zone">
			<el-select v-model="form.region" placeholder="please select your zone">
				<el-option label="Zone one" value="shanghai" />
				<el-option label="Zone two" value="beijing" />
			</el-select>
		</el-form-item>
		<el-form-item label="Activity time">
			<el-col :span="11">
				<el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" />
			</el-col>
			<el-col :span="2" class="text-center">
				<span class="text-gray-500">-</span>
			</el-col>
			<el-col :span="11">
				<el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" />
			</el-col>
		</el-form-item>
		<el-form-item label="Instant delivery">
			<el-switch v-model="form.delivery" />
		</el-form-item>
		<el-form-item label="Activity type">
			<el-checkbox-group v-model="form.type">
				<el-checkbox value="Online activities" name="type">
					Online activities
				</el-checkbox>
				<el-checkbox value="Promotion activities" name="type">
					Promotion activities
				</el-checkbox>
				<el-checkbox value="Offline activities" name="type">
					Offline activities
				</el-checkbox>
				<el-checkbox value="Simple brand exposure" name="type">
					Simple brand exposure
				</el-checkbox>
			</el-checkbox-group>
		</el-form-item>
		<el-form-item label="Resources">
			<el-radio-group v-model="form.resource">
				<el-radio value="Sponsor">Sponsor</el-radio>
				<el-radio value="Venue">Venue</el-radio>
			</el-radio-group>
		</el-form-item>
		<el-form-item label="Activity form">
			<el-input v-model="form.desc" type="textarea" />
		</el-form-item>
		<el-form-item>
			<el-button type="primary" @click="onSubmit">Create</el-button>
			<el-button>Cancel</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({
	name: '',
	region: '',
	date1: '',
	date2: '',
	delivery: false,
	type: [],
	resource: '',
	desc: '',
})
const onSubmit = () => {
	console.log('submit!')
}
</script>
综合案例

 ,
 ,
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import {
	Aim,
	Document,
	Menu as IconMenu,
	Location,
	Setting,
	Timer
} from '@element-plus/icons-vue'
import axios from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { ComponentSize } from 'element-plus'
//查询学生列表
const pageNum = ref(1) //当前页
const pageSize = ref(5) //每页条数
const total = ref(0) //总记录数
const size = ref<ComponentSize>('default')
const handleSizeChange = (val: number) => {
	findList();
}
const handleCurrentChange = (val: number) => {
	findList();
}
const studentList = ref([])
const findList = function () {
	//发送请求
	// axios.get("http://localhost:8090/student").then(resp => {
	// 	studentList.value = resp.data.data;
	// })
	axios.get("http://localhost:8090/student/findByPage", {
		params: {
			pageNum: pageNum.value,
			pageSize: pageSize.value
		}
	}).then(resp => {
		total.value = resp.data.data.total;
		studentList.value = resp.data.data.rows;
	})
}
//新增学生
const studentAddFrom = ref({}) //封装添加框数据
const addFormVisible = ref(false) //控制添加框显示
const addStudent = function () {
	//发送请求
	axios.post('http://localhost:8090/student', studentAddFrom.value).then(resp => {
		if (resp.data.code == 1) {
			//1. 关闭窗口
			addFormVisible.value = false
			//2. 清空添加框
			studentAddFrom.value = {}
			//3. 重新查询
			findList();
		}
	})
}
//修改学生
const studentUpdateFrom = ref({}) //封装添加框数据
const updateFormVisible = ref(false) //控制添加框显示
//点击修改框
const handleEdit = (index, row) => {
	//打开修改框
	updateFormVisible.value = true
	//根据id查询
	axios.get("http://localhost:8090/student/" + row.id).then(resp => {
		studentUpdateFrom.value = resp.data.data
	})
	//console.log(index, row.id)
}
//点击修改框修改按钮
const updateStudent = function () {
	//发送请求
	axios.put('http://localhost:8090/student', studentUpdateFrom.value).then(resp => {
		if (resp.data.code == 1) {
			//1. 关闭窗口
			updateFormVisible.value = false
			//2. 清空添加框
			studentUpdateFrom.value = {}
			//3. 重新查询
			findList();
		}
	})
}
//删除
const handleDelete = (index, row) => {
	ElMessageBox.confirm(
		'您是否确认要删除本条记录?',
		'',
		{
			confirmButtonText: '确认',
			cancelButtonText: '取消',
			type: 'warning',
		}
	).then(() => {
		axios.delete("http://localhost:8090/student/" + row.id).then(resp => {
			if (resp.data.code == 1) {
				findList();
				ElMessage({
					type: 'success',
					message: '删除成功',
				})
			}
		})
	})
}
//页面加载完毕
onMounted(function () {
	findList();
})
</script>
<template>
	<!-- 主界面 -->
	<div class="common-layout">
		<el-container>
			<el-header>
				<el-menu class="el-menu-demo" mode="horizontal" background-color="#545c64" text-color="#fff"
					active-text-color="#ffd04b" :ellipsis="false">
					<el-menu-item index="1" style="margin-right: auto;">Export</el-menu-item>
					<el-menu-item index="3">处理中心</el-menu-item>
					<el-sub-menu index="2">
						<template #title>我的工作台</template>
						<el-menu-item index="2-1">item one</el-menu-item>
						<el-menu-item index="2-2">item two</el-menu-item>
						<el-menu-item index="2-3">item three</el-menu-item>
					</el-sub-menu>
					<el-menu-item index="4">首页</el-menu-item>
				</el-menu>
			</el-header>
			<el-container>
				<el-aside width="200px">
					<el-menu default-active="1-1" class="el-menu-vertical-demo">
						<el-sub-menu index="1">
							<template #title>
								<el-icon>
									<location />
								</el-icon>
								<span>学工部</span>
							</template>
							<el-menu-item index="1-1"><el-icon>
									<Aim />
								</el-icon>在校学生管理</el-menu-item>
							<el-menu-item index="1-2"><el-icon>
									<Aim />
								</el-icon>学生升级/留级</el-menu-item>
							<el-menu-item index="1-3"><el-icon>
									<Aim />
								</el-icon>学生就业情况</el-menu-item>
						</el-sub-menu>
						<el-sub-menu index="2">
							<template #title>
								<el-icon>
									<Setting />
								</el-icon>
								<span>咨询部</span>
							</template>
							<el-menu-item index="2-1">在校学生管理</el-menu-item>
							<el-menu-item index="2-2">学生升级/留级</el-menu-item>
							<el-menu-item index="2-3">学生就业情况</el-menu-item>
						</el-sub-menu>
						<el-sub-menu index="3">
							<template #title>
								<el-icon>
									<Document />
								</el-icon>
								<span>教研部</span>
							</template>
							<el-menu-item index="3-1">在校学生管理</el-menu-item>
							<el-menu-item index="3-2">学生升级/留级</el-menu-item>
							<el-menu-item index="3-3">学生就业情况</el-menu-item>
						</el-sub-menu>
					</el-menu>
				</el-aside>
				<el-main>
					<div>
						<span style="font-weight: bold;color: red;">学生列表</span>
						<el-button type="primary" style="float: right;" @click="addFormVisible = true">添加学生</el-button>
					</div>
					<div>
						<el-table :data="studentList" style="width: 100%">
							<el-table-column prop="id" label="学号" width="180" />
							<el-table-column prop="name" label="姓名" width="180" />
							<el-table-column prop="birthday" label="生日" width="180" />
							<el-table-column prop="address" label="地址" width="180" />
							<el-table-column label="操作">
								<template #default="scope">
									<el-button type="warning" @click="handleEdit(scope.$index, scope.row)">
										编辑
									</el-button>
									<el-button type="danger" @click="handleDelete(scope.$index, scope.row)">
										删除
									</el-button>
								</template>
							</el-table-column>
						</el-table>
					</div>
					<div style="margin-top: 10px;">
						<el-pagination layout="total, sizes, prev, pager, next, jumper" v-model:current-page="pageNum"
							v-model:page-size="pageSize" :page-sizes="[5, 10, 15]" :size="size" :total="total"
							@size-change="handleSizeChange" @current-change="handleCurrentChange" />
					</div>
				</el-main>
			</el-container>
		</el-container>
	</div>
	<!-- 添加框 -->
	<el-dialog v-model="addFormVisible" title="添加学生信息" width="500">
		<el-form :model="studentFrom">
			<el-form-item label="学生学号">
				<el-input v-model="studentAddFrom.id" />
			</el-form-item>
			<el-form-item label="学生姓名">
				<el-input v-model="studentAddFrom.name" />
			</el-form-item>
			<el-form-item label="学生生日">
				<el-input v-model="studentAddFrom.birthday" />
			</el-form-item>
			<el-form-item label="学生地址">
				<el-input v-model="studentAddFrom.address" />
			</el-form-item>
		</el-form>
		<template #footer>
			<div class="dialog-footer">
				<el-button type="primary" @click="addStudent()">添加</el-button>
				<el-button @click="addFormVisible = false">重置</el-button>
			</div>
		</template>
	</el-dialog>
	<!-- 修改框 -->
	<el-dialog v-model="updateFormVisible" title="修改学生信息" width="500">
		<el-form :model="studentFrom">
			<el-form-item label="学生学号">
				<el-input v-model="studentUpdateFrom.id" />
			</el-form-item>
			<el-form-item label="学生姓名">
				<el-input v-model="studentUpdateFrom.name" />
			</el-form-item>
			<el-form-item label="学生生日">
				<el-input v-model="studentUpdateFrom.birthday" />
			</el-form-item>
			<el-form-item label="学生地址">
				<el-input v-model="studentUpdateFrom.address" />
			</el-form-item>
		</el-form>
		<template #footer>
			<div class="dialog-footer">
				<el-button type="primary" @click="updateStudent()">修改</el-button>
				<el-button @click="updateFormVisible = false">重置</el-button>
			</div>
		</template>
	</el-dialog>
</template>
<style>
.el-menu--horizontal>.el-menu-item:nth-child(1) {
	margin-right: auto;
}
</style>
–>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 <template #footer>
 
		</div>
	</template>
</el-dialog>
<!-- 修改框 -->
<el-dialog v-model="updateFormVisible" title="修改学生信息" width="500">
	<el-form :model="studentFrom">
		<el-form-item label="学生学号">
			<el-input v-model="studentUpdateFrom.id" />
		</el-form-item>
		<el-form-item label="学生姓名">
			<el-input v-model="studentUpdateFrom.name" />
		</el-form-item>
		<el-form-item label="学生生日">
			<el-input v-model="studentUpdateFrom.birthday" />
		</el-form-item>
		<el-form-item label="学生地址">
			<el-input v-model="studentUpdateFrom.address" />
		</el-form-item>
	</el-form>
	<template #footer>
		<div class="dialog-footer">
			<el-button type="primary" @click="updateStudent()">修改</el-button>
			<el-button @click="updateFormVisible = false">重置</el-button>
		</div>
	</template>
</el-dialog>



















