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. 前端开发中一些实用的工具类网站

    从零到一已经有不少人写过啦,但我仍是列到了列表里,若是不幸胜出了,我就尽力写的不一样一些吧。

相关文章
相关标签/搜索