NUXT项目要点记录

因为公司的项目要考虑SEO,因此采用了NUXT来作服务端渲染。先后写了三个NUXT项目,遇到很多坑,这里记录一下填坑的过程和心得。vue

1.浏览器返回后,回到历史浏览位置(缓存页面数据)

现象:chrome

在写NUXT项目的时候,发现返回以后没法回到历史浏览位置,可是页面会留在一个特定的位置。检查后发现,页面中用了无限滚动,无限滚动后加载的内容在返回以后就消失了。浏览器

缘由:缓存

asyncData等钩子函数在返回以后依然会触发,致使页面的数据在返回后从新加载了,因此以前无限滚动加载的数据都被重置了bash

解决方案:app

先说基本思路:浏览过的页面保持活跃不被销毁,这样返回时组件的状态都还保持着离开时的样子,而且mounted等钩子函数不会再次触发,但asyncData函数没法被禁止,因此咱们须要判断当前的执行环境,只有当执行环境是服务端时(也就是用户进入网站浏览的第一个页面)咱们使用asyncData初始化数据,在客户端环境时(浏览器环境)咱们使用mounted钩子来初始化数据,因此咱们除了须要判断当前执行环境外,还要判断当前是不是第一个页面(第一个页面时mounted的初始化代码不触发,放在asyncData中触发);接下来上代码async

首先使用keep-alive保持组件不被销毁,并使浏览器返回后,mounted等钩子函数再也不触发函数

使用了keep-alive后,组件会添加activated和deactivated钩子,而且只有这两个钩子会在进入和离开页面时触发,mounted等钩子都不会再触发

<nuxt keep-alive />复制代码

而后在asyncData中判断当前执行环境,若是是服务端环境则触发初始化代码,不然不触发post

async asyncData({app,store:{state}}){    
if(process.client) return;
    // 初始化代码    .......
}复制代码

客户端环境下,使用mounted来获取服务端数据初始化页面,这里须要一个字段来判断mounted是否须要执行初始化代码,在VUEX中添加is_serve_page属性。使用一个公共函数在mounted中执行,该函数判断初始化代码是否执行网站

// 客户端初始化页面数据  
inject("clientInitPage", (callback, data) => {    
  if (state.is_serve_page) {      
    commit("setServePage", false);    
  } else {      
    callback && (data ? callback(data) : callback());    
  }  
});复制代码

在页面组件的mounted中执行clientInitPage

mounted(){    
  this.$clientInitPage(this.initPage);  
}复制代码

这样问题就解决了。

2.特殊的URL结构处理

为了更加友好的SEO,URL的目录结构和长度越短越好,个人项目中采用的详情页URL为”/post-123“和"/u-111",一个是帖子详情页,一个是用户详情页。这种的URL须要一个动态路由来处理。

  1. 在pages目录下,新建"_path.vue"文件。
  2. 在_path.vue中,根据URL的前缀来判断当前是什么页面,并获取相应的数据。
这里遇到一个坑,详情页之间切换的时候,页面会先显示第一个加载的详情页的数据,而后才会变成新的数据。缘由是客户端执行的时候,会加载组件的mounted,在mounted数据加载出来以前,_path.vue中的数据会被当成props传过去,因此在客户端环境下,要重置_path.vue中的数据

// 根据url信息来选择显示相应的组件
<div class="path-page">    
 <uIndex v-if="page_name=='u'" :page_data="page_data" />    
 <postIndex v-else-if="page_name=='post'" :page_data="page_data" />  
</div>
// 获取URL上的页面信息,并加载相应的数据
async asyncData({ app, store: { state }, params }) {    
  const PAGENAME = params.path.split("-")[0];    
  const PAGEID = params.path.split("-")[1];
  //  客户端环境重置page_data和page_name    
  if (process.client) {      
    return {        
      page_data: null,        
      page_name: PAGENAME      
    };    
  }    
  let page_data = await getPageData(PAGENAME, PAGEID, app);    
  return {      
    page_data: page_data,      
    page_name: PAGENAME    
  };
}
// 获取页面数据
async function getPageData(PAGENAME, PAGEID, app) {  
switch (PAGENAME) {    
  //  用户中心    
  case "u": {      
    return await getUPage(app, PAGEID);      
    break;    
  }    
  //  帖子详情    
  case "post": {      
    return await getPostPage(app, PAGEID);      
    break;    
  }    
  default:      
  break;  
 }
}
复制代码

到这里,_path.vue就处理完毕了。服务端环境下页面的初始化放在_path.vue中获取,在客户端环境下,只须要在各自的组件mounted中获取就好了。

3. 添加谷歌百度等统计代码

作SEO确定少不了添加各个搜索引擎的统计代码,统计代码只须要在生产环境中执行,因此这里把统计代码封装成函数,在页面初始化的时候加载。

1. 谷歌统计

在plugins中新建ga.js文件

export default ({ app: { router } }, inject) => {  
 // 谷歌统计分析  
 inject("googleAnalytics", _ => {    
 /*     ** 只在生产模式的客户端中使用     */    
 if (process.client && process.env.NODE_ENV === "production") {      
 /*       ** Google 统计分析脚本       */      
 (function(i, s, o, g, r, a, m) {        
  i["GoogleAnalyticsObject"] = r;        
  (i[r] =          
    i[r] ||          
    function() {            
    (i[r].q = i[r].q || []).push(arguments);          
  }),          
  (i[r].l = 1 * new Date());        
  (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);        
  a.async = 1;        
  a.src = g;        
  m.parentNode.insertBefore(a, m);      
  })(        
    window,        
    document,        
    "script",        
    "https://www.google-analytics.com/analytics.js",        
    "ga"      
  );      
  /*      
  ** 当前页的访问统计这里写上本身网站的UA编码       
  */
      ga("create", "UA-*****-*", "auto");
      /*
       ** 每次路由变动时进行pv统计
       */
      router.afterEach((to, from) => {
        /*
         ** 告诉 GA 增长一个 PV
         */
        ga("set", "page", to.fullPath);
        ga("send", "pageview");
      });
    }
  });};复制代码

2.百度统计

同样在plugins中新建bg.js

export default ({ app: { router } }, inject) => {
  // 百度分析
  inject("baiduAnalytics", _ => {
    /*
     ** 只在生产模式的客户端中使用
     */
    if (process.client && process.env.NODE_ENV === "production") {
      /*
       ** baidu 统计分析脚本
       */
      var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?**********";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
      })();
      /*
       ** 每次路由变动时进行pv统计
       */
      router.afterEach((to, from) => {
        /* 告诉百度增长一个PV */
        try {
          window._hmt = window._hmt || [];
          window._hmt.push(["_trackPageview", to.fullPath]);
        } catch (e) {}
      });
    }
  });};复制代码

而后在plugins中建立init.js文件,用做网站初始化的文件

export default ({ app }) => {
   // 加载谷歌分析代码
    app.$googleAnalytics();
    // 加载百度分析代码
    app.$baiduAnalytics();};
}复制代码

最后在nuxt.config.js中引入js文件

plugins: [
    { src: '~plugins/ga.js', ssr: false },
    { src: '~plugins/bd.js', ssr: false },
    { src: "~/plugins/init.js", ssr: false }
  ],复制代码

统计的代码就算是加上了,在chrome的NETWORK中能够看到没次切换页面都会触发百度和谷歌的统计

总结

随手记录下,其实在开发中遇到过很多问题,不少都记不清了。持续更新吧,想起来的时候继续补上。

相关文章
相关标签/搜索