ul元素显示的是tabs控件的导航标签部分,根据每个tab页的显示或者隐藏来确定标签是否激活,它还有一个功能就是接受鼠标点击事件,传给控制脚本,模板基本没什么逻辑,主要就是显示和接收事件。
整个选项卡body是否显示,根据showTabBody计算属性确定。因为选项卡body有时停靠在控件左侧,有时停靠在控件右侧,这个停靠方式根据属性dockLeft确定,如果停靠在左边dockLeft为true,反之为false。
根据计算属性showTabTitle确定是否显示。关闭按钮负责接收点击事件,传递给控制器脚本。不管用什么样的方式实现,控制脚本只要能满足模板的这个要求就可以了。相当于接口定了,根据接口设计实现方式。
NormalState(普通tabs控件),MiddleState(列表状态,带标题带图标),MiniState(迷你列表状态,只显示图标)。后两个类有一些共同的操作,比如弹出隐藏选项卡等,可以继承共同的基类:ListState,三个状态类功能上也有一些交集,他们可以有共同的基类State。类关系图如下(好多年没有用UML工具了,用Excel凑合一下):
不仔细看,不知道这个图其实是Excel画的,还以为是哪个高端UML工具做的呢。
状态类对应的代码:
classState{
constructor(context){this.context=context
}
widthChange(width){if(width<=90){this.toState(this.context.miniState)
}elseif(width<=160){this.toState(this.context.middleState)
}else{this.toState(this.context.normalState)
}
}
showTabBody(){returntrue}
showTabTitle(){returnfalse}
showIcon(){returnfalse}
showTitle(){returntrue}
close(){}
toState(state){if(this.context.state!==state){if(this.context.state===this.context.normalState){this.context.selectedTab.isShow=falseconsole.log('dddd')
}if(state===this.context.normalState){this.context.selectedTab.isShow=true}this.context.state=state
}
}
stateClass(){return''}
}
classNormalStateextendsState{
constructor(context){
super(context)
}
clickTab(clickedTab){this.context.tabs.forEach(tab=>{
tab.isShow\=(tab.name==clickedTab.name)this.context.selectedTab=clickedTab
});
}
}//需要弹出式显示标签内容
classListStateextendsState{
constructor(context){
super(context)
}
showTabBody(){returnthis.context.selectedTab.isShow
}
showTabTitle(){returntrue}
showIcon(){returntrue}
showTitle(){returntrue}
close(){this.context.selectedTab.isShow=false}
clickTab(clickedTab){this.context.tabs.forEach(tab=>{if(tab===clickedTab){
tab.isShow\=!tab.isShowthis.context.selectedTab=clickedTab
}else{
tab.isShow\=false}
});
}
}//该状态显示图标跟标题
classMiddleStateextendsListState{
constructor(context){
super(context)
}
stateClass(){return'middle-size'}
}//该状态只显示图标
classMiniStateextendsListState{
constructor(context){
super(context)
}
showTitle(){returnfalse}
stateClass(){return'mini-size'}
}
控件脚本代码:
exportdefault{
name:'WidgetTabs',
data(){return{
tabs:\[\],
state:null,
selectedTab:null,
dockLeft:false,
}
},
created(){this.tabs=this.$children;this.normalState=newNormalState(this)this.middleState=newMiddleState(this)this.miniState=newMiniState(this)this.state=this.normalState
},
computed:{
stateClass(){returnthis.state.stateClass()
},
showIcon(){returnthis.state.showIcon()
},
showTitle(){returnthis.state.showTitle()
},
showTabBody(){returnthis.state.showTabBody()
},
showTabTitle(){returnthis.state.showTabTitle()
},
},
methods:{
click(clickTab){this.state.clickTab(clickTab)
},
mouseMove(){if(this.$refs.widget){this.dockLeft=this.$refs.widget.offsetLeft<50
this.state.widthChange(this.$refs.widget.offsetWidth)
}
},
mouseDown(event){
document.addEventListener('mousemove',this.mouseMove)
},
mouseUp(event){
document.removeEventListener('mousemove',this.mouseMove)
},
close(){this.state.close()
}
},
mounted(){
document.addEventListener('mousedown',this.mouseDown)
document.addEventListener('mouseup',this.mouseUp)this.tabs.forEach(tab=>{if(tab.isShow){this.selectedTab=tab
}
});
},
beforeDestroyed(){
document.removeEventListener('mousedown',this.mouseDown)
document.removeEventListener('mouseup',this.mouseUp)
},
}
组件创建时初始化各种状态。需要注意的一点是,需要在窗口变化时动态获取控件宽度,来确定控件是处在哪个状态。JS中DIV没有resize事件,可以通过鼠标事件来代替。我们的窗口大小是通过鼠标拖动实现的,所以跟踪鼠标拖动事件,动态查询控件大小,然后分发事件。
这个控件至此就完成了,写这个文章的事件比写代码时间长,天生是个程序员不是writer。
整个项目在这个历史节点的代码,请到我的Github上查看:https://github.com/vularsoft/...
找到该历史节点的方法:
RXEditor是一个Boostrap代码可视化编辑工具,本系列记录了该软件的开发过程,有问题的朋友请在ithub上给我留言。
总结
到此这篇关于Vue状态模式实现窗口停靠功能(灵动、自由,管理后台Admin界面)的文章就介绍到这了,更多相关vue状态模式实现窗口停靠内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。