美文网首页
基于vue.js&vue-router的动态更新TDK(

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

作者: SeasonDe | 来源:发表于2018-08-01 21:59 被阅读402次

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

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


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

    相关文章

      网友评论

          本文标题:基于vue.js&vue-router的动态更新TDK(

          本文链接:https://www.haomeiwen.com/subject/ffcdvftx.html