Layout.vue 3.0 KB
Newer Older
E
Evan You 已提交
1
<template>
E
Evan You 已提交
2
  <div class="theme-container"
E
Evan You 已提交
3 4 5 6
    :class="{
      'sidebar-open': isSidebarOpen,
      'no-sidebar': $page.frontmatter.home || $page.frontmatter.sidebar === false
    }"
E
Evan You 已提交
7 8 9 10
    @touchstart="onTouchStart"
    @touchend="onTouchEnd">
    <Navbar @toggle-sidebar="toggleSidebar"/>
    <Sidebar @toggle-sidebar="toggleSidebar"/>
E
Evan You 已提交
11 12 13 14 15
    <div class="custom-layout" v-if="$page.frontmatter.layout">
      <component :is="$page.frontmatter.layout"/>
    </div>
    <Home v-else-if="$page.frontmatter.home"/>
    <Page v-else/>
E
Evan You 已提交
16 17 18 19
  </div>
</template>

<script>
20
import Vue from 'vue'
E
Evan You 已提交
21
import nprogress from 'nprogress'
E
Evan You 已提交
22
import Home from './Home.vue'
E
Evan You 已提交
23
import Navbar from './Navbar.vue'
E
Evan You 已提交
24
import Page from './Page.vue'
E
Evan You 已提交
25
import Sidebar from './Sidebar.vue'
E
Evan You 已提交
26
import { pathToComponentName, getTitle, getLang } from '../app/util'
E
Evan You 已提交
27

E
Evan You 已提交
28
export default {
E
Evan You 已提交
29
  components: { Home, Page, Sidebar, Navbar },
E
Evan You 已提交
30 31 32 33 34
  data () {
    return {
      isSidebarOpen: false
    }
  },
E
Evan You 已提交
35 36 37 38 39 40 41 42

  created () {
    if (this.$ssrContext) {
      this.$ssrContext.title = getTitle(this.$page)
      this.$ssrContext.lang = getLang(this.$page)
    }
  },

E
Evan You 已提交
43
  mounted () {
E
Evan You 已提交
44 45 46 47 48 49 50 51 52 53 54
    // update title / meta tags
    this.currentMetaTags = []
    const updateMeta = () => {
      document.title = getTitle(this.$page)
      document.documentElement.lang = getLang(this.$page)
      this.currentMetaTags = updateMetaTags(this.$page, this.currentMetaTags)
    }
    this.$watch('$page', updateMeta)
    updateMeta()

    // configure progress bar
E
Evan You 已提交
55 56 57
    nprogress.configure({ showSpinner: false })

    this.$router.beforeEach((to, from, next) => {
58
      if (to.path !== from.path && !Vue.component(pathToComponentName(to.path))) {
E
Evan You 已提交
59 60
        nprogress.start()
      }
E
Evan You 已提交
61 62 63 64 65
      next()
    })

    this.$router.afterEach(() => {
      nprogress.done()
E
Evan You 已提交
66
      this.isSidebarOpen = false
E
Evan You 已提交
67
    })
E
Evan You 已提交
68
  },
E
Evan You 已提交
69 70 71 72 73

  beforeDestroy () {
    updateMetaTags(null, this.currentMetaTags)
  },

E
Evan You 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  methods: {
    toggleSidebar (to) {
      this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
    },
    // side swipe
    onTouchStart (e) {
      this.touchStart = {
        x: e.changedTouches[0].clientX,
        y: e.changedTouches[0].clientY
      }
    },
    onTouchEnd (e) {
      const dx = e.changedTouches[0].clientX - this.touchStart.x
      const dy = e.changedTouches[0].clientY - this.touchStart.y
      if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
        if (dx > 0 && this.touchStart.x <= 80) {
          this.toggleSidebar(true)
        } else {
          this.toggleSidebar(false)
        }
      }
    }
E
Evan You 已提交
96 97
  }
}
E
Evan You 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

function updateMetaTags (page, current) {
  if (current) {
    current.forEach(c => {
      document.head.removeChild(c)
    })
  }
  const data = page && page.frontmatter.meta
  if (data) {
    return data.map(m => {
      const tag = document.createElement('meta')
      Object.keys(m).forEach(key => {
        tag.setAttribute(key, m[key])
      })
      document.head.appendChild(tag)
      return tag
    })
  }
}
E
Evan You 已提交
117 118
</script>

E
Evan You 已提交
119
<style src="prismjs/themes/prism-tomorrow.css"></style>
E
Evan You 已提交
120
<style src="./styles/theme.stylus" lang="stylus"></style>