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>