Vue-SSR: head Mixin 實現頭部信息管理

上週發了我第一篇技術博客,傳送門1:JS中的數組過濾,從簡單篩選到多條件篩選,感謝你們的支持,尤爲是提出疑問,發現錯誤的同窗,感謝大家。發完博客之後,我用 hexo 搭了一個 github pages, 綁定了我以前買的域名,傳送門2: blog.yidol.cn/,之後個人博客會在GitHub發一遍,而後掘金抄送一遍。javascript

近兩個月都在忙着搭建 vue-ssr 的項目,由於公司產品是媒體類,SEO 很重要,第一週是嘗試用 nuxt 搭建了一個項目,nuxt 確實是開箱即用,比較爽,就是配置的時候可能要看看 nuxt 的文檔,還要看看 webpack 的文檔,不少人使用 vue-cli3 產生了一樣的感覺。因爲公司給的時間也夠,我決定參考尤雨溪的官方例子🌰 傳送門3: vue-hacknews-2.0 搭建了我司的新 PC 端項目,整個項目是用 webpack4+vue2+vue-ssr 從 0 到 1,踩過一些坑,多謝網上各個平臺的同窗們貢獻的文章,我打算陸續寫文章分享項目搭建的過程,但願也可以幫助到你們。html

  下面進入這篇文章的主題,尤大大的例子裏是作了一個 tilte 的 Mixin 方法,能夠修改各個頁面的 title,可是我司的需求多是不一樣的頁面不只是要不一樣的 title,還要不一樣的 description,author,keywords,網上有不少人使用 vue-meta, 感興趣的小夥伴能夠搜索一下用法,今天我想討論的是改造尤大大項目裏的 title mixin 爲 head mixin,知足我司需求。前端

尤大大的title mixin

  打開 vue-hacknews 項目 src/util/title.js ,能夠看到如下代碼或者 傳送門4: vue SSR 指南 Head 管理vue

// 獲取模版裏的 title
function getTitle (vm) { 
  const { title } = vm.$options
  if (title) {
    return typeof title === 'function'
      ? title.call(vm)
      : title
  }
}

// 若是有 title 了就加載新的 title,沒有就還有默認的頂着,默認的 title 在哪裏,稍後告訴你
// 下面倆一個是服務器端渲染時調用,一個是客戶端渲染是調用,爲啥倆不同,可查看文末知識點

const serverTitleMixin = { 
  created () {
    const title = getTitle(this)
    if (title) {
      this.$ssrContext.title = `Vue HN 2.0 | ${title}`
    }
  }
}

const clientTitleMixin = { 
  mounted () {
    const title = getTitle(this)
    if (title) {
      document.title = `Vue HN 2.0 | ${title}`
    }
  }
}

export default process.env.VUE_ENV === 'server'
  ? serverTitleMixin
  : clientTitleMixin

複製代碼

  文件 src/app.js 在這裏全局引入 Mixinjava

...
import titleMixin from './util/title'
...
// mixin for handling title
Vue.mixin(titleMixin)
...
複製代碼

  這裏是默認 title 的地方src/server.jswebpack

...
//在render函數裏
  const context = {
    title: 'Vue HN 2.0', // default title
    url: req.url
  }
...
複製代碼

  具體組件裏的用法 src/views/UserView.vuegit

export default {
  name: 'user-view',
  ...
  title () {
    return this.user
      ? this.user.id
      : 'User not found'
  },
  ...
}
複製代碼

Head Mixin的改造過程

  首先是明確個人需求,如文章開頭所說,僅僅是 title 是不符合個人需求的,我還須要可以自定義 description,author,keywords。github

組件裏用法

  尤大大的 title 是返回一個字符串,我把我須要的塞到了一個對象裏,須要自定義的就 return 出去,不須要的就仍是默認的就行。web

export default {
  name: 'article-list',
  ...
  head(){
      return {
        'title': '文章列表',
        'author': '大俠'
      };
    },
  ...
}

複製代碼

默認的頭信息

  一樣在 server.jsvue-cli

