I have a problem about dynamite vue component beyond my ability, here is the question:
1.click icons
icons
2.put components into an array and render components dynamitically
click icons and render components
3.click tabs, tabs will be removed and, components relatived with tabs will be removed too
close tabs and windows
when I close tabs or windows from right, everything is ok, but when I close tabs or windows which index less then active window, the active window will refresh。I tried a lot of ways to resolve it, but it doesnt work.
Is there someone else had the same problem, or give me some suggestions, thanks.
Router:
var router = [{
path: '',
redirect: '/layout'
}, {
path: '/',
component: App,
redirect: '/layout',
children: [{
path: '/login',
component: login,
beforeEnter: redirectToHome
},
{
path: '/layout',
component: layout
},
{
path: '/getbackPwd',
component: getbackPwd
},
{
path: '/*',
component: notfound
}]
}]
Layout:
<div class="mu-layout">
<LayoutHead>
<div class="mu-layout-head-left">
<a class="mu-layout-showdesk" @click="toggleShowDesk"></a>
<a class="mu-layout-toggle-sidebar" @click="toggleSidebar">
<i class="el-icon-menu"></i>
</a>
<layout-tab v-for="(tab, i) in iconTabs"
:key="i"
:title="tab.title"
:component="tab.componentName"
:img="tab.img"
:minisize="tab.showMinisize"
:current="tab.current"
@close="closeTab"
@choose="chooseTab"
:tabIdx="i"
></layout-tab>
</div>
<div class="mu-layout-head-right">
<a class="mu-layout-head-link">
<i class="el-icon-search"></i>
</a>
<a class="mu-layout-head-link">
<i class="el-icon-warning" title="通知"></i>
</a>
<a class="mu-layout-head-link">
<i class="iconfont icon-act7"></i>
<span class="head-user-wrap">
{{loginUser && loginUser.username}}
</span>
</a>
<el-popover placement="bottom"
width="160"
trigger="hover"
popper-class="rect-popper"
>
<ul class="mu-layout-list mu-setting-list">
<li class="mu-layout-item">
<a class="mu-layout-item-inner" @click="openSetting"><i class="el-icon-edit-outline"></i>修改密码</a>
<a class="mu-layout-item-inner" @click="logout"><i class="el-icon-logout"></i>注销</a>
</li>
</ul>
<a class="mu-layout-head-link" slot="reference"><i class="icon-more"></i></a>
</el-popover>
</div>
</LayoutHead>
<div class="mu-layout-content">
<div class="swiper-container swiper-no-swiping">
<div class="swiper-wrapper">
<div class="swiper-slide">
<layout-iconmenu-panel>
<layout-icon-menu :img="imenu.img"
:component="imenu.component"
:title="imenu.title"
:menu-id="imenu.menu_id"
v-for="(imenu, i) in iconMenus"
:key="i"
@click="clickIconMenu"
></layout-icon-menu>
</layout-iconmenu-panel>
</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</div>
</div>
<win-panel :title="comp.title"
:tool-title="`${comp.title}(${comp.componentName})`"
:minisize-event="minisize"
@close-event="close"
:component="comp.componentName"
:ref="comp.componentName"
@choose="chooseWin"
:current="comp.current"
v-for="(comp, i) in wpanels"
:key="i"
v-model="comp.show"
:resizable="comp.resizable"
:win-width="comp.width"
:win-height="comp.height"
:is-sys="comp.isSys"
:clazz="comp.classname"
@monitor-win="monitorWin"
:rect="{drag_x: comp.drag_x, drag_y: comp.drag_y , resize_x: comp.resize_x, resize_y: comp.resize_y}"
>
<component :is="comp.comp" ></component>
</win-panel>
<layout-sidebar v-model="sidebarModel"></layout-sidebar>
</div>
import $ from 'jquery'
import LayoutHead from './head'
import LayoutFoot from './foot'
import LayoutLaunch from './button'
import LayoutIconMenu from './iconmenu'
import LayoutIconmenuPanel from './iconmenu-panel'
import LayoutTab from './tabs'
import LayoutPost from './post'
import LayoutSidebar from './sidebar'
import WinPanel from './winpanel'
import * as Components from '../getComponent'
import {
setActivePanel,
getActivePanel,
removeActivePanel,
logout,
getLoginUser,
getLoguserMenus,
setMenuId,
getMenuId
} from '../utils/auth'
import { stopPropagation } from '../utils'
import Swiper from 'swiper'
export default {
components: {
LayoutTab,
LayoutHead,
LayoutPost,
LayoutFoot,
LayoutLaunch,
LayoutSidebar,
LayoutIconMenu,
LayoutIconmenuPanel,
WinPanel,
},
data() {
var _userMenus = getLoguserMenus()
var $menus = _userMenus ? JSON.parse(_userMenus).map(e => {
return {
img: e.menu_icon,
component: e.menu_component,
title: e.menu_name,
menu_id: e.menu_id
}
}).filter(e => e.component!= 'login') : [] //排除登录组件
return {
Components,
sidebarModel: false,
loginUser: getLoginUser(),
iconMenus: $menus,
iconTabs: [],
wpanels: [],
showDeskModel: false,
activeIdx: 0, //当前激活的索引
}
},
methods: {
/*
* 根据传入的arrs进行map 操作,在回调中传入遍历的参数
*/
filterArrs(comName, cb, arrs) {
arrs = arrs ? arrs : this.iconTabs
arrs = arrs.map(e => {
cb(e)
return e
})
},
/*
* 切换sidebar事件
*/
toggleSidebar(e) {
stopPropagation(e)
this.sidebarModel = !this.sidebarModel
},
/*
* 选择窗口
*/
chooseWin(comName) {
this.toggleTab( comName )
},
/*
* 点击tab的操作事件
*/
chooseTab(comName, minisize, current) {
this.setMenuids(comName)
if(current) {
this.filterArrs(comName, e => {
if(e.componentName == comName) {
e.current = false
}
})
this.filterArrs(comName, e => {
if(e.componentName == comName ) {
e.show = false
}
}, this.wpanels)
}
else {
this.filterArrs(comName, e => {
if(e.componentName == comName ) {
e.current = true
} else {
e.current = false
}
})
this.filterArrs(comName, e => {
if(e.componentName == comName ) {
e.show = true
e.current = true
}
}, this.wpanels)
}
},
/*
* 切换不同的tab
*/
toggleTab(comName) {
this.filterArrs(comName, e => {
if(e.componentName == comName) {
e.current = true
} else {
e.current = false
}
})
this.showDeskModel = !this.showDeskModel
setActivePanel(comName)
this.setMenuids(comName)
},
/*
* 点击icon 菜单
*/
clickIconMenu(componentName, title, img, menuId, config) {
var filters = this.iconTabs.filter(e => e.componentName == componentName)
if(filters.length == 0) {
var _config = {
title,
componentName,
img,
showMinisize: false,
current: true,
comp: Components[componentName],
show: true,
menuId
}
if(componentName == 'sysSetting') {
_config.isSys = true
}
if(config) {
_config = Object.assign(_config, config)
}
this.iconTabs.push(_config)
this.wpanels = this.iconTabs.slice(0)
} else {
this.wpanels = this.wpanels.map(function(e) {
if(e.componentName == componentName) {
e.current = true
e.show = true
} else {
e.current = false
}
return e
})
this.iconTabs = this.iconTabs.map(function(e) {
if(e.componentName == componentName) {
e.current =true
} else {
e.current = false
}
return e
})
}
this.toggleTab( componentName )
this.filterArrs(componentName, e => {
if(e.componentName == componentName) {
e.current = true
} else {
e.current = false
}
}, this.wpanels)
},
/*
* 自动选择最后一个tab 和 窗口
*/
autoChooseLast() {
if(this.iconTabs.length > 0) {
var $fs = this.iconTabs.filter(e => e.current)
if($fs.length == 0) {
setTimeout(_ => {
this.iconTabs.forEach((e, i) => {
if(i == this.iconTabs.length - 1) {
e.current = true
this.wpanels[i].current = true
this.wpanels[i].show = true
setActivePanel(e.componentName)
}
})
})
}
} else {
removeActivePanel()
}
},
/*
* 窗口最小化
*/
minisize(id, component, e) {
// stopPropagation(e)
this.filterArrs(component, el => {
if(el.componentName == component) {
el.current = false
}
})
this.filterArrs(component, el => {
if(el.componentName == component) {
el.show = false
el.current = false
}
}, this.wpanels)
// this.autoChooseLast()
},
/*
* 关闭窗口事件
* 和关闭tab 相同,需要阻止冒泡,否则最外层的事件会冲突
*/
close(component, e) {
stopPropagation(e)
this.closeTab(component, e)
},
/*
* 关闭tab,同时关闭相关联的窗口
*/
closeTab(comName, e) {
stopPropagation(e)
this.iconTabs = this.iconTabs.filter(el => el.componentName != comName)
this.wpanels = this.wpanels.filter(e => e.componentName != comName)
this.autoChooseLast()
},
/*
* 切换显示菜单
*/
toggleShowDesk() {
if(this.iconTabs.length == 0 || this.wpanels.length == 0) {
return
}
if(!this.showDeskModel) {
this.iconTabs = this.iconTabs.map(function(e) {
e.current = false
return e
})
this.wpanels = this.wpanels.map(function(e) {
e.show = false
return e
})
} else {
this.wpanels = this.wpanels.map(function(e) {
e.show = true
return e
})
this.autoChooseLast()
}
this.showDeskModel = !this.showDeskModel
}
},
}
Actrually, most of my components dont relate with router, but dynamitecally component rendering. The website is just like an web os, every icon has its own page, they are all in layout.vue page, the router path always is '/layout'