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中能夠看到沒次切換頁面都會觸發百度和谷歌的統計

總結

隨手記錄下,其實在開發中遇到過很多問題,不少都記不清了。持續更新吧,想起來的時候繼續補上。

相關文章
相關標籤/搜索