最小單元 flutter for webURL導(dǎo)航與hashtag(#)的處理

關(guān)于Flutter for web的導(dǎo)航

通常對于傳統(tǒng)網(wǎng)站來說訪問行為是讓一個HTML地址對應(yīng)一個頁面資源,而對于APP來說內(nèi)部的多個頁面是通過代碼指令耦合的,整個APP實(shí)際上是一個資源。隨著應(yīng)用規(guī)模的擴(kuò)大原本通過指令進(jìn)行頁面跳轉(zhuǎn)的模式被抽取歸納統(tǒng)一為路由跳轉(zhuǎn)。隨著HYBRID的發(fā)展與urlscheme結(jié)合為協(xié)議路由統(tǒng)一跳轉(zhuǎn)與狀態(tài)傳遞的方式。

flutter中的頁面導(dǎo)航使用'router'進(jìn)行,在應(yīng)用內(nèi)部導(dǎo)航的方式比較自由,指令或者命名或者根據(jù)已有規(guī)范統(tǒng)一到urlScheme中走中心路由的架構(gòu)都可以隨自己應(yīng)用的體量來選擇。

攔截URL

使用 onGenerateRoute: onGenerateRoute可以截獲通過URL獲取路由的路徑,在flutter for web中這里就可以截獲在瀏覽器地址中輸入的鏈接中index地址后面的部分

image
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {

  return MaterialApp(
   title: "main",
      debugShowCheckedModeBanner: false,
      onGenerateRoute:  onGenerateRoute,

  );
}
}
Route<dynamic> onGenerateRoute(RouteSettings settings) {
  String routeName = settings.name;
//根據(jù)地址跳轉(zhuǎn)不同的頁面
  if (routeName.contains('/artical')) {
      //截取參數(shù)
    String arg = "";
    if(routeName.length > 10){
      arg =  routeName.substring(9,routeName.length);
    }
    return MaterialPageRoute(builder: (context) { return HomeWidget(arguments: arg,); });
  } else if (routeName.contains('/tool')) {
    return MaterialPageRoute(builder: (context) { return ToolsPage(); });
  }else if (routeName.contains('/quote')) {
    return MaterialPageRoute(builder: (context) { return KlinePage(); });
  }else{
    return  MaterialPageRoute(builder: (context) { return HomeWidget(); });
  }
}

HashTag("#")問題

由于Flutter for web 是作為HTMLApp的形式存在因此對于瀏覽器來說,無論進(jìn)行多少次內(nèi)部跳轉(zhuǎn)仍然在一個頁面內(nèi)。

nginx以#為分界解析路徑。flutter通過hashtag判別獲取url路徑給onGenerateRoute進(jìn)行攔截獲取參數(shù)。對于單頁面或者內(nèi)嵌WEBAPP來說這對訪問不會造成任何影響。但如果要通過URL訪問指定的頁面會在一些情況下無法訪問。

隱藏自動添加的"/#/"

如果只需要通過根路徑訪問網(wǎng)站。此時flutter會自動將"/#/"拼接在地址欄中

image

如果希望去除# 有兩種方法

1.阻止自動添加#

可以從從項(xiàng)目中刪除向地址欄添加#的代碼 。

首先build項(xiàng)目,然后找到構(gòu)建的項(xiàng)目的 main.dart.js文件并打開搜索 '#'+a找到

we:function(a){return a.length===0?H.b(window.location.pathname)+H.b(window.location.search):"#"+a},

刪除 "#"+。

image
2.向?yàn)g覽器添加一個新的URL
  html.window.history.pushState(null, "flutter", "/");

配合NGINX重定向使用URL導(dǎo)航

如果需要使用URL通過瀏覽器在flutter web app內(nèi)導(dǎo)航則需要使用hashTag的機(jī)制向APP傳遞地址信息,此時若想要在導(dǎo)航鏈路中排除"#",需要配合地址重定向和html.window.history.pushState來手動構(gòu)建導(dǎo)航體系。

  1. 通過NGINX添加重定向

    image
  2. 獲取路徑后Push訪問路經(jīng)

    image

如果是訪問有連接后綴的地址onGenerateRoute 會被調(diào)用兩次,第一次是傳入空置進(jìn)去,第二次才會傳入地址欄中的地址。因此在沒有收到后綴的地址中不能pushstate否則會屏蔽掉后續(xù)的重定向內(nèi)容導(dǎo)致鏈接跳轉(zhuǎn)失效。

過程大致如圖

image

在這個方案下,頁面導(dǎo)航與Nginx地址解析實(shí)際上是深度綁定了NGINX需要重定向所有應(yīng)用中PUSHSTATE進(jìn)瀏覽器的地址。而如果使用了CDN加速 會導(dǎo)致重定向失效

通過瀏覽器獲取URL進(jìn)行導(dǎo)航

在無法通過NGINX重定向來協(xié)助導(dǎo)航的情況下,只能根據(jù)瀏覽器這一使用場景做特殊處理。讓實(shí)例自己獲取當(dāng)前URL去做導(dǎo)航。使用html.window.location獲取當(dāng)前訪問的地址。而NGINX只需要將所有有導(dǎo)航目的地的路徑都指向根目錄就行了。

NGINX:

image

Flutter:

image

最后 如果設(shè)置了一些特殊的NGINX規(guī)則如二級路徑有可能導(dǎo)致flutter中無法找到圖片資源。因此建議使用遠(yuǎn)端資源。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容