Why Dynamite Vue components in an array auto refresh

Viewed 51

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'

0 Answers
Related