<template>
  <div id="app">
    <keep-alive exclude="Detail">
      <!--路由出口,路由匹配到的组件将渲染在这里-->
      <router-view></router-view>
    </keep-alive>

    <!--主导航栏MainTabBar.vue组件,含有路由(由main.js挂载)-->
    <main-tab-bar></main-tab-bar>
  </div>
</template>

1. keep-alive

1.1 概念

<keep-alive></keep-alive>是Vue的一个内置组件,可以使被包含的组件在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
(ps: 组件间切换会不停的created与destoryed)

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。它只是一个抽象组件,它不会在DOM树中渲染(真实或者虚拟都不会),也不在父组件链中存在,比如:你永远在 this.$parent 中找不到 keep-alive 。

1.2 生命周期函数

被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子:
(在服务端渲染时,此钩子函数也不会被调用)
* activated 当 keep-alive 包含的组件再次渲染的时候触发
* deactivated 当 keep-alive 包含的组件销毁的时候触发

2. router-view

2.1 概念

<router-view>组件是一个 functional 组件,渲染路径匹配到的视图组件。
<router-view>渲染的组件还可以内嵌自己的<router-view>,根据嵌套路径,渲染嵌套组件。

3. 配合使用

router-view也是一个组件,如果直接被包在keep-alive里面,那么所有路径匹配到的视图组件都会被缓存,如下:

<keep-alive>
    <router-view>
        <!-- 所有路径匹配到的视图组件都会被缓存! -->
    </router-view>
</keep-alive>

4. 路由使用

4.1 建立router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

//引入组件页
const Home = () => import('views/home/Home')
const Category = () => import('views/category/Category')
const Cart = () => import('views/cart/Cart')
const Profile = () => import('views/profile/Profile')
const Detail = () => import('views/detail/Detail')

// 1.安装VueRouter
Vue.use(VueRouter)

// 2.配置路由信息
const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: '/home',
    component: Home
  },
  {
    path: '/category',
    component: Category
  },
  {
    path: '/cart',
    component: Cart
  },
  {
    path: '/profile',
    component: Profile
  },
  {
    path: '/detail',
    component: Detail
  }
]

// 3.创建路由对象
const router = new VueRouter({
  mode: 'history',
  routes
})

// 4.导出
export default router

4.2 主目录/main.js挂载

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import VueLazyLoad from 'vue-lazyload'

Vue.config.productionTip = false

Vue.use(VueLazyLoad, {
  preLoad: 1,
  loading: require('assets/img/common/placeholder.png')
})

new Vue({
  render: h => h(App),
  store,
  router //挂载路由
}).$mount('#app')

4.3 建立导航栏组件

4.3.1 直接使用router-link组件

4.3.2 或采用自定义属性结合方法

<tab-bar-item link="/home">
  <div slot="text">首页</div>
</tab-bar-item>

TabBarItem.vue组件

<template>
  <div id="tab-bar-item" @click="itemClick">
    <div class="item-icon" v-show="!isActive"><slot name="icon"></slot>
    </div>
    <div class="item-active-icon" v-show="isActive"><slot name="active-icon"></slot>
    </div>
    <div class="item-text" :style="activeStyle"><slot name="text"></slot>
    </div>
  </div>
</template>

<script>
    export default {
        name: "TabBarItem",
    props: {
            link: {
                type: String,
        required: true
      }
    },
    computed: {
            isActive() {
                return this.$route.path.indexOf(this.link) !== -1
      },
      activeStyle() {
                return this.isActive ? {'color': 'red'} : {}
      }
    },
    methods: {
            itemClick() {
        //MainTabBar.vue中使用link="/home"属性,这里使用方法将属性加到路由中再匹配路由
        //因此没有使用router-link
                this.$router.replace(this.link)
      }
    }
    }
</script>

<style scoped>
  #tab-bar-item {
    flex: 1;
  }

  .item-icon img, .item-active-icon img {
    width: 24px;
    height: 24px;
    margin-top: 5px;
    vertical-align: middle;
  }

  .item-text {
    font-size: 12px;
    margin-top: 3px;
    color: #333;
  }
</style>