亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

實(shí)時(shí)監(jiān)控,無(wú)需刷新

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

實(shí)現(xiàn)監(jiān)聽(tīng),簡(jiǎn)單幾步

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

監(jiān)聽(tīng)文件和文件夾

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

操作類型全覆蓋

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

試一下我們的 Demo,實(shí)時(shí)進(jìn)行修改,就會(huì)觸發(fā)

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

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

怎么申請(qǐng)token

首先我們?cè)L問(wèn) 谷歌FSO申請(qǐng)鏈接 并登錄賬號(hào)。

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

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

f12打開(kāi)控制臺(tái)輸入FileSystemObserver,如果有返回既是使用成功

那怎么調(diào)用這套API來(lái)實(shí)現(xiàn)我們監(jiān)聽(tīng)文件夾的功能?

<!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)聽(tīng)文件夾變化</h1>
  <div class="alert-box">
    <div class="alert-title">?? 注意?。?!</div>
    <div class="alert-content">
      <p>本程序不會(huì)上傳任何文件到服務(wù)器,切勿使用重要文件進(jìn)行調(diào)試,以免造成數(shù)據(jù)丟失</p>
    </div>
  </div>
  <button id="dir-btn">請(qǐng)選擇一個(gè)文件夾進(jìn)行監(jiān)聽(tīng)</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': '移動(dòng)',
      '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)聽(tīng)的本地目錄: ${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('/')) {
        // 子文件中增加實(shí)體時(shí),不顯示
        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('/')
      
      // 文件層級(jí)下沉
      if (pathArr.length > oldPathArr.length) {
        entry?.remove()
      }

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

這里是setFSObserverToken,把前面申請(qǐng)到的token進(jìn)行替換即可,這里要配置好域名,域名不一樣會(huì)報(bào)錯(cuò),無(wú)法使用

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的引入,不僅僅是對(duì)Web開(kāi)發(fā)者的一次解放,更是對(duì)整個(gè)Web生態(tài)的巨大推動(dòng)。它讓W(xué)eb應(yīng)用更加強(qiáng)大,用戶體驗(yàn)更加流暢?,F(xiàn)在,是時(shí)候開(kāi)始探索這個(gè)全新的API,為你的Web應(yīng)用增添超級(jí)能力了!

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

相關(guān)文章

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

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

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

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

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

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

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

    用JS編寫選項(xiàng)卡效果

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

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

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

    深入了解TypeScript中的映射類型

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

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

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

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

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

    async/await實(shí)現(xiàn)Promise.acll()簡(jiǎn)介

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

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

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

最新評(píng)論