vue3
什么破学校还要学jsp,jsp是学不了了,浅学一下VUE3,应付一下期末考试吧
vue3概要
Vue是一套前端框架,用于简化JavaScript中的DOM操作,简化书写。
在之前我们也学习过后端的框架MyBatis,MyBatis是用来简化JDBC代码编写的;而Vue是前端框架,简化JavaScript代码编写的
vue的使用
- vue3的使用前提需要下载安装好node.js版本要在15.0以上
- 在命令窗中输入 npm init vue@laste 即可创建一个初始的vue文件夹
- hello vue
值得一提的是每个绑定仅支持单一的js表达式,如{ {n+1} },页面会显示11,{ {ok?yes:no} },页面会显示ok1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<template>
<p>{ {meg} }</p>
<p>{ {n+1} }</p>
<p>{ {ok?yes:no } }</p>
</template>
<script >
export default {
data(){
return{
meg:"hello jsp",
n:10,
ok:true
}
}
}
</script>v-bind
v-bind可以简写为 :
v-bind的作用的:可以为元素绑定vue属性基本用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<template>
<div>
<p v-bind:class="meg">测试</p>
</div>
</template>
<script >
export default {
data(){
return{
meg:"active"
}
}
}
</script>
可以在控制台看到 测试的class属性已经绑定成了active
v-if
用于条件判断是否展示元素
基本用法
当meg为true时显示,为false不显示
1 | |

多条件语句
1 | |
页面显示B
v-on
事件处理,用来监听DOM事件,并在事件触发时执行对应的JS语句 ,v-on可简写为@
方法事件处理器
每点击一次Add就会触发add()方法
1 | |
方法传参
点击谁,会在控制台输出谁
1 | |

数组变化侦测
变更数据 可以直接使页面更新

代码案例:点击添加数据,会给meg数组增加一个数据sakura
1 | |
点击前

点击后

替换数组
这个方法不会使前端直接展示
代码案例:点击添加数据,会给meg数组增加一个数据sakura
1 | |
点击后 可以看到页面并没有展示出新添加的数据,但是在控制台可以输出可以看到

原因:因为这个方法是新建了一个数组,在原本的数组数据基础上添加新数据,所以将新数据赋值给原本的数组即可
将 this.meg.concat([“sakura”]) 改成 this.meg= this.meg.concat([“sakura”]) 即可
点击后
watch
用来监听响应式数据变化,当监听数据变化时可执行一个函数
代码示例:meg默认值为hello,当点击按钮时meg的值改为world,watch监听到数据变化时会执行将新数据和老数据打印到控制台的函数
注意!! watch里的函数名称必须与响应式数据名称一样
1 | |

watch 是一个浅度监听,例如watch监听的是一个响应式对象,那么这个对象的属性变化,watch是监听不到的,解决方法有两种,
- 在watch的监听方法中指定监听对象的具体属性(下面例子中注释的部分)
- 在watch监听方法的末尾添加deep:true,immediate:true;
- deep:true 是开启深度监听,这样就可以监听到对象的所有属性
- immediate:true 原本watch只有在数据变化时才会监听,开启这个则会立即监听
1 | |
v-model
进行表单数据双向绑定
代码实例:输入框中输入的数据会实时显示在下方
1 | |

v-model.lazy
不加lazy 每输入一个数据都会实时绑定
加上lazy 全部输入完数据才会进行绑定
v-model.number
只有输入的数字才会进行绑定
v-moder.trim
删除数据的前后空格在绑定
引用组件
局部引用组件

全局引入组件

组件传递数据
父传子
vue2 父传子 Props
父组件
1 | |
子组件接收
1 | |
结果

