HarmonyOS 鸿蒙Next中Web 使用WebviewController.loadUrl加载哈希路由,#号后面路由地址变化,但是Web页面不刷新

HarmonyOS 鸿蒙Next中Web 使用WebviewController.loadUrl加载哈希路由,#号后面路由地址变化,但是Web页面不刷新

cke_246.png

cke_1164.png

哈希路由id有变化,但是Web不更新


更多关于HarmonyOS 鸿蒙Next中Web 使用WebviewController.loadUrl加载哈希路由,#号后面路由地址变化,但是Web页面不刷新的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

你好

可以尝试使用 JavaScriptProxy 监听哈希变化

@Entry
@ComponentV2
struct WebViewPage {
  private webviewController: WebviewController = new WebviewController()
  @Local currentUrl: string = ''

  build() {
    Column() {
      Web({ src: this.currentUrl, controller: this.webviewController })
        .javaScriptAccess(true)
        .domStorageAccess(true)
        .onPageEnd(() => {
          // 页面加载完成后注入监听脚本
          this.injectHashChangeListener()
        })
        .onConsole((event) => {
          // 监听控制台消息,用于调试
          console.log(`WebView Console: ${event?.message}`)
          return false
        })
        .width('100%')
        .height('100%')
    }
  }

  aboutToAppear() {
    this.currentUrl = 'https://your-spa-app.com/#/home'
    this.setupJavaScriptProxy()
  }

  // 设置JavaScript桥接
  private setupJavaScriptProxy() {
    try {
      this.webviewController.registerJavaScriptProxy({
        object: {
          // 处理哈希路由变化
          onHashChange: (newHash: string) => {
            console.log(`Hash changed to: ${newHash}`)
            // 可以在这里处理路由变化逻辑
          },
          
          // 强制刷新页面
          forceRefresh: () => {
            this.webviewController.refresh()
          }
        },
        name: 'NativeInterface',
        methodList: ['onHashChange', 'forceRefresh']
      })
    } catch (error) {
      console.error('Failed to register JavaScript proxy:', error)
    }
  }

  // 注入哈希变化监听脚本
  private injectHashChangeListener() {
    const script = `
      (function() {
        let lastHash = location.hash;
        
        // 监听 hashchange 事件
        window.addEventListener('hashchange', function(e) {
          console.log('Hash changed from', e.oldURL, 'to', e.newURL);
          if (window.NativeInterface && window.NativeInterface.onHashChange) {
            window.NativeInterface.onHashChange(location.hash);
          }
        });
        
        // 监听 popstate 事件(浏览器前进后退)
        window.addEventListener('popstate', function(e) {
          console.log('Popstate event:', e.state);
          if (location.hash !== lastHash) {
            lastHash = location.hash;
            if (window.NativeInterface && window.NativeInterface.onHashChange) {
              window.NativeInterface.onHashChange(location.hash);
            }
          }
        });
        
        // 重写 history.pushState 和 replaceState
        const originalPushState = history.pushState;
        const originalReplaceState = history.replaceState;
        
        history.pushState = function() {
          originalPushState.apply(history, arguments);
          setTimeout(() => {
            if (location.hash !== lastHash) {
              lastHash = location.hash;
              if (window.NativeInterface && window.NativeInterface.onHashChange) {
                window.NativeInterface.onHashChange(location.hash);
              }
            }
          }, 0);
        };
        
        history.replaceState = function() {
          originalReplaceState.apply(history, arguments);
          setTimeout(() => {
            if (location.hash !== lastHash) {
              lastHash = location.hash;
              if (window.NativeInterface && window.NativeInterface.onHashChange) {
                window.NativeInterface.onHashChange(location.hash);
              }
            }
          }, 0);
        };
        
        console.log('Hash change listener injected successfully');
      })();
    `
    
    try {
      this.webviewController.runJavaScript(script)
    } catch (error) {
      console.error('Failed to inject hash change listener:', error)
    }
  }

  // 手动导航到新的哈希路由
  navigateToHash(hash: string) {
    const script = `
      if (location.hash !== '${hash}') {
        location.hash = '${hash}';
        // 触发路由更新
        window.dispatchEvent(new HashChangeEvent('hashchange', {
          oldURL: location.href,
          newURL: location.origin + location.pathname + location.search + '${hash}'
        }));
      }
    `
    
    try {
      this.webviewController.runJavaScript(script)
    } catch (error) {
      console.error('Failed to navigate to hash:', error)
    }
  }
}

更多关于HarmonyOS 鸿蒙Next中Web 使用WebviewController.loadUrl加载哈希路由,#号后面路由地址变化,但是Web页面不刷新的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,WebviewController.loadUrl加载带哈希路由的URL时,页面不刷新是预期行为。哈希路由(#后的部分)变化不会触发页面重载,这是Web标准设计。若需监听路由变化,可通过WebviewControlleronUrlLoadChange回调处理。对于单页应用(SPA),前端应使用History API或框架自带路由机制管理视图更新。鸿蒙Webview遵循通用浏览器规范,哈希路由变更仅触发hashchange事件,不发送新请求。

这是一个典型的WebView中处理哈希路由(hash routing)的问题。在HarmonyOS Next中,当使用WebViewController.loadUrl加载带有哈希路由的URL时,如果只改变#号后面的部分,WebView默认不会触发页面刷新。

解决方案建议:

  1. 监听哈希变化事件: 在Web页面中通过JavaScript添加hashchange事件监听:
window.addEventListener('hashchange', function() {
    // 处理路由变化逻辑
    location.reload(); // 或者执行其他更新操作
});
  1. 在HarmonyOS端强制重载:
// 当检测到哈希变化时,强制重新加载页面
webViewController.loadUrl(url, { forceReload: true });
  1. 或者使用replaceState方法替代哈希路由:
// 使用history API代替哈希路由
history.pushState(null, null, newUrl);

注意:哈希路由变化本身不会触发页面重载,这是浏览器的默认行为。开发者需要主动处理路由变化后的页面更新逻辑。

回到顶部