学习链接
Vue Router获取当前页面由哪个路由跳转
在Vue3的setup中如何使用this
- beforeRouteEnter 在这个路由方法中不能访问到组件实例this,但是可以使用next里面的vm访问到组件实例,并通过vm.$data获取组件实例上的data数据
- getCurrentInstance 是vue3提供的获取组件实例的方法,可通过getCurrentInstance函数获取了当前组件实例对象,并通过instance.data.message和instance.ctx.sayHello访问了组件实例的数据和方法
<template>
<div class="main-box">
<div class="title">菜单权限</div>
<div class="role-menu-box" v-loading="dataLoading">
<div class="role-menu-header">
<el-form inline :model="roleInfo" ref="roleInfoRef" :rules="roleInfoRules" label-width="80px">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="roleInfo.roleName"></el-input>
</el-form-item>
<el-form-item label="角色标识" prop="roleLabel">
<el-input v-model="roleInfo.roleLabel"></el-input>
</el-form-item>
</el-form>
</div>
<div class="role-menu-body">
<el-scrollbar>
<el-tree :props="defaultProps" node-key="id" :expand-on-click-node="false" check-on-click-node
default-expand-all ref="menuTreeRef" show-checkbox :data="roleMenuTreeData">
</el-tree>
</el-scrollbar>
</div>
<div class="role-menu-footer">
<el-button @click="goBack">返回</el-button>
<el-button type="primary" @click="saveRoleMenu">保存</el-button>
</div>
</div>
</div>
</template>
<script>
import msgBoxer from '@/utils/msgBoxer'
export default {
// name: 'roleMenu', // 这个组件不应该被缓存下来, 因此需要让 路由名称 与 组件名称不一致
data() {
return {
formerRoute: {},
isSaved: false
}
},
// 在进入路由的时候, 记录进入之前的路由
beforeRouteEnter(to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
let { query, params, path } = from
vm.$data.formerRoute = { query, params, path } // 没有this, 只能通过vm去访问组件实例上的数据
})
},
}
</script>
<script setup>
import { ref, reactive, onMounted, nextTick, getCurrentInstance } from 'vue'
import { getRoleMenuByRoleId as getRoleMenuByRoleIdApi, saveRoleMenu as saveRoleMenuApi } from '@/api/roleApi'
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router'
import Messager from '@/utils/messager'
// 使用tagsViewStore
import useTagsView from '@/store/tagsView'
const tagsViewStore = useTagsView()
const dataLoading = ref(false)
// 获取组件实例
const instance = getCurrentInstance()
// 使用路由
const route = useRoute()
const router = useRouter()
const defaultProps = {
label: 'title',
children: 'children'
}
// 角色信息
let roleInfo = ref({})
// 菜单树ref
const menuTreeRef = ref(null)
// 菜单树数据
let roleMenuTreeData = ref([])
const roleInfoRules = {
roleName: [
{ required: true, message: '角色名称不能为空', trigger: 'blur' }
],
roleLabel: [
{ required: true, message: '角色标识不能为空', trigger: 'blur' }
]
}
function getRoleMenuByRoleId() {
console.log(route);
getRoleMenuByRoleIdApi(route.params.roleId).then(({ roleId, roleName, roleLabel, menuIdList, roleMenuTreeDTOList }) => {
roleInfo.value = { roleId, roleName, roleLabel, menuIdList }
roleMenuTreeData.value = roleMenuTreeDTOList
// window.menuTreeRef = menuTreeRef
nextTick(()=>{
menuIdList.forEach(menuId=>{
menuTreeRef.value.setChecked(menuId, true, false)
})
})
})
}
onMounted(() => {
getRoleMenuByRoleId()
})
function saveRoleMenu() {
// 这里要注意下顺序, 半选的要在前面, 选中状态的要在后面
// (半选状态对于后台权限来说是有意义的, 若子节点被选中, 那么该子节点的所有父节点都应该要有)
let menuIdList = [...menuTreeRef.value.getHalfCheckedKeys(), ...menuTreeRef.value.getCheckedKeys(false) ]
saveRoleMenuApi({ ...roleInfo.value, menuIdList }).then(res => {
Messager.ok('保存成功')
instance.data.isSaved = true // 记录保存, 通过instance访问组件实例上data配置项的数据
router.push({ ...instance.data.formerRoute }) // 回到之前的路由去
})
}
function goBack() {
instance.data.isSaved = true // 记录保存, 通过instance访问组件实例上data配置项的数据
if(instance.data.formerRoute.path) {
router.push({ ...instance.data.formerRoute })
} else {
router.push('/sys/role')
}
}
/* 在路由离开之前, 判断是否是点击保存值后离开的,
如果不是点击保存后离开的, 就弹框问是不是要离开,
如果确定是, 就离开, 并关闭页签, 如果不是, 就取消离开, */
onBeforeRouteLeave((to, from, next)=> {
// console.log('beforeRouteLeave');
if (!instance.data.isSaved) {
msgBoxer.confirm('您确定要离开当前页面么?').then(res => {
next()
// 关闭当前页签
tagsViewStore.closeSpecifiedTag({name: route.name})
}).catch(err => {
next(false)
})
} else {
next()
// 关闭当前页签
tagsViewStore.closeSpecifiedTag({name: route.name})
}
})
console.log('setup...');
</script>
<style lang="scss" scoped></style>