programing

어레이 자동 갱신에 Dynamite Vue 컴포넌트가 필요한 이유

coolbiz 2022. 7. 3. 18:14
반응형

어레이 자동 갱신에 Dynamite Vue 컴포넌트가 필요한 이유

다이너마이트 Vue 컴포넌트에 대해 내 능력 밖의 문제가 있습니다.여기서 질문이 있습니다.

1. 아이콘 클릭
2. 컴포넌트를 어레이에 배치하고 컴포넌트를 동적으로 클릭하여 컴포넌트를 렌더링한다.
3. 탭을 클릭하면 탭이 삭제되고 탭과 관련된 컴포넌트가 탭과 창에 너무 가깝게 삭제됩니다.

오른쪽에서 탭이나 창을 닫으면 모든 것이 정상입니다만, 액티브한 창보다 인덱스가 적은 탭이나 창을 닫으면 활성화 창이 새로 고쳐집니다.여러 가지 방법으로 해결했지만 작동하지 않습니다.

다른 사람도 같은 문제를 겪었거나 제안해 준 적이 있나요? 감사합니다.

라우터:


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
    }]
}]

레이아웃:

<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
            }
        },
    }

실제로 대부분의 컴포넌트는 라우터와 관련이 없지만 다이너마이트하게 컴포넌트 렌더링을 하고 있습니다.웹사이트는 웹 OS와 비슷하며 모든 아이콘에는 자체 페이지가 있으며 모두 레이아웃되어 있습니다.vue 페이지, 라우터 경로는 항상 '/filename'입니다.

언급URL : https://stackoverflow.com/questions/52368196/why-dynamite-vue-components-in-an-array-auto-refresh

반응형