这是局部引用组件,被引用的组件是子组件,子组件接收数据要用props;
props可以接收任何形式的数据
vue3 父传子传递数据
defineProps 是 Vue 3 中新引入的函数,用于定义子组件的 props。
- 在子组件中定义props
这是一个子组件(department-index)中定义的props1
2
3
4
5
6
7
8
9
10const props = defineProps({
id: {
type: String,
required: true
},
isdetail:{
type:Boolean,
required: false
}
}) - 父组件中给子组件props传值总结
1
2
3<el-tab-pane label="项目完成单位" name="department">
<department-index :isdetail="true" :id="props.id" />
</el-tab-pane>
defineProps 是 Vue 3 中一个非常强大的特性,它提供了一种更加明确和类型安全的方式来定义子组件的 props。通过使用 defineProps,我们可以让子父组件之间的数据传递更加清晰和可维护,同时也提高了代码的健壮性子接收数据校验
子组件可以规定接收数据的类型,如果父组件传递的类型不是子组件规定的,会报警告
利用props中的type
子传父(传的是函数)
vue2子传父 this.$emit
子传父利用this.$emit,其实原理是回调父组件的函数
先看子组件,子组件利用this.$emit,向父组件传递了一个函数名,和一个新数据
父组件用v-on绑定了子组件传过来的函数名和数据,并再methods中实现了。
最后效果
vue3 defineEmits
defineEmits 函数返回的是一个函数,而不是一个对象或数组。因此,不能直接修改它返回的事件列表
你可以使用 defineEmits 来定义多个事件,只需将它们作为字符串数组传递给 defineEmits 即可。例如:defineEmits([‘event1’, ‘event2’])。
在子组件中触发事件时,你可以传递任意数量的参数给事件监听器。这些参数将在父组件的事件处理函数中作为参数接收。
如果你不使用 defineEmits 来定义事件,Vue 仍然会正常工作,但使用 defineEmits 可以提供更好的类型检查和代码提示
看一个案例 分别有三个文件 base.vue edit.vue index.vue
- 子组件 base.vue
其中定义了两个个自定义事件refreshData,closeEdit ,然后在执行 submitHandle函数的时候会 触发emit(‘refreshData’)这个事件这里的自定义事件可以只是一个名字
emit(‘refreshData’)可以携带参数例如 emit(‘refreshData’, ‘1’)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//自定义事件
const emit = defineEmits(['refreshData', 'closeEdit'])
// 表单提交
const submitHandle = () => {
dataFormRef.value!.validate((valid: boolean) => {
if (!valid) {
return
}
let data = Object.assign({}, dataForm)
useProjectUpdateApi(data).then(() => {
ElMessage.success({
message: '操作成功',
duration: 500,
onClose: () => {
//visible.value = false
emit('refreshData')
}
})
})
})
} - base.vue的父组件 edit.vue
在edit.vue中 使用了base.vue组件 并用v-on监听了refreshData事件(@refresh-data=”handleRefresh”),所以当refreshData事件被触发时
edit.vue组件会监听到,然后执行handleRefresh函数,可以看到edit组件自己也自定义了两个事件,并在handleRefresh函数中触发了自己的refreshData事件1
2
3
4
5
6
7<base-edit v-if="activeName === 'base'" :id="props.id" @refresh-data="handleRefresh" />
const emit = defineEmits(['refreshData', 'closeEdit'])
const handleRefresh = () => {
emit('refreshData')
} - edit.vue的父组件index.vue
当edit中的refreshData事件被触发时,index.vue会监听到并执行getDataList函数,1
<edit ref="editRef" :id="editId" @refresh-data="getDataList"></edit>动态组件
多个组件之间来回切换,需要用到
简单实例:创建3个组件A,B,C;默认在C组件中展示A,当点击按钮后切换成B1
2
3<template>
<p>组件A</p>
</template>1
2
3<template>
<p>组件B</p>
</template>点击前1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<template>
<component :is="change"></component>
<button @click="changeHandle">切换组件</button>
</template>
<script>
import A from '@/components/A.vue'
import B from '@/components/B.vue'
export default{
data(){
return{
change: "A"
}
},
components:{
A,
B
},
methods:{
changeHandle(){
this.change=this.change== "A"?"B":"A"
}
}
}
</script>
点击后
组件存活
使用
例如 将A更改一下
1 | |
再来看点击前

先点击更新数据,会展示新数据

然后在点击两次切换组件 让他切换到A

会发现组件A的数据变成了老数据,说明组件A在被切换后被销毁了,再次切换回来只是重新加载了一边生命周期
如果需要组件存活 需要用到

这样就可以了
axios发起请求
axios用于前端发送请求到后端
- 安装 axios的依赖baseURL用来记录转发的目的地路径,可以是具体路径192.168.217.168等,这里写的是api因为会发生跨域
1
import axios from 'axios';
instance = axios.create({baseURL})是创造一个axios的实例,实例会有很多功能如图

简单使用:我这里使用的request是因为 axios的导入和URL,instance都是在request中的,所以方便一些
跨域问题
跨域指挥发生在浏览器中,浏览器不能将前端5173端口的请求转发到另一个端口上,但是可以又5173前端端口转发到后端
所以axios的URL不建议直接写后端的端口地址,会发生跨域问题
解决:
- 使用代理模式
指定URL 例如api,这样前端会把请求发送到前端 5173/api的接口中,然后利用代理,会将地址改变
target :改变的api前面的路径端口等
changeOrigin : 是否开启代理
rewrite : 可以将api替换成空格
最后结果 http://local host:5173/api 会代理成 http://local host:8080/

路由
路由帮助我们跳转页面 例如点击登录后跳转到主页面
- 安装
执行命令1
npm install vue-router@latest - 创造路由并导入
可以看到我们新建了router文件夹下面的index.js
- 首先导入vue-router,和导入组件
- 需要定义路由关系
- 创建路由,并把路由关系指定给路由
- 导出路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//导入vue-router
import { createRouter, createWebHistory } from 'vue-router'
//导入组件
import LoginVue from '@/views/Login.vue'
import LayoutVue from '@/views/Layout.vue'
//定义路由关系
const routes = [
{ path: '/login', component: LoginVue },
{ path: '/', component: LayoutVue }
]
//创建路由器
const router = createRouter({
history: createWebHistory(),
routes: routes
});
export default router
- 将路由配置全局
在main.js文件中导入路由并挂载
- 在根组件中使用路由标签挂载
1
<router-view></router-view> - 在需要跳转的函数或按钮中添加路由

子路由
子路由可以控制主页面都一部分的内容改变
例如:点击左侧,中间内容会改变
实现:
- 配置路由关系
在原来的路由关系中,导入组件,并定义子路由关系
- 在分类菜单中加入对应的路由
index是因为路由关系在我的index.js文件夹中
- 在需要展示的页面中的中间部份用路由标签挂载
pinia 携带请求头
一般登录成功后后端会传来一个token,用来确定身份,登陆后其他请求也都需要token验证
- 安装
执行命令1
npm install pinia - pinia导入全局

- 定义store

- 组件中使用store

基础知识补充
==和===
- == 号用于比较两边的值是否相等
- === 号不仅判断两边的值是否相同还需要判断两边的类型的是否相同
#default=”scope” 插槽
实现功能:表格做判断
使用template中的作用域插槽,它的作用是在外部获取组件内的数据 ,这里是为了获取这一行的数据,我们让slot-scope值为scope,那么由scope.row就可以得到数据了利用了 v-if=”scope.row.PId == 0” 判断层数,第一层的Pid为0时显示增加按钮1
2
3
4
5
6
7<el-table-column label="操作" fixed="right" header-align="center" align="center" width="160">
<template #default="scope">
<el-button v-if="scope.row.PId == 0" v-auth="'projectscorekind:add'" type="primary" link @click="addOrUpdateHandle(false, state.dataList, scope.row)">新增</el-button>
<el-button v-auth="'projectscorekind:edit'" type="primary" link @click="addOrUpdateHandle(true, state.dataList, scope.row)">修改</el-button>
<el-button v-auth="'projectscorekind:delete'" type="primary" link @click="deleteHandle(scope.row.Id)">删除</el-button>
</template>
</el-table-column>




