vue 使用keep-alive 实现多页签并支持强制刷新
需求我司有一款使用Vue构建的SPA 后台管理系统,此时客户提出一个需求。1:要求支持打开多页签2多页签保留状态,即切换页签的时候不重新刷新内容。3关闭某一页签之后,重新打开之后,需要进行刷新4在当前页面可以进行强制刷新功能。如图示意(左侧箭头为多页签,右侧为强制刷新按钮,图是网图,非本公司后台管理系统页面,效果类似)思路1:首先编写Tags(...
·
需求
我司有一款使用Vue构建的SPA 后台管理系统,此时客户提出一个需求。
1:要求支持打开多页签
2多页签保留状态,即切换页签的时候不重新刷新内容。
3关闭某一页签之后,重新打开之后,需要进行刷新
4在当前页面可以进行强制刷新功能。
如图示意(左侧箭头为多页签,右侧为强制刷新按钮,图是网图,非本公司后台管理系统页面,效果类似)
思路
1:首先编写Tags(多页签) 2:使用Keep-alive包裹 router-view。 3:利用router-view key值变化会导致内容刷新来实现页面强制刷新
已打开菜单组件
Tags(多页签)左侧箭头指出功能
<template>
<div class="vtag" id="nTabs">
<div class="overFlowWapper" ref="overFlowWapper">
<div class="tagItemWapper" ref="tagItemWapper" v-bind:style="{ width:tagsList.length*110+'px',marginLeft:curGo+'px'}">
<div class="tagItem" v-for="(item,index) in tagsList" v-bind:class="{ active: isActive(item.path) }"
@contextmenu="showMenu" @click="goMe(item)" :title="(myRouter[item.name]||item.title)+(item.queryName||'')">
<a class="leftx" v-bind:class="{canCloseNot:!item.canClose}">
{{(myRouter[item.name]||item.title)+(item.queryName||'')}}
</a>
<a class="rightx" v-if="item.canClose" @click.stop="delTags(index)"><span>×</span></a>
<vue-context-menu :contextMenuData="contextMenuData" @delAll="delAll">
</vue-context-menu>
</div>
</div>
</div>
<div class="tagBtn tagleft" @click="tagLeft" v-if="tagsButtonShow">
<img src="static/img/svg/icon_narrow.svg">
</div>
<div class="tagBtn tagRight" @click="tagRight" v-if="tagsButtonShow">
<img src="static/img/svg/icon_narrow.svg">
</div>
<div class="tagBtn tagRefresh" @click="refreshCurrent">
<img src="static/img/svg/icon_refresh.svg">
</div>
</div>
</template>
<script>
import bus from './bus';
export default {
data() {
return {
contextMenuData: {
// the contextmenu name(@1.4.1 updated)
menuName: 'demo',
// The coordinates of the display(菜单显示的位置)
axis: {
x: null,
y: null
},
// Menu options (菜单选项)
menulists: [
{
fnHandler: 'delAll', // Binding events(绑定事件)
icoName: 'fa fa-home fa-fw', // icon (icon图标 )
btnName: '关闭所有' // The name of the menu option (菜单名称)
},
]
},
tagsList: [],//tag集合
myRouter: {},
curGo:0,// 当前往左走的步伐,往左为正数,往右为负数
tagsButtonShow:false,//是不是应该显示左右侧按钮
defaultPage:{
path:"",
name: "",
canClose:false,
title:"",
keepAlive:true
}
}
},
methods: {
//右键菜单的使用
showMenu () {
event.preventDefault();
let x = event.clientX;
let y = event.clientY;
// Get the current location
this.contextMenuData.axis = {
x, y
}
},
delAll()
{
this.tagsList = [];
this.$router.push('/');
this.tagsList.push(this.defaultPage);
},
//刷新当前页
refreshCurrent() {
bus.$emit('keyCurName', 1);
},
//按钮
tagLeft() {
this.curGo = 0;
},
//按钮
tagRight() {
let owidth = this.$refs.overFlowWapper.offsetWidth;
let twidth = this.$refs.tagItemWapper.offsetWidth;
this.curGo =owidth-twidth;
},
//切换是不是显示左右侧按钮的状态,规则:当tagItemWapper的宽度大于overFlowWapper时,显示两侧按钮
tagsButtonShowChange() {
if(typeof this.$refs.overFlowWapper == "undefined") {
this.tagsButtonShow = false;
return
}
let owidth = this.$refs.overFlowWapper.offsetWidth;
// let twidth = this.$refs.tagItemWapper.offsetWidth; 这里不能用这个,这里有动画会延迟
let twidth = 10 + this.tagsList.length*110;
if(twidth > owidth + 15) {
this.tagsButtonShow = true;
}
else {
this.tagsButtonShow = false;
//测试提出:当导航标签数量较多出现左右滚动条时,向右滚动标签后从右边依次关闭标签,当空间足够展示当前打开的所有标签时,左侧被遮挡的标签没有自动展示
this.curGo = 0;
}
},
goMe(item)
{
this.$router.push(item.path);
},
delTags(index)
{
//工作看板不可以被关闭哟
if(index == 0) {
return;
}
const delItem = this.tagsList.splice(index, 1)[0];
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
if (item) {
delItem.path === this.$route.fullPath && this.$router.push(item.path);
}else{
this.$router.push('/');
}
},
isActive(path) {
return path === this.$route.fullPath;
},
//根据路由切换Tags标签
setTags(route)
{
if(this.tagsList.length < 1) {
if(this.defaultPage.name == "")
{
let path = this.$router.options.routes[0].redirect;
let children = this.$router.options.routes[1].children;
for(let i=0;i<children.length;i++) {
let copy_i = children[i];
if(copy_i.path == path ) {
this.defaultPage.name = copy_i.name;
this.defaultPage.path = copy_i.path;
this.defaultPage.title = copy_i.meta.title;
this.defaultPage.keepAlive = copy_i.meta.keepAlive;
}
}
}
this.tagsList.push(this.defaultPage);
}
let isExist = false; //是不是已经打开了这个标签
for(let i=0;i<this.tagsList.length;i++) {
if(this.tagsList[i].path === route.fullPath) {
isExist = true;
break;
}
}
if(!isExist)
{
if(this.tagsList.length>11) {
this.tagsList.splice(1,1);
}
this.tagsList.push({
title: (this.myRouter[route.name]||route.meta.title),
path: route.fullPath,
name: route.matched[1].name,
keepAlive:route.meta.keepAlive,
canClose:true,
//详情页 附加名称
queryName: (route.query.name?"-"+route.query.name : "")
})
}
this.changePosition(route);
},
//测试提出:当导航标签数量较多出现左右滚动条时,通过导航菜单打开新标签或激活被隐藏的标签时,没有自动将导航标签移动到活动标签处
changePosition(route) {
let currentPosition = 1;//当前位置,从1开始
for(let i=0;i<this.tagsList.length;i++) {
if(this.tagsList[i].name == route.name) {
currentPosition = i+1;
}
}
let currentPositionRight = 110*currentPosition-10;//当前标签最右侧的位置
//如果当前标签最右侧的位置超出了边界,那么让他拽出来
if(this.$refs.overFlowWapper) {
if(currentPositionRight>this.$refs.overFlowWapper.offsetWidth) {
let owidth = this.$refs.overFlowWapper.offsetWidth;
let twidth = this.tagsList.length*110;
this.curGo =owidth-twidth;
}
}
},
},
computed: {
},
watch:{
$route:{
immediate:true,
handler:function(newValue){
this.setTags(newValue);
},
deep:true
},
tagsList:{
immediate:true,
handler:function(newValue) {
bus.$emit('keepList', this.tagsList);
this.tagsButtonShowChange();
},
},
'$store.state.myRouter':{
immediate:true,
handler:function(newValue){
let myRouter = {};
if(newValue != null) {
for(let i=0; i<newValue.length; i++) {
myRouter[newValue[i].url] = newValue[i].label;
}
}
this.myRouter = myRouter;
},
deep:true
},
},
created(){
},
mounted()
{
//当页面分辨率发生变化时,将curGo 偏移量修改为0
this.addResizeFunctions({
type: "const",
name: "tags",
callback: ()=>{
this.curGo = 0;
this.tagsButtonShowChange();
}
});
}
}
</script>
复制代码
Home页面
<v-tags></v-tags> <!--刚才的tags组件-->
<div class="content">
<keep-alive :include="myKeepList">
<router-view :key="key">
</router-view>
</keep-alive>
</div>
复制代码
export default {
data(){
return {
myKeepList: [""],
bindKeys:{
addEs: "24",
addWorkflow: "30",
announceIssuerWatching: "45",
approvalHistory: "33",
approvalTask: "32",
bondDetail: "50",
},
}
},
components:{
vTags
},
computed: {
key() {
return this.bindKeys[this.$route.name];
},
...mapState(['routerKey','copyRight'])
},
watch:{
'$route': {
immediate: true,
handler: function (val) {//监听路由是否变化
this.showFooter = (val.name =="dashboard"?false:true);
}
}
},
methods: {
},
created(){
// 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
bus.$on('keepList', msg => {
let arr = [];
for(let i=0;i<msg.length;i++) {
let copy_m = msg[i];
if(copy_m.keepAlive) {
arr.push(copy_m.name);
}
}
this.myKeepList = arr;
});
// 点击强制刷新按钮会触发这里。
bus.$on('keyCurName', msg => {
this.bindKeys[this.$route.name] = new Date().getTime();
});
},
mounted() {
},
}
作者:嚣张的胖头鱼
链接:https://juejin.im/post/5ddfd39ae51d456b345adf2f
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
更多推荐
已为社区贡献2条内容
所有评论(0)