Vue 折騰記 - (12) Nuxt.js寫一個校驗訪問瀏覽器裝置型別及環境的中介軟體

CRPER發表於2018-08-24

前言

這個需求非常常見,分享出去的頁面的有時候在手機訪問,有時候別人是PC開啟的;

若是不是共享同一個頁面的情況,就需要攔截跳轉了;

當然你要共享同一個頁面也可以(放大化到PC也需要新增某些CSS,也需判斷裝置)


思路

本質上還是校驗UA, 只是這次是從req拿到,而不是從客戶端獲取再做處理

客戶端的處理的姿勢

  • 拿到window.navigator.userAgent
  • 寫一個判斷的JS,匹配,返回對應的型別
  • 拿到型別之後我們再考慮是否去跳轉,或者做一些行為處理

服務端的處理姿勢

其實基本和上面的思路一樣的,只是我們能做處理的時間提前了

不用等到客戶端頁面渲染完畢後,再去判斷,再做處理

使用者的體驗上會好很多

理清了邏輯我們就可以開始寫了


談談Nuxt生命週期

Nuxt.js就是一個Vue的服務端渲染框架,和React的服務端渲染框架Next.js類似,

我們這裡使用的版本是v1.4.2(預設初始化版本是基於Express的),

讓我們看官方給出的Nuxt執行生命週期流程

Vue 折騰記 - (12) Nuxt.js寫一個校驗訪問瀏覽器裝置型別及環境的中介軟體

render(渲染)之前有幾個階段,通用全域性配置均在middleware(中介軟體)階段

那為什麼不在nuxtServerInit去做一些處理,因為這裡只能觸發storeaction


程式碼實現

這裡已經假設你已經大體看完官方文件,對於目錄結構什麼都瞭解為前提!

deviceType.js(utils目錄)

// 這裡的判斷型別是自己整理的,覆蓋面只涵蓋我工作領域的
// 可以按需追加

/**
 *
 * @param {*} UA ,就是userAgent
 * @returns  type: 裝置型別
 *           env: 訪問環境(微信/微博/qq)
 *           masklayer: 就是給外部拿到判斷是否顯示遮罩層的,一些特殊環境要引導使用者到外部去開啟訪問
 */

function isWechat(UA) {
  return /MicroMessenger/i.test(UA) ? true : false;
}

function isWeibo(UA) {
  return /Weibo/i.test(UA) ? true : false;
}

function isQQ(UA) {
  return /QQ/i.test(UA) ? true : false;
}

function isMoible(UA) {
  return /(Android|webOS|iPhone|iPod|tablet|BlackBerry|Mobile)/i.test(UA)
    ? true
    : false;
}

function isIOS(UA) {
  return /iPhone|iPad|iPod/i.test(UA) ? true : false;
}

function isAndroid(UA) {
  return /Android/i.test(UA) ? true : false;
}

export function deviceType(UA) {
  if (isMoible(UA)) {
    if (isIOS(UA)) {
      if (isWechat(UA)) {
        return {
          type: "ios",
          env: "wechat",
          masklayer: true,
        };
      }
      if (isWeibo(UA)) {
        return {
          type: "ios",
          env: "weibo",
          masklayer: true,
        };
      }
      if (isQQ(UA)) {
        return {
          type: "ios",
          env: "qq",
          masklayer: true,
        };
      }
      return {
        type: "ios",
      };
    }
    if (isAndroid(UA)) {
      if (isWechat(UA)) {
        return {
          type: "android",
          env: "wechat",
          masklayer: true,
        };
      }
      if (isWeibo(UA)) {
        return {
          type: "android",
          env: "weibo",
          masklayer: true,
        };
      }
      if (isQQ(UA)) {
        return {
          type: "android",
          env: "qq",
          masklayer: true,
        };
      }
      return {
        type: "android",
      };
    }

    return {
      type: "mobile",
    };
  } else {
    return {
      type: "pc",
    };
  }
}




複製程式碼

device.js(middleware目錄)

// @ts-nocheck
import { deviceType } from "~/utils/deviceType";
export default function(context) {
  // @ts-ignore
  context.userAgent = process.server
    ? context.req.headers["user-agent"]
    : navigator.userAgent;
  // 給全域性上下文新增一個屬性來儲存我們返回的匹配資訊
  context.deviceType = deviceType(context.userAgent);
  // 這裡注入到store,是因為我部分頁面需要判斷機型請求不同的資料,
  // 你們沒有用到的話可以移除
  context.store.commit("SetDeviceType", context.deviceType);

  // 若是判斷UA非移動端的,就在這裡做處理了..
  // context.redirect(status,url) 這個可以重定向到外部網站
  // 若是內部訪問可以直接用router物件push
  if (context.deviceType.type === "pc") {
    // context.redirect(301,'https://wwww.baidu.com')
  }
}

複製程式碼

nuxt.config.js

這種功能是面向全站的,所以要注入到全域性,所以頁面都預設執行

往router注入中介軟體即可全域性生效


module.exports = {
  router: {
    middleware: ["device"],
  },
};

複製程式碼

總結

至此,常規的開發已經基本滿足

有不對之處亦或者更好的實現請留言,會及時修正,謝謝閱讀

相關文章