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

2018-08-01  本文已影响402人  SeasonDe

本文基于工作项目开发,做的整理笔记
前几天帮朋友解决这个问题,顺带学习了一下,做个笔记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。有待验证。

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


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

上一篇下一篇

猜你喜欢

热点阅读