From abfc5e8bd0a1d5b86749562e07cc6e7082135d4f Mon Sep 17 00:00:00 2001 From: Xinyu Liu Date: Tue, 1 May 2018 19:02:25 +0800 Subject: [PATCH] refactor: extract the functions from layout to mixins --- lib/default-theme/Layout.vue | 110 +++------------------ lib/default-theme/mixins/index.js | 9 ++ lib/default-theme/mixins/nprogress.js | 20 ++++ lib/default-theme/mixins/scrollListener.js | 43 ++++++++ lib/default-theme/mixins/updateHead.js | 48 +++++++++ 5 files changed, 132 insertions(+), 98 deletions(-) create mode 100644 lib/default-theme/mixins/index.js create mode 100644 lib/default-theme/mixins/nprogress.js create mode 100644 lib/default-theme/mixins/scrollListener.js create mode 100644 lib/default-theme/mixins/updateHead.js diff --git a/lib/default-theme/Layout.vue b/lib/default-theme/Layout.vue index df988d69d7..6f19d394ec 100644 --- a/lib/default-theme/Layout.vue +++ b/lib/default-theme/Layout.vue @@ -21,19 +21,25 @@ diff --git a/lib/default-theme/mixins/index.js b/lib/default-theme/mixins/index.js new file mode 100644 index 0000000000..0a9c460e86 --- /dev/null +++ b/lib/default-theme/mixins/index.js @@ -0,0 +1,9 @@ +import nprogressMixin from './nprogress' +import scrollListenerMixin from './scrollListener' +import updateHeadMixin from './updateHead' + +export { + nprogressMixin, + scrollListenerMixin, + updateHeadMixin +} diff --git a/lib/default-theme/mixins/nprogress.js b/lib/default-theme/mixins/nprogress.js new file mode 100644 index 0000000000..7736bac922 --- /dev/null +++ b/lib/default-theme/mixins/nprogress.js @@ -0,0 +1,20 @@ +import Vue from 'vue' +import nprogress from 'nprogress' +import { pathToComponentName } from '@app/util' + +export default { + mounted () { + nprogress.configure({ showSpinner: false }) + + this.$router.beforeEach((to, from, next) => { + if (to.path !== from.path && !Vue.component(pathToComponentName(to.path))) { + nprogress.start() + } + next() + }) + + this.$router.afterEach(() => { + nprogress.done() + }) + } +} diff --git a/lib/default-theme/mixins/scrollListener.js b/lib/default-theme/mixins/scrollListener.js new file mode 100644 index 0000000000..b1e0b8fe28 --- /dev/null +++ b/lib/default-theme/mixins/scrollListener.js @@ -0,0 +1,43 @@ +import throttle from 'lodash.throttle' +import store from '@app/store' + +export default { + mounted () { + window.addEventListener('scroll', this.onScroll) + }, + beforeDestroy () { + window.removeEventListener('scroll', this.onScroll) + }, + methods: { + onScroll: throttle(function () { + this.setActiveHash() + }, 300), + setActiveHash () { + const sidebarLinks = [].slice.call(document.querySelectorAll('.sidebar-link')) + const anchors = [].slice.call(document.querySelectorAll('.header-anchor')) + .filter(anchor => sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash)) + + const scrollTop = Math.max(window.pageYOffset, document.documentElement.scrollTop, document.body.scrollTop) + + for (let i = 0; i < anchors.length; i++) { + const anchor = anchors[i] + const nextAnchor = anchors[i + 1] + + const isActive = i === 0 && scrollTop === 0 || + (scrollTop >= anchor.parentElement.offsetTop + 10 && + (!nextAnchor || scrollTop < nextAnchor.parentElement.offsetTop - 10)) + + if (isActive && this.$route.hash !== anchor.hash) { + store.disableScrollBehavior = true + this.$router.replace(anchor.hash, () => { + // execute after scrollBehavior handler. + this.$nextTick(() => { + store.disableScrollBehavior = false + }) + }) + return + } + } + } + } +} diff --git a/lib/default-theme/mixins/updateHead.js b/lib/default-theme/mixins/updateHead.js new file mode 100644 index 0000000000..179563ec9a --- /dev/null +++ b/lib/default-theme/mixins/updateHead.js @@ -0,0 +1,48 @@ +export default { + created () { + if (this.$ssrContext) { + this.$ssrContext.title = this.$title + this.$ssrContext.lang = this.$lang + this.$ssrContext.description = this.$page.description || this.$description + } + }, + mounted () { + // update title / meta tags + this.currentMetaTags = [] + const updateMeta = () => { + document.title = this.$title + document.documentElement.lang = this.$lang + const meta = [ + { + name: 'description', + content: this.$description + }, + ...(this.$page.frontmatter.meta || []) + ] + this.currentMetaTags = updateMetaTags(meta, this.currentMetaTags) + } + this.$watch('$page', updateMeta) + updateMeta() + }, + beforeDestroy () { + updateMetaTags(null, this.currentMetaTags) + } +} + +function updateMetaTags (meta, current) { + if (current) { + current.forEach(c => { + document.head.removeChild(c) + }) + } + if (meta) { + return meta.map(m => { + const tag = document.createElement('meta') + Object.keys(m).forEach(key => { + tag.setAttribute(key, m[key]) + }) + document.head.appendChild(tag) + return tag + }) + } +}