基于vue.js&vue-router的动态更新TDK(SEO优化)

本文基于工作项目开发,做的整理笔记
前几天帮朋友解决这个问题,顺带学习了一下,做个笔记Mark下。

前提条件:
你已经了解并使用vue,能够搭建应用站点。

编码环境:
system:OS X EI Capitan 10.13.3
npm:5.5.1
node:v8.9.3
vue-cli:@lastest

相关技术栈:
vue2 + vue-router

相关地址:
参考阅读:https://alligator.io/vuejs/vue-router-modify-head/

基于vue.js&vue-router的动态更新TDK.jpg

1.router部分

直接看代码,主要包含一个配置变量mapping,也可以抽出去放到单独的配置文件中,这里就简化放进来了,容易看。在路由配置中,给了一个meta字段用于存放对应的TDK信息。

注意:这里我们发现NewsDetail暂存的TDK信息和News一样,没关系,因为它和ID有关,在app.js那边我们还要具体处理。

/**********************************************/
/* src/router/index.js                                */
/**********************************************/
import Vue from 'vue'
import Router from 'vue-router'
import Layout from '@/components/layout'
import Home from '@/components/home'
import News from '@/components/hot-news'
import Detail from '@/components/hot-news/detail'
import About from '@/components/info/about'
import ContactUs from '@/components/info/contact-us'
import JoinUs from '@/components/info/join-us'
import Terms from '@/components/info/terms'
import Error404 from '@/components/404'

Vue.use(Router)
const mapping = {
  home: {
    title: 'xxxxxxxxxxxxxxxx-【官网名称】',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '官网页面的一段描述'
      },
    ],
  },
  news: {
    title: '【新闻热点】_xxxxxxx-官网名称',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '新闻热点页面的一段描述'
      },
    ],
  },
}

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      component: Layout,
      // redirect: '/home',
      hidden: true,
      children: [
        { 
          path: '',
          component: Home,
          meta: mapping.home,
        },
        {
          path: 'home',
          redirect: '/',
          component: Home,
          meta: mapping.home,
        },
        {
          path: 'news', 
          component: News, 
          meta: mapping.news,
        },
        {
          path: 'news/:id', 
          component: NewsDetail, 
          meta: mapping.news,
        },
        {
          path: 'about', 
          component: About, 
          meta: mapping.home,
        },
        {
          path: 'contact-us', 
          component: ContactUs, 
          meta: mapping.home,
        },
        {
          path: 'join-us', 
          component: JoinUs, 
          meta: mapping.home,
        },
        {
          path: 'terms', 
          component: Terms, 
          meta: mapping.home,
        },
        {
          path: '404', 
          component: Error404, 
          meta: mapping.home,
        },
      ]
    },
  ]
})

2. 看看app.js这边如何使用

这段代码中,也有一个配置变量mappingFull,它主要服务于那种带查询条件的,带id的具体路由的TDK。另外注意的就是方法

/**********************************************/
/* src/app.js                                             */
/**********************************************/

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import store from './store';
import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@/style/base.scss'

Vue.use(ElementUI);
Vue.config.productionTip = false

const mappingFull = {
   '/news?categary=xxxxx': {
    title: '【新闻热点】_xxxxx-官网名称',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '这一搜索条件的相关描述'
      },
    ],
  },
   '/news/1': {
    title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '新闻热点1的相关描述'
      },
    ],
  },
   '/news/2': {
    title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '新闻热点2的相关描述'
      },
    ],
  },
  '/hot-news/3': {
    title: '【xxxxx_新闻热点】_xxxxxx-官网名称',
    metaTags: [
      {
        name: 'keywords',
        content: 'xxx, xx, xxxx, xxx, xxx'
      },
      {
        name: 'description',
        content: '新闻热点3的相关描述'
      },
    ],
  },
}

router.beforeEach((to, from, next) => {
  const matchPath = to.matched.slice().reverse();
  const meta = mappingFull[to.fullPath];
  // console.log(to.fullPath);   // 可以打印输出看看
  // console.log(meta);
  let nearestWithTitle = undefined;
  let nearestWithMeta = undefined;
  if (meta) {
    nearestWithTitle = { meta };
    nearestWithMeta = { meta };
  } else {
    nearestWithTitle = matchPath.find(r => r.meta && r.meta.title);
    nearestWithMeta = matchPath.find(r => r.meta && r.meta.metaTags);
  }

  if(nearestWithTitle) document.title = nearestWithTitle.meta.title;
  Array.from(document.querySelectorAll('[data-vue-router-controlled]')).map(el => el.parentNode.removeChild(el));
  if(!nearestWithMeta) return next();
  nearestWithMeta.meta.metaTags.map(tagDef => {
    const tag = document.createElement('meta');
    Object.keys(tagDef).forEach(key => {
      tag.setAttribute(key, tagDef[key]);
    });
    tag.setAttribute('data-vue-router-controlled', '');
    return tag;
  })
  .forEach(tag => document.head.appendChild(tag));

  if (to.need && to.need.requireAuth) {
    if (store.getters.token) { 
      next();
    }
    else {
      next('/home');
      // next({
      //   path: '/login',
      //   query: {redirect: to.fullPath}  // 将跳转的路由path作为参数,登录成功后跳转到该路由
      // });
    }
  }
  else {
    next();
  }
});

router.afterEach((to,from,next) => {
    window.scrollTo(0,0);
})

new Vue({
  store,
  router,
  render: h => h(App)
}).$mount('#app');

3. 疑问

我们大多都知道SEO优化有很多方式,更可行的可能是SSR后端渲染,但是毕竟有时候我们就是前端渲染实现某个官网,只能找找其他简单可行办法。文中这种做法实际上只有真是访问的时候才可以拿到真正准确的TDK,各搜索引擎的爬虫拿到的是静态文件index.html的代码view-source,那个时候TDK还没有被替换,不知道这种做法是否真的有利于SEO。有待验证。

欢迎留言提出此类问题的优化,互相学习。


学习是一条漫漫长路,每天不求一大步,进步一点点就是好的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容