Leancloud 快速搞定網站訪問量統計

蘆薈發表於2019-03-30

部落格現在用的評論是 Valine, 是一款基於 Leancloud 的快速、簡潔且高效的無後端評論系統。看配置什麼都挺簡單的,也有不少教程,本來沒想寫這個,但實際在訪問量統計這個功能上遇到不少問題(仍然是需要一定開發工作的),找到的教程都挺亂,乾脆自己重新梳理下了。

我的部落格 blog.liluhui.cn, 歡迎右上角 RSS 訂閱 ~

Before. 配置好 Valine

先參照 Valine官網教程 把應用配置好,不要遺漏安全域名,至此你的評論功能應該已經好了。

如果你不需要評論功能,或者不需要 Valine 來實現評論功能,可以跳過引用 Valine,但仍然需要建立好 Leancloud 的應用。

Start.訪問量統計

|前因

雖然 Valine 文件中說明從 v1.2.0 版本開始支援了文章閱讀量統計

new Valine({ el:'#vcomments', ... visitor: true // 閱讀量統計 })   如果開啟了閱讀量統計,Valine 會自動檢測 leancloud 應用中是否存在Counter類,如果不存在會自動建立,無需手動建立~   Valine會自動查詢頁面中class值為leancloud-visitors的元素,獲取其id為查詢條件。並將得到的值填充到其class的值為leancloud-visitors-count的子元素裡:

以上為官方說明,但配置並沒有軟用,因為查下原始碼可以看見,Valine 除了在 leancloud 中建立一個 Counter 類什麼都沒有幹 !...

Leancloud 快速搞定網站訪問量統計

 

這裡從一些其他資料看是具體邏輯是在 Hexo-theme-next 這個主題做了處理,也就是具體業務方做了儲存和獲取資料的邏輯,挺不合理的,還是應該 Valine 封裝好才對。

 

至此,我們只能自己動手做儲存和訪問的邏輯了。

|動手

思路:

  1. 約定 HTML 節點用於採集渲染統計量資料
  • 帶有 classleancloud_visitors_count 的表示需要渲染資料,節點屬性 data-index 表示唯一索引。我這個場景是 url 為唯一索引,舉例如
<span class="leancloud_visitors_count" data-index="/2019/03/12/ZRender使用記錄/"></span>
複製程式碼
  • 帶有 idleancloud_visitors 的表示採集資料,節點屬性data-index 表示唯一索引。舉例如
<span class="leancloud_visitors_count" data-index="/2019/03/12/計算字的寬高/"></span>
複製程式碼
  1. JS實現方法 addCount 用於上傳資料(指定索引訪問量+1)和 showTime 用於渲染訪問量資料

  2. 要渲染的所有索引批量查詢一次

  3. 減少請求,每個頁面採集只允許一次,所以採集資料約定的節點為 id 而不是 class

 

S1. Leancloud 建 Counter 類

Leancloud 快速搞定網站訪問量統計

S2. JS 程式碼實現

同 Hexo 的使用者,把這段程式碼單獨存檔案 _partials/lean-analytics.swig,在對應主題目錄下 ./layout/javascript.swing 中引用這份檔案即可

以下程式碼根據你的實際場景做些處理,你要儲存哪些欄位、你的 Leancloud 的 appId 和 appKey、你的節點約定規則等。

// 這段程式碼依賴 jquery,請檢查下是否有引用
// 具體的HTML節點約定你可以根據你的需要更改
<script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
<script>
function showTime(Counter) {
  var query = new AV.Query(Counter);
  var $doms = $(".leancloud_visitors_count")
  if (!$doms.length) return
  // var urls = $doms.map(function(){return $(this).attr('data-index')}) || [];
  var urls = []
  for (var i = 0; i < $doms.length; i++) {
    urls.push($($doms[i]).attr('data-index'))
  }
  query.containedIn("url", urls);
  query.find({
    success: function(rst) {
      // 初始化
      $doms.each(function(i) {
        $(this).text(0)
      })
      // 渲染資料
      for (var i in rst) {
        var item = rst[i]
        $('.leancloud_visitors_count[data-index="'+ item.get('url') +'"]').text(item.get('time'))
      }
    },
    error: function (obj, e) {
      console.warn(obj, e)
    }
  })
}
function addCount(Counter) {
  var Counter = AV.Object.extend("Counter");
  var $dom = $("#leancloud_visitors")
  if (!$dom.length) return
  url = $dom.attr('data-index').trim(); 
  var query = new AV.Query(Counter);
  query.equalTo("url", url); // 我的需求以儲存的url為唯一索引
  // Case 有這條資料則time欄位+1
  query.find({
    success: function(results) {
      if (results.length > 0) {
        var counter = results[0];
        counter.fetchWhenSave(true);
        counter.increment("time");
        counter.save(null, {
          success: function(counter) {
          },
          error: function(counter, e) {
            console.warn(counter, e)
          }
        });
      } 
      // Case 沒有這條資料則新增一行資料
      else { 
        var newcounter = new Counter();
        var acl = new AV.ACL();
        acl.setPublicReadAccess(true);
      // acl.setWriteAccess(AV.User.current(),true);
        acl.setWriteAccess('*', true);
        newcounter.setACL(acl)
        // 這裡是你想儲存的資料
        newcounter.set("title", title);
        newcounter.set("url", url); // 我的需求以儲存的url為唯一索引
        newcounter.set("time", 1);
        newcounter.save(null, {
          success: function(newcounter) {
          },
          error: function(newcounter, error) {
            console.log('Failed to create');
          }
        });
      }
    },
    error: function(e) {
      console.warn(e)
    }
  });
}
$(function() {
  // @TODO 
  // appId 和 appKey 在 Leancloud 應用的設定內可以找到,
  // 具體可參考上面 Valine 的官方引導吧。
  AV.initialize(appId, appKey); 
  var Counter = AV.Object.extend("Counter");
  addCount(Counter);
  showTime(Counter);
});
</script>

複製程式碼

S3. HTML 節點新增

這是我在文章列表的訪問量渲染節點

<span class="reading-time">
    <span class="leancloud_visitors_count" data-index="{{ url_for(post.path) }}"></span>
    read
</span>
複製程式碼

這是我在每個文章頁面的採集節點

<div id="leancloud_visitors" data-index="{{ url_for(page.path) }}" data-title="{{ page.title }}"></div>
複製程式碼

問題集

ACL 許可權問題

出現報錯 ACL 許可權問題,是因為建立 Counter 類的時候選擇了限制寫入作為ACL的預設設定。

Leancloud 快速搞定網站訪問量統計

參考 ACL 許可權管理開發指南],可以通過建立資料行時宣告 ACL 許可權解決

  // 新建一個帖子物件
  var Post = AV.Object.extend('Post');
  var post = new Post();
  post.set('title', '大家好,我是新人');

  // 新建一個 ACL 例項
  var acl = new AV.ACL();
  acl.setPublicReadAccess(true);
  acl.setWriteAccess(AV.User.current(),true);

  // 將 ACL 例項賦予 Post 物件
  post.setACL(acl);
  post.save().then(function() {
    // 儲存成功
  }).catch(function(error) {
    console.log(error);
  });
複製程式碼

臨時處理上,可以在後臺直接編輯修改

Leancloud 快速搞定網站訪問量統計

相關文章