Vue-element-admin clicks on the sidebar to refresh the current page

vue-element-admin clicks on the sidebar to refresh the current page

Write the directory title here

  • Vue-element-admin clicks on the sidebar to refresh the current page
    • foreword
    • 1. Refresh the entire routing page
    • 2. Only refresh the nested routing page

Foreword

Before using the spa (single-page application) development model, users would re-request this page every time they clicked on the sidebar. Users gradually developed the habit of clicking the current route on the sidebar to refresh the view Habit. But now the spa is different, the user clicks the currently highlighted route and will not refresh the view, because vue-router will intercept your route, it judges that your url has not changed, so it will not trigger any hooks or view changes.

(Reference article: vue-elemnt-admin documentation)

1. Refresh the entire routing page

Use $nextTick and v-if to refresh the current route after clicking

Configure the corresponding configuration in the app.vue file, configure v-if and refresh method

<template>
  <div id="app">
    <router-view v-if="isRouterAlive" />
  </div>
</template>

<script>
export default {<!-- -->
  name: 'App',
  provide() {<!-- -->
    return {<!-- -->
      reload: this.reload
    };
  },
  data() {<!-- -->
    return {<!-- -->
      isRouterAlive: true
    };
  },
  methods: {<!-- -->
    reload() {<!-- -->
      console.log('Trigger reload function')
      this.isRouterAlive = false;
      this.$nextTick(function () {<!-- -->
        this.isRouterAlive = true;
      });
    }
  }
}
</script>

Then in the src/layout/components/sidebar/index.vue folder, we first receive the function, then check whether there is a change according to the routing address, and call the reload refresh function if there is a change.

<template>
  <div :class="{ 'has-logo': showLogo }">
    <logo v-if="showLogo" :collapse="isCollapse" />
    <el-scrollbar wrap-class="scrollbar-wrapper">
      <el-menu :default-active="activeMenu" :collapse="isCollapse" :background-color="variables.menuBg"
        :text-color="variables.menuText" :unique-opened="false" :active-text-color="variables.menuActiveText"
        :collapse-transition="false" mode="vertical" @select="handleSelect">
        <sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
      </el-menu>
    </el-scrollbar>
  </div>
</template>

<script>
import {<!-- --> mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'

export default {<!-- -->
  inject: ['reload'],
  components: {<!-- --> SidebarItem, Logo },
  computed: {<!-- -->
    ...mapGetters([
      'sidebar'
    ]),
    routes() {<!-- -->
      return this.$router.options.routes
    },
    activeMenu() {<!-- -->
      const route = this. $route
      const {<!-- --> meta, path } = route
      // if set path, the sidebar will highlight the path you set
      if (meta. activeMenu) {<!-- -->
        return meta. activeMenu
      }
      return path
    },
    showLogo() {<!-- -->
      return this.$store.state.settings.sidebarLogo
    },
    variables() {<!-- -->
      return variables
    },
    isCollapse() {<!-- -->
      return !this.sidebar.opened
    }
  },
  methods: {<!-- -->
    handleSelect(index) {<!-- -->
      console. log(index)
      const route = this. $route
      const {<!-- --> path } = route
      if (index === path) {<!-- -->
        this. reload()
      }
    }
  }
}
</script>

2. Only refresh the nested routing page

The logic is roughly the same. You only need to change the reload and v-if judgments to the nested routing vue file.
The main file path of the nested route is src/layout/index.vue

<template>
  <div :class="classObj" class="app-wrapper">
    <div v-if="device === 'mobile' & amp; & amp; sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
    <sidebar class="sidebar-container" />
    <div class="main-container">
      <div :class="{ 'fixed-header': fixedHeader }">
        <navbar />
      </div>
      <app-main v-if="isRouterAlive" />
    </div>
  </div>
</template>

<script>
import {<!-- --> Navbar, Sidebar, AppMain } from './components'
import ResizeMixin from './mixin/ResizeHandler'

export default {<!-- -->
  name: 'Layout',
  components: {<!-- -->
    Navbar,
    Sidebar,
    AppMain
  },
  provide() {<!-- -->
    return {<!-- -->
      reloadMain: this.reloadMain
    };
  },
  data() {<!-- -->
    return {<!-- -->
      isRouterAlive: true
    };
  },
  mixins: [ResizeMixin],
  computed: {<!-- -->
    sidebar() {<!-- -->
      return this.$store.state.app.sidebar
    },
    device() {<!-- -->
      return this.$store.state.app.device
    },
    fixedHeader() {<!-- -->
      return this.$store.state.settings.fixedHeader
    },
    classObj() {<!-- -->
      return {<!-- -->
        hideSidebar: !this.sidebar.opened,
        openSidebar: this.sidebar.opened,
        withoutAnimation: this.sidebar.withoutAnimation,
        mobile: this.device === 'mobile'
      }
    }
  },
  methods: {<!-- -->
    handleClickOutside() {<!-- -->
      this.$store.dispatch('app/closeSideBar', {<!-- --> withoutAnimation: false })
    },
    reloadMain() {<!-- -->
      this.isRouterAlive = false;
      this.$nextTick(function () {<!-- -->
        this.isRouterAlive = true;
      });
    }
  }
}
</script>

<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";

.app-wrapper {<!-- -->
  @include clearfix;
  position: relative;
  height: 100%;
  width: 100%;

   &.mobile.openSidebar {<!-- -->
    position: fixed;
    top: 0;
  }
}

.drawer-bg {<!-- -->
  background: #000;
  opacity: 0.3;
  width: 100%;
  top: 0;
  height: 100%;
  position: absolute;
  z-index: 999;
}

.fixed-header {<!-- -->
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9;
  width: calc(100% - #{<!-- -->$sideBarWidth});
  transition: width 0.28s;
}

.hideSidebar .fixed-header {<!-- -->
  width: calc(100% - 54px)
}

.mobile.fixed-header {<!-- -->
  width: 100%;
}
</style>