// 一樣也在render 函數裏
  const context = {
    'title': '可愛王', // 默認title
    'author': 'Anne', // 默認author
    'keywords': '我是keywords', // 默認keywords
    'description': '我是description', //默認description 
    'url': req.url // 我是重要的一行代碼,可是我跟這篇文章不要緊
  };// 沒錯我很無聊,打了這麼多無聊的註釋
複製代碼

引入全局head mixin

  一樣在 src/main.js

import headMixin from './utils/head';
// head()
Vue.mixin(headMixin);
複製代碼

定義head Mixin

  在 src/utils/head.js 裏,在這裏是判斷了是否有 head,是否有各個我須要的東西,有就加載新的,沒有就仍是默認的。

function getHead (vm) {
  const { head } = vm.$options;

  if (head) {
    return typeof head === 'function' ?
      head.call(vm) :
      head;
  }
}

const serverHeadMixin = {
  created () {
    const head = getHead(this);

    if (head) {
      if (head.title) this.$ssrContext.title = `${head.title}-可愛王`;
      if (head.author) this.$ssrContext.author = `${head.author}-可愛王`;
      if (head.keywords) this.$ssrContext.keywords = head.keywords;
      if (head.description) this.$ssrContext.description = head.description;
    }
  }
};

const clientHeadMixin = {
  mounted () {
    const head = getHead(this);

    if (head) {
      if (head.title) document.title = `${head.title}-可愛王`;
      if (head.author) document.querySelector('meta[name="author"]').setAttribute('content', `${head.author}-可愛王`);
      if (head.keywords) document.querySelector('meta[name="keywords"]').setAttribute('content', head.keywords);
      if (head.description) document.querySelector('meta[name="description"]').setAttribute('content', head.description);
    }
  }
};

export default process.env.VUE_ENV === 'server' ?
  serverHeadMixin :
  clientHeadMixin;
複製代碼

知識點一:混入 (mixins)

  在作這個項目以前,我沒有用過這個東西,傳送門5: vue官方文檔對混入的介紹

混入 (mixins) 是一種分發 Vue 組件中可複用功能的很是靈活的方式。混入對象能夠包含任意組件選項。當組件使用混入對象時,全部混入對象的選項將被混入該組件自己的選項。

  簡而言之,就是你能夠自定義一個鉤子函數,在每個 Vue 實例裏引用,好比這篇文章裏提到的 head() , 帥呆了。

知識點二:服務器端渲染與客戶端渲染的生命週期不一樣

  在全部的生命週期鉤子函數裏,只有 beforeCreatecreated 會在服務器端渲染過程當中調用,官方文檔有提到這個,因此在開發過程當中要必定要注意這點。

完!

題外話:關於將來文章的規劃

  😁若是你還在看的話,幫忙留個言吧! 上週的文章在掘金獲得了一百多個贊,開心,特別感謝個人朋友 Dylan 同窗的糾錯以及掘金網友 Auroral 提醒遞歸優化的實例代碼與 deepclone 無關聯。前端從業兩年多,一直沒有輸出文章,上週突發奇想要整理出本身的博客,可以梳理本身的知識,分享出來也可以幫助到你們, 也但願本身可以堅持下去。想寫的太多,精力有限,我想列一些想寫的文章,一篇一篇的出,走過路過若是看到了這篇文章,能夠評論一下哪篇是你想看的,民意比較多的我就先寫啦。<( ̄︶ ̄)>

  1. vue 單頁應用的多 layout 實現

  2. 從零到一:用 webpack4 搭一個 vue 項目

  3. 從零到一:用 vue-cli3 搭一個項目

  4. 從零到一:用 nuxt 搭一個 vue-ssr 項目

  5. 從零到一:用 github 和 hexo 搭一個本身的線上博客

  6. Vue-ssr 系列 基於 vue-hacknhews 2.0 想到什麼寫什麼咯

  7. 前端開發中一些實用的工具類網站

    從零到一已經有不少人寫過啦,但我仍是列到了列表裏,若是不幸勝出了,我就盡力寫的不一樣一些吧。

相關文章
相關標籤/搜索