欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

純JS實現(xiàn)監(jiān)控本地文件變化

 更新時間:2025年04月11日 11:05:44   作者:你不會困  
你是否曾夢想擁有一個能夠?qū)崟r監(jiān)控本地文件變化的網(wǎng)頁應(yīng)用,現(xiàn)在,這個夢想即將成為現(xiàn)實,本文將通過純JS實現(xiàn)這一功能,感興趣的小伙伴可以了解下

網(wǎng)頁端的超級能力:File System Observer API

在最新的Web技術(shù)革命中,我們迎來了一個令人興奮的新API——File System Observer API(文件系統(tǒng)觀察者API)。這不僅僅是一個簡單的文件操作工具,它賦予了網(wǎng)頁應(yīng)用前所未有的能力——實時監(jiān)控本地文件的一舉一動!

實時監(jiān)控,無需刷新

想象一下,你正在開發(fā)一個Web端相冊應(yīng)用,用戶可以隨時添加或刪除圖片。有了File System Observer API,你的應(yīng)用能夠即時響應(yīng)這些變化,無需用戶手動刷新頁面。這就像是給網(wǎng)頁裝上了千里眼和順風(fēng)耳,任何文件的新增、修改或刪除都逃不過它的監(jiān)控。

實現(xiàn)監(jiān)聽,簡單幾步

實現(xiàn)文件監(jiān)聽的步驟簡單到令人難以置信。首先,你需要實例化一個FileSystemObserver對象,并傳入一個回調(diào)函數(shù)。然后,通過showOpenFilePickershowDirectoryPicker選擇要監(jiān)聽的文件或文件夾,并使用observe方法開始監(jiān)聽。

監(jiān)聽文件和文件夾

無論是單個文件還是整個文件夾,F(xiàn)ile System Observer API都能輕松應(yīng)對。你可以選擇監(jiān)聽文件夾的一級內(nèi)容,或者通過設(shè)置recursive: true來監(jiān)聽所有子級內(nèi)容。

操作類型全覆蓋

文件的新建、刪除、修改、移動,甚至是重命名,F(xiàn)ile System Observer API都能準(zhǔn)確捕捉并通知你的應(yīng)用。每個操作都會生成一個詳細(xì)的FileSystemChangeRecord對象,讓你能夠精確地了解發(fā)生了什么。

試一下我們的 Demo,實時進行修改,就會觸發(fā)

解除監(jiān)聽,一鍵搞定

當(dāng)你想要停止監(jiān)聽某個文件或文件夾時,只需調(diào)用disconnect方法,一切都會恢復(fù)原狀。

怎么申請token

首先我們訪問 谷歌FSO申請鏈接 并登錄賬號。

FSO 還是一套嶄新的 API,有多新呢?MDN 和 CanIUse 中還沒有建立關(guān)于它的詞條。但這并不意味著我們完全無法用于生產(chǎn)環(huán)境,我已經(jīng)用到線上功能中了。只要做一點配置工作,你和你的用戶就能成為全球第一批享受到 FSO 的人 。

Chrome 已經(jīng)對 FSO 開啟了試用,版本范圍是 129 到 134,你可以為你的 Web App 域名注冊一個試用 token,你可以跟著我一步一步操作

f12打開控制臺輸入FileSystemObserver,如果有返回既是使用成功

那怎么調(diào)用這套API來實現(xiàn)我們監(jiān)聽文件夾的功能?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>谷歌FSO API</title>
  <style>
    .row-box {
      display: flex;
    }
    .row-box > div {
      width: 50%;
      height: 70vh;
      overflow: auto;
    }
    #log-box {
      background-color: #f0f0f0;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
      display: none;
    }
    .alert-box {
      color: red;
      font-size: 12px;
      line-height: 1;
      margin-bottom: 12px;
      padding: 8px;
      border-radius: 12px;
    }
    .alert-title,.alert-content{
      font-size: 20px;
    }
    #dir-name{
      color: red;
    }
  </style>
</head>
<body>
  <h1>File Observer API 監(jiān)聽文件夾變化</h1>
  <div class="alert-box">
    <div class="alert-title">?? 注意?。?!</div>
    <div class="alert-content">
      <p>本程序不會上傳任何文件到服務(wù)器,切勿使用重要文件進行調(diào)試,以免造成數(shù)據(jù)丟失</p>
    </div>
  </div>
  <button id="dir-btn">請選擇一個文件夾進行監(jiān)聽</button>
  <p>
    <span id="dir-name"></span>
  </p>
  <div class="row-box">
    <div id="dir-info"></div>
    <div id="log-box"></div>
  </div>
  <script type="importmap">
  {
    "imports": {
      "@rejax/fsot": "https://unpkg.com/@rejax/fsot/index.js"
    }
  }
  </script>
  <script type="module">
    import { setFSObserverToken } from './index.js'
    setFSObserverToken()
  </script>
  <script type="module">
    import { FSObserver } from '@rejax/fsot'

    const dirBtn = document.getElementById('dir-btn')
    const dirInfo = document.getElementById('dir-info')
    const logBox = document.getElementById('log-box')
    const dirName = document.getElementById('dir-name')

    let dirEntries = null
    const fob = new FSObserver(callback)

    const kindMap = {
      'directory': '文件夾',
      'file': '文件',
    }
    const operationMap = {
      'appeared': '新增',
      'disappeared': '刪除',
      'modified': '修改',
      'moved': '移動',
      'renamed': '重命名',
    }
    
    dirBtn.addEventListener('click', handleClick)
    
    async function handleClick() {
      const dirHandle = await window.showDirectoryPicker()
      dirEntries = dirHandle.values()

      const options = {
        recursive: true,
      }
      
      console.log('fob', fob);
      
      await fob.observe(dirHandle, options)
      const localDirName = fob.rootHandle.name
      dirName.innerText=`當(dāng)前監(jiān)聽的本地目錄: ${localDirName}`

      dirBtn.disabled = true
      logBox.style.display = 'block'

      for await (const entry of dirEntries) {
        const { kind, name } = entry
        showChild(kind, name)
      }
    }
    
    async function callback(log, records, observer) {
      console.log('log', log);
      const logEle = document.createElement('p')
      logEle.innerText = log.description
      logBox.appendChild(logEle)

      const { operation, handle, to, from } = log
      switch (operation) {
        case 'create':
          add(handle, to)
          break
        case 'remove':
          remove(handle, to)
          break
        case 'modify':
          modifyFile(handle, to)
          break
        case 'move':
          move(handle, to, from)
          break
        case 'rename':
          rename(handle, to, from)
          break
      }
    }
    function showChild(kind, name) {
      const entryId = `${kind}-${name}`
      const entry = document.createElement('p')
      entry.id = entryId
      entry.innerHTML = `${kindMap[kind]} ${name}`
      dirInfo.appendChild(entry)
    }
    
    async function add(handle, path) {
      const { kind } = handle
      if (!path.includes('/')) {
        // 子文件中增加實體時,不顯示
        showChild(kind, path)
      }
    }

    function remove(handle, path) {
      const { kind, name } = handle
      const childName = path || name
      const entryId = `${kind}-${childName}`
      const entry = document.getElementById(entryId)
      if (entry) {
        entry.remove()
      }
    }

    async function modifyFile(handle, path) {
      
    }

    async function rename(handle, path, oldPath) {
      const { kind, name } = handle
      const childName = path || name
      const entryId = `${kind}-${oldPath}`
      let entry = document.getElementById(entryId)
      if (entry) {
        entry.innerText = `${kindMap[kind]} ${path}`
        entry.id = `${kind}-${path}`
      }
    }

    async function move(handle, path, oldPath) {
      const { kind, name } = handle
      const childName = path || name
      const entryId = `${kind}-${oldPath}`
      let entry = document.getElementById(entryId)
      const pathArr = path.split('/')
      const oldPathArr = oldPath.split('/')
      
      // 文件層級下沉
      if (pathArr.length > oldPathArr.length) {
        entry?.remove()
      }

      // 文件層級上升
      if (pathArr.length < oldPathArr.length && pathArr.length === 1) {
        showChild(kind, name)
      }
    }
  </script>
</body>
</html>

這里是setFSObserverToken,把前面申請到的token進行替換即可,這里要配置好域名,域名不一樣會報錯,無法使用

export function setFSObserverToken () {
  let token = 'AvBwEvROC6H+jSr2r1nwgj0G0T8tOs2MnXT9GSFcHVXV2un4GQ/+9Sa2TfWbJGhUbZe5lyF+APSpjovP+NtNEQwAAABWeyJvcmlnaW4iOiJodHRwOi8vMTI3LjAuMC4xOjUzMTA1IiwiZmVhdHVyZSI6IkZpbGVTeXN0ZW1PYnNlcnZlciIsImV4cGlyeSI6MTc0NzE4MDc5OX'
  const origin = window.location.origin
  if (origin.includes('https://rejax.fun')) {
    token = 'AvBwEvROC6H+jSr2r1nwgj0G0T8tOs2MnXT9GSFcHVXV2un4GQ/+9Sa2TfWbJGhUbZe5lyF+APSpjovP+NtNEQwAAABWeyJvcmlnaW4iOiJodHRwOi8vMTI3LjAuMC4xOjUzMTA1IiwiZmVhdHVyZSI6IkZpbGVTeXN0ZW1PYnNlcnZlciIsImV4cGlyeSI6MTc0NzE4MDc5OX'
  }
  const meta = document.createElement('meta')
  meta.httpEquiv = 'origin-trial'
  meta.content = token
  document.head.appendChild(meta)
}

總結(jié)

File System Observer API的引入,不僅僅是對Web開發(fā)者的一次解放,更是對整個Web生態(tài)的巨大推動。它讓W(xué)eb應(yīng)用更加強大,用戶體驗更加流暢?,F(xiàn)在,是時候開始探索這個全新的API,為你的Web應(yīng)用增添超級能力了!

到此這篇關(guān)于純JS實現(xiàn)監(jiān)控本地文件變化的文章就介紹到這了,更多相關(guān)JS監(jiān)控本地文件變化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • xmlplus組件設(shè)計系列之列表(4)

    xmlplus組件設(shè)計系列之列表(4)

    xmlplus 是一個JavaScript框架,用于快速開發(fā)前后端項目。這篇文章主要介紹了xmlplus組件設(shè)計系列之列表,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 詳解js根據(jù)百度地圖提供經(jīng)緯度計算兩點距離

    詳解js根據(jù)百度地圖提供經(jīng)緯度計算兩點距離

    這篇文章主要介紹了js根據(jù)百度地圖提供經(jīng)緯度計算兩點距離,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • JavaScript 驗證瀏覽器是否支持javascript的方法小結(jié)

    JavaScript 驗證瀏覽器是否支持javascript的方法小結(jié)

    一些網(wǎng)站只有客戶端js的驗證,這樣就給一些hacher一些可趁之機了,不信大家測試一些網(wǎng)站的注冊功能看看,有部分網(wǎng)站只有客戶端驗證,我為了達(dá)到客戶端驗證,先是判斷瀏覽器是否支持js,如果不支持,提示信息,然后屏蔽掉發(fā)送按鈕
    2009-05-05
  • 用JS編寫選項卡效果

    用JS編寫選項卡效果

    這篇文章主要為大家詳細(xì)介紹了用JS編寫選項卡效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 基于BootStrap Metronic開發(fā)框架經(jīng)驗小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理

    基于BootStrap Metronic開發(fā)框架經(jīng)驗小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理

    在很多系統(tǒng)模塊里面,我們可能都需要進行一定的數(shù)據(jù)交換處理,這樣可以很好的達(dá)到用戶操作體驗感,接下來通過本文給大家介紹基于BootStrap Metronic開發(fā)框架經(jīng)驗小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理相關(guān)知識,非常具有參考價值,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • 深入了解TypeScript中的映射類型

    深入了解TypeScript中的映射類型

    在?TypeScript?中,映射類型可以幫助我們避免編寫重復(fù)的代碼,它可以根據(jù)現(xiàn)有類型和定義的一些規(guī)則來創(chuàng)建新類型。本文我們就來看一下什么是映射類型以及如何構(gòu)建自己的映射類型
    2022-08-08
  • 原生JS實現(xiàn)可拖拽登錄框

    原生JS實現(xiàn)可拖拽登錄框

    這篇文章主要為大家詳細(xì)介紹了原生JS實現(xiàn)可拖拽登錄框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 淺談html轉(zhuǎn)義及防止javascript注入攻擊的方法

    淺談html轉(zhuǎn)義及防止javascript注入攻擊的方法

    下面小編就為大家?guī)硪黄獪\談html轉(zhuǎn)義及防止javascript注入攻擊的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • async/await實現(xiàn)Promise.acll()簡介

    async/await實現(xiàn)Promise.acll()簡介

    Promise.all() 方法接收一個 promise 的 iterable 類型的輸入,并且只返回一個Promise實例,并且輸入的所有 promise 的 resolve 回調(diào)的結(jié)果是一個數(shù)組,這篇文章主要介紹了async/await實現(xiàn)Promise.acll()簡介,需要的朋友可以參考下
    2022-11-11
  • Postman參數(shù)化實現(xiàn)過程及原理解析

    Postman參數(shù)化實現(xiàn)過程及原理解析

    這篇文章主要介紹了Postman參數(shù)化實現(xiàn)過程及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08

最新評論