Skip to content

Web APIs

紀錄少見但很有用的原生 Web API

頁面能見度 document.visibilityState

判斷目前網頁的能見度,當頁面 可見不可見 時,做出相對應的事件。常見在頁面「不可見」時停止播放媒體,而「可見」後繼續播放,或其它應用方式。

  • 監聽頁面能見度
    js
    document.addEventListener('visibilitychange', () => {
      // 當頁面能見度變化時
    })
    
  • 判斷當前能見度
    js
    const visible = document.visibilityState
    console.log(visible)
    
    • 可見 visible
    • 不可見 hidden
      • 最小化視窗
      • 切換桌面
      • 切換頁籤
Demo

html

html
<video id="video" controls>
  <source
    src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/VolkswagenGTIReview.mp4"
    type="video/mp4"
  />
</video>

script

js
const videoEl = document.querySelector('video')

document.addEventListener('visibilitychange', () => {
  const documentVisible = document.visibilityState

  if (documentVisible === 'hidden') {
    JQ
    console.log(`目前不可見 (${new Date()})`)
    videoEl.pause()
  } else if (documentVisible === 'visible') {
    console.log(`目前可見 (${new Date()})`)
    videoEl.play()
  }
})

分享功能 navigator.share

Web Share API 的 navigator.share() 是一個 promise 方法,可以調用來分享網頁、連結、數據...。

👇 試試看

手機端取消分享信息:

Demo

html

html
<button
  id="share-button"
  style="border: 1px solid lightblue; padding: .1rem 1rem; border-radius: 4px; display: flex; align-items: center; "
>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="16"
    height="16"
    fill="currentColor"
    class="bi bi-share"
    viewBox="0 0 16 16"
  >
    <path
      d="M13.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5zm-8.5 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm11 5.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"
    />
  </svg>
  <span style="margin-left: .4rem; ">分享頁面</span>
</button>

javascript

js
<script>
  export default {
    data: () => ({
      shareData: {},
      result: ''
    }),

    mounted() {
      document.querySelector('#share-button').addEventListener('click', () => this.sharePage(this.shareData))
      this.shareData =  {
        title: 'docs99 Web Share API 分享功能',
        url: location.href,
        text: '這是來自 docs99 的 navigator.share 功能的分享內文。'
      }
    },

    methods: {
      async sharePage(shareData) {
        try {
          await navigator.share(shareData)
        } catch(errors) {
          if(errors.message === 'Abort due to cancellation of share.') {
            this.result = errors
            return false
          }
          alert(errors)
        }
      }
    }
  }
</script>

使用限制

  • 操作 url 必須為 https
  • 必須是使用 UI 互動 (比如: 點擊) 來執行事件,不可以直接調用!
  • 目前還是有 瀏覽器支援度 問題
    • 目前手機端 (chrome / edge / safari) 都是沒有問題
    • web chrome 會發生問題

特別注意

在手機端操作 navigator.share 若「取消分享」,會進到 catch,這是要特別處理,不然會跟不能操作的錯誤一樣走 catch 方法。

若「取消分享」 errors.messageAbort due to cancellation of share.,可以使用這個來判斷。

Demo
js
async sharePage(shareData) {
  try {
    await navigator.share(shareData)
  } catch(errors) {
    if(errors.message === 'Abort due to cancellation of share.') {
      this.result = errors
      return false
    }
    alert(errors)
  }
}

注意

這個方法必須是使用 UI 互動 (比如: 點擊) 來執行事件,不可以直接調用!

廣播頻道 BroadcastChannel

簡單說

BroadcastChannel 就是一個共用的頻道,只要有訂閱,大家都可以在上面「接收資料」與「傳送資料」。

圖片出處

同一個網域下,透過訂閱「相同」 的頻道,可以在不同的 視窗頁籤iframe 與頻道雙向互動 「接收頻道資料」、「傳送資料」到頻道上。想要一次跟多個頁面溝通,可以使用這個方法。

建立廣播實例

new BroadcastChannel 來建立一個實例,方法內寫入建立頻道的名稱 (字串);而這個實例就是與頻道互動的實體。

js
const channel = new BroadcastChannel('custom_channel_name')

廣播中發送信息

透過實例方法 channel.postMessage 可以在頻道上廣播信息。

js
const channel = new BroadcastChannel('custom_channel_name')
channel.postMessage('這是來自 page1 的廣播信息')

TIP

建立一樣的頻道名稱實例,就可以在相同頻道互動。

監聽廣播信息

頻道實例以 .onmessage 方法,寫入當頻道有傳送信息時執行的事件 (除了自已傳送之外)。

js
channel.onmessage = (e) => {
  // 當 channel 傳送資料時執行
  console.log(e.data)
}

注意

若有停止監聽頻道,需要再重新監聽頻道

關閉廣播監聽

頻道實例以 .close() 方法,可以終止與頻道的互動,無法收到頻道傳送的資料,也無法對頻道傳送資料。

js
channel.close()

注意

若執行 .close() 再對頻道傳資料,就會報錯!

Demo

code

html

html
<h1>Pae1</h1>
<button>來自 Page1 的廣播</button>
<p>廣播信息: <span id="result"></span></p>

Javascript

js
const channel = new BroadcastChannel('custom_channel_name')

const buttonEl = document
  .querySelector('button')
  .addEventListener('click', () => {
    channel.postMessage('這是來自 Page1 的廣播')
  })

channel.onmessage = (e) => {
  console.log(e.data)
  document.querySelector('#result').textContent = e.data
}
code

html

html
<h1>Page2</h1>
<button id="channel-post-message">傳送 Page2 廣播</button>
<button id="close-channel">停止廣播</button>
<button id="connect-channel">接通廣播</button>

<p>廣播信息: <span id="result"></span></p>

Javascript

js
let channel

const channelConnect = () => {
  channel = new BroadcastChannel('custom_channel_name')
  channel.onmessage = (e) => {
    document.querySelector('#result').textContent = e.data
    console.log(`由頻道收到的信息: ${e.data}`)
  }
}

channelConnect()

document
  .querySelector('#channel-post-message')
  .addEventListener('click', () => {
    channel.postMessage('這是來自 Page2 的廣播')
  })

document.querySelector('#close-channel').addEventListener('click', () => {
  console.log('停止監聽廣播')
  document.querySelector('#result').textContent = ''
  channel.close()
})

document.querySelector('#connect-channel').addEventListener('click', () => {
  channelConnect()
  console.log('開始監聽廣播')
})
code

html

html
<h1>Page3</h1>
<button>傳送 Page3 廣播</button>
<p>廣播信息: <span id="result"></span></p>

Javascript

js
const channel = new BroadcastChannel('custom_channel_name')
channel.onmessage = (e) => {
  document.querySelector('#result').textContent = e.data
  console.log(e.data)
}
const buttonEl = document
  .querySelector('button')
  .addEventListener('click', () => {
    channel.postMessage('這是來自 Page3 的廣播')
  })

原生加解密功能 crypto

之前經常使用 uuid 套件 來操作加解密功能,而原生的 Crypto API 已擁有這個功能且強大,可以不需要再依賴套件了。

使用 uuid 套件

js
const { v4: uuidv4 } = require('uuid')
uuidv4() // 5b493ee8-6b5c-4c34-a7d0-750dc1488ccf

原生 uuid v4 隨機產生

js
crypto.randomUUID() // '14197bf2-140f-454d-83b4-1efb984d911c'

Reference

Reference