chenlei il y a 6 mois
Parent
commit
70d61c9344
3 fichiers modifiés avec 179 ajouts et 1 suppressions
  1. 1 1
      convert/index.js
  2. 3 0
      tools/index.js
  3. 175 0
      tools/native.js

+ 1 - 1
convert/index.js

@@ -6,7 +6,7 @@ const convert = {
   },
   getTypeStr(typeName, value) {
     const map = config.status[typeName]
-    return map.find((f) => f.value == value)?.label
+    return map.find((f) => f.value == value)?.label || convert.nullViewStr
   },
   getCheckItem(obj, filterFunc = (f) => true) {
     let arr = []

+ 3 - 0
tools/index.js

@@ -1,5 +1,8 @@
 import convert from '../convert'
+import native from './native'
+
 export default {
+  native,
   getDateRange(n = 30, endn = 0) {
   // 获取当前日期
     var myDate = new Date(Date.now() - 1000 * 60 * 60 * 24 * endn)

+ 175 - 0
tools/native.js

@@ -0,0 +1,175 @@
+class ComprehensiveURLObserver {
+  constructor(options = {}) {
+    this.options = {
+      trackHash: true,
+      trackSearch: true,
+      trackPathname: true,
+      debounce: 50,
+      ...options
+    }
+
+    this.observers = []
+    this.lastUrl = this.getCurrentURLState()
+    this.debounceTimer = null
+    this.init()
+  }
+
+  init() {
+    // 监听标准事件
+    window.addEventListener('popstate', this.handleChange.bind(this))
+
+    if (this.options.trackHash) {
+      window.addEventListener('hashchange', this.handleChange.bind(this))
+    }
+
+    // 拦截 History API
+    this.interceptHistoryMethods()
+
+    // 监听点击事件(捕获链接点击)
+    document.addEventListener('click', this.handleClick.bind(this), true)
+
+    // 可选:轮询作为备用方案
+    if (this.options.polling) {
+      this.startPolling()
+    }
+  }
+
+  getCurrentURLState() {
+    return {
+      href: window.location.href,
+      pathname: window.location.pathname,
+      search: window.location.search,
+      hash: window.location.hash,
+      origin: window.location.origin
+    }
+  }
+
+  interceptHistoryMethods() {
+    const methods = ['pushState', 'replaceState']
+
+    methods.forEach(method => {
+      const original = history[method]
+      history[method] = (...args) => {
+        const oldState = this.getCurrentURLState()
+        const result = original.apply(history, args)
+        this.handleChange('history', oldState)
+        return result
+      }
+    })
+  }
+
+  handleClick(event) {
+    const link = event.target.closest('a')
+    if (link && link.href) {
+      const targetUrl = new URL(link.href, window.location.origin)
+      const currentUrl = new URL(window.location.href)
+
+      // 如果是同源导航且不是当前页面
+      if (targetUrl.origin === currentUrl.origin &&
+                targetUrl.href !== currentUrl.href) {
+        event.preventDefault()
+
+        this.handleChange('click', this.getCurrentURLState())
+
+        // 执行实际导航
+        setTimeout(() => {
+          window.location.href = link.href
+        }, 0)
+      }
+    }
+  }
+
+  handleChange(type, oldState = this.lastUrl) {
+    if (this.debounceTimer) {
+      clearTimeout(this.debounceTimer)
+    }
+
+    this.debounceTimer = setTimeout(() => {
+      const newState = this.getCurrentURLState()
+
+      if (this.hasUrlChanged(oldState, newState)) {
+        const changeInfo = {
+          oldUrl: oldState.href,
+          newUrl: newState.href,
+          type: type,
+          timestamp: Date.now(),
+          details: {
+            pathname: { old: oldState.pathname, new: newState.pathname },
+            search: { old: oldState.search, new: newState.search },
+            hash: { old: oldState.hash, new: newState.hash }
+          }
+        }
+
+        this.notifyObservers(changeInfo)
+        this.lastUrl = newState
+      }
+    }, this.options.debounce)
+  }
+
+  hasUrlChanged(oldState, newState) {
+    if (oldState.href !== newState.href) return true
+
+    if (this.options.trackPathname && oldState.pathname !== newState.pathname) return true
+    if (this.options.trackSearch && oldState.search !== newState.search) return true
+    if (this.options.trackHash && oldState.hash !== newState.hash) return true
+
+    return false
+  }
+
+  startPolling() {
+    setInterval(() => {
+      const currentState = this.getCurrentURLState()
+      if (this.hasUrlChanged(this.lastUrl, currentState)) {
+        this.handleChange('polling', this.lastUrl)
+      }
+    }, this.options.pollingInterval || 1000)
+  }
+
+  subscribe(callback) {
+    this.observers.push(callback)
+    return () => this.unsubscribe(callback)
+  }
+
+  unsubscribe(callback) {
+    this.observers = this.observers.filter(obs => obs !== callback)
+  }
+
+  notifyObservers(changeInfo) {
+    this.observers.forEach(observer => {
+      try {
+        observer(changeInfo)
+      } catch (error) {
+        console.error('URL观察者错误:', error)
+      }
+    })
+  }
+
+  destroy() {
+    window.removeEventListener('popstate', this.handleChange)
+    window.removeEventListener('hashchange', this.handleChange)
+    document.removeEventListener('click', this.handleClick)
+
+    if (this.debounceTimer) {
+      clearTimeout(this.debounceTimer)
+    }
+  }
+}
+
+// const unsubscribe = urlWatcher.subscribe((change) => {
+//     console.group('URL变化详情');
+//     console.log('类型:', change.type);
+//     console.log('从:', change.oldUrl);
+//     console.log('到:', change.newUrl);
+//     console.log('路径变化:', change.details.pathname);
+//     console.log('查询参数变化:', change.details.search);
+//     console.log('哈希变化:', change.details.hash);
+//     console.groupEnd();
+// });
+export default {
+  urlWatcher: new ComprehensiveURLObserver({
+    trackHash: true,
+    trackSearch: true,
+    trackPathname: true,
+    debounce: 100
+  })
+}