import findIndex from 'lodash/findIndex' import Panel from './panel.vue' import TabNav from './tabNav.jsx' import DrpMenus from './drpMenus' const Tabs = { name: 'PTabs', props: { value: {}, hasMoreMenu:{ type:Boolean, default:true }, hasContextMenu:{ type:Boolean, default:true } }, watch: { value(value) { this.setCurrentName(value) }, }, inject:['showTab','hideTab'], data() { return { currentName: this.value || this.activeName, contextMenuKey: null, scrollStep: 115, showScroll: false, panels: [] } }, created() { this.$on('tab-nav-update', this.calcPaneInstances.bind(null, true)); }, mounted() { this.calcPaneInstances(); window.addEventListener('resize',this.resize); }, updated() { this.calcPaneInstances(); }, beforeDestroy() { window.removeEventListener('resize',this.resize); }, methods: { setCurrentName(value) { this.currentName = value; //绑定提是v-model所以这里要加一下,这样可以对 props 传进来的value 进行改变 this.$emit('input', value); this.$nextTick(r=>{ let panel = this.getItem(value); this.$emit('onActiveTab',panel); }); }, calcPaneInstances() { //收集插槽里头的组件实例,以重新渲染 if (this.$slots.default) { const panelslots = this.$slots.default.filter(vnode => vnode.tag && vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'PTabpanel'); // update indeed const panels = panelslots.map(({ componentInstance }) => componentInstance); const panelsChanged = !(panels.length === this.panels.length && panels.every((pane, index) => pane === this.panels[index])); if (panelsChanged) { this.panels = panels; this.$set(this,'panels',panels) } } else if (this.panels.length !== 0) { this.$set(this,'panels',[]) } }, closeItem(key) { let me = this; me.$emit('onRemoveTab', key); me.resize(); }, closeCurItem() { this.closeItem(this.currentName); }, getItemIndex(name) { let index = findIndex(this.panels, item => { return item.name == name; }); return index; }, getItem(name) { let index = findIndex(this.panels, item => { return item.name == name; }); if (index > -1) { return this.panels[index]; } return null; }, getItemObj(name) { let panel = this.getItem(name); if (panel == null) return null; return { //.$refs['TabNavs'] id:name, uid:name, name:name, tabEl: this.$el.querySelector('#tab_'+name),//null tabPanelEl: panel.$el, tabPanelIframeEl: panel.$el.querySelector('iframe') }; }, getSeldItemObj() { return this.getItemObj(this.currentName); }, resize() { this.$refs['TabNavs'].resize(); // console.log('height', this.$refs['domTabHead'].offsetHeight) // console.log('offsetHeight', this.$el.offsetHeight) this.$refs['domTabBody'].style.height = this.$el.offsetHeight - this.$refs['domTabHead'].offsetHeight + 'px'; // console.log('main height', this.$refs['domTabBody'].style.height) let tabScroll = this.$refs['domTabScroll']; this.showScroll = tabScroll.offsetWidth < tabScroll.scrollWidth; }, handleShowDrpMenus(evt) { evt.stopPropagation(); const rects = evt.currentTarget.getClientRects()[0]; this.$refs['cmp-drpMenus'].show(rects.left,rects.top + rects.height); }, handleHideDrpMenus() { this.$refs['cmp-drpMenus'].hide(); }, handleMoreMenuClick(vm, event) { // this.activeKey = vm.$el.getAttribute('alt'); this.resize(); }, handleScrollLt(step) { let el = this.$refs['domTabScroll']; el.scrollLeft = el.scrollLeft - (step || this.scrollStep); }, handleScrollLtMouseDown() { let me = this; me.scrollPressTimer = setInterval(function () { me.handleScrollLt(10); }, 10); }, handleScrollLtMouseUp() { clearInterval(this.scrollPressTimer); }, handleScrollRt(step) { let el = this.$refs['domTabScroll']; el.scrollLeft = el.scrollLeft + (step || this.scrollStep); }, handleScrollRtMouseDown() { let me = this; me.scrollPressTimer = setInterval(function () { me.handleScrollRt(10); }, 10); }, handleScrollRtMouseUp() { clearInterval(this.scrollPressTimer); }, handleTabChange(panel) { if(panel.name==this.currentName){ return; } this.setCurrentName(panel.name); }, handleTabClose(name) { this.closeItem(name); }, handleTabCloseAll(){ this.$emit('onRemoveAllTab'); this.resize(); }, handleTabCloseLt(name,index){ this.$emit('onRemoveLeft',name,index); this.resize(); }, handleTabCloseRt(name,index){ this.$emit('onRemoveRight',name,index); this.resize(); }, handleTabCloseOt(name,index){ this.$emit('onRemoveOther',name,index); this.resize(); }, handleFullScreen(){ this.$emit('onFullScreen') } }, render(h) { let {hasMoreMenu,hasContextMenu}=this; let children = this.panels; let navData={ props:{ panels:children, hasContextMenu:hasContextMenu }, on:{ onTabChange: this.handleTabChange, onTabClose: this.handleTabClose, onTabCloseAll: this.handleTabCloseAll, onTabCloseLt:this.handleTabCloseLt, onTabCloseRt:this.handleTabCloseRt, onTabCloseOt:this.handleTabCloseOt, onFullScreen:this.handleFullScreen }, ref:'domTabSrcollInner' }; let scrollLtBtn = { style: { display: this.showScroll ? 'inline-block' : 'none' }, on: { //click:this.handleScrollLt, mousedown: this.handleScrollLtMouseDown, mouseup: this.handleScrollLtMouseUp, } }, scrollRtBtn = { style: { display: this.showScroll ? 'inline-block' : 'none' }, on: { //click:this.handleScrollRt, mousedown: this.handleScrollRtMouseDown, mouseup: this.handleScrollRtMouseUp, } }, moreBtn = { on: { mouseover: this.handleShowDrpMenus, mouseout: this.handleHideDrpMenus } }, drpMenus = { props: { children: children }, on: { click: this.handleMoreMenuClick, onTabChange: this.handleTabChange, onTabClose: this.handleTabClose } }, hideSty = { on: { mouseout: this.showTab, mouseover: this.hideTab } }; return ( <div class="pl-tabs"> <div class="pl-tabs-hd" ref='domTabHead'> <div class="pl-tabs-tool" ref='domTabTool'> <div class="item" title='左边滚动' ref='domTabScrollLt' {...scrollLtBtn}> <i class="iconfont icon-arrow-left"></i> </div> <div class="item" title='右边滚动' ref='domTabScrollRt' {...scrollRtBtn}> <i class="iconfont icon-arrow-right"></i> </div> { hasMoreMenu&&( <div class="item" title='更多' ref='domTabScrollMore' {...moreBtn} > <i class="iconfont icon-arrow-down"></i> <DrpMenus ref="cmp-drpMenus" {...drpMenus}></DrpMenus> </div> ) } </div> <div class="pl-tabs-scroll" ref='domTabScroll'> <TabNav {...navData} ref='TabNavs'></TabNav> </div> </div> <div class="pl-tabpanel-bd" ref='domTabBody' {...hideSty}> {this.$slots.default} </div> </div> ) } } export default Tabs;