懂 Vue、React 就懂 Flutter 路由管理
在现代应用程序中,页面之间的导航是一个重要的组成部分。无论是前端开发还是Flutter开发,路由都是用于管理不同页面之间导航的关键技术。在本文中,我们将深入研究Flutter路由管理的各个方面,帮助你更好地理解Flutter中的路由概念和使用方法。
路由介绍
无论是前端还是Flutter,路由都是用于管理应用程序中不同页面之间的导航。它们都允许用户通过点击链接或按钮来切换到不同的页面。这使得用户能够轻松地浏览不同的内容,无论是在浏览器中还是在Flutter应用程序中。
它们的相似点:
- 都用于实现页面之间的导航和切换。
- 都可以通过路由名称或路径进行页面跳转。
- 都支持传递参数给目标页面。
它们的不同点:
- 原生路由通常是基于操作系统提供的导航机制,而Flutter路由是在Flutter框架内部实现的。
- 原生路由通常使用操作系统提供的界面元素(如导航栏、标签栏),而Flutter路由可以自定义界面元素。
- 浏览器路由通常是基于URL的,可以直接通过URL进行导航,而Flutter路由通常使用命名路由来进行页面跳转。
Flutter 路由的使用场景
基本路由
基本路由是最简单的路由形式,用于在不同页面之间进行简单的切换。在Flutter中,可以通过使用Navigator进行基本路由的管理。在前端中我们通常可以通过 history 包来做页面的切换
import { useHistory } from 'react-router-dom';
// ...
const history = useHistory();
// ...
history.push('/about');
那在 Flutter 中也是一样的。
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
除了这种编程式导航外,前端还可以通过 Link 标签做跳转
import { Link } from 'react-router-dom';
<Link to="/about">About</Link>
Flutter 没有对应的语法支持,但是可以通过 InkWell
组件实现类似的效果
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
child: Text('About'),
)
在这个示例中,当用户点击About文本时,将会导航到名为SecondScreen的页面。
命名路由
当页面路由多了以后,我们就会“找个地方”统一的定义路由,来管理整个页面的 url 和组件的对应关系, 在React中
import { BrowserRouter as Router, Route } from 'react-router-dom';
const App = () => {
return (
<Router>
<Route path="/" exact component={HomeScreen} />
<Route path="/second" component={SecondScreen} />
<Route path="/third" component={ThirdScreen} />
</Router>
);
};
在上述示例中,通过组件的path属性指定了每个页面的URL路径,并使用component属性指定了对应的组件。这样,当用户访问相应的URL时,React Router会根据path属性匹配到对应的组件进行渲染。
在 Flutter 中还是熟悉的感觉
MaterialApp(
routes: {
'/': (context) => HomeScreen(),
'/second': (context) => SecondScreen(),
'/third': (context) => ThirdScreen(),
},
);
命名路由允许我们在应用程序中为每个页面指定一个唯一的名称,并通过该名称进行路由切换。这种路由形式在大型应用程序中尤其有用。
嵌套路由
React 和 Flutter 中的嵌套路由实现方式略有不同,但基本原理相似。
当我们的页面变得复杂,我们想在页面中嵌套其他页面, 举个例子,我们页面上面有个header 是导航条,有一个 Home, 和 Profile 的链接,下面是具体 Home 或者 Profile 的页面。相当于我们要在当前页面中嵌套 Home 和 Profile。 在 React 中怎么做呢?
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/profile">Profile</Link>
</li>
</ul>
</nav>
<Route path="/" exact component={Home} />
<Route path="/profile" component={Profile} />
</div>
</Router>
);
}
function Home() {
return <h2>Home</h2>;
}
function Profile() {
return <h2>Profile</h2>;
}
只要用把这2页面的路由嵌入这个页面里,如果当前url的path是/ , 则渲染 home 页面,如果浏览器的 url 是 /profile 则渲染 Profile页面。
Flutter 中我们想实现同样的效果也很简单,唯一区别是上面的映射关系是自动的, Flutter中我们需要写个 swtich case 自己判断一下,什么 “url” 显示什么页面
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: Navigator(
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
switch (settings.name) {
case '/':
builder = (BuildContext context) => HomeScreen();
break;
case '/profile':
builder = (BuildContext context) => ProfileScreen();
break;
}
return MaterialPageRoute(builder: builder, settings: settings);
},
),
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Home'),
),
);
}
}
class ProfileScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Profile'),
),
);
}
}
路由传值
路由传值在路由的使用中场景太常见了, 比如:
- 在新闻app中,将新闻文章ID传递给文章详情页面,以便显示特定文章的内容、评论和分享功能。
- 在社交媒体应用中,将用户ID传递给用户个人资料页面,以便显示特定用户的个人信息、帖子和活动。
- 在旅行预订应用中,将目的地ID传递给目的地详情页面,以便显示特定目的地的景点、酒店和旅游活动。
- balabala
在 React 中传个值,比如传这个ID,只需2步,先定义这个路由接收 id
这个参数,然后在当前页面的 url 中获取这个ID。
// 定义一个组件,接收路由参数
const MyComponent = ({ match }) => {
const { id } = match.params;
return (
<div>
<h1>Hello React!</h1>
<p>路由参数: {id}</p>
</div>
);
};
// 在路由中定义对应的路径和组件
<Route path="/example/:id" component={MyComponent} />
当然也可以编程式传 ID
import React from 'react';
import { useHistory } from 'react-router-dom';
const MyComponent = () => {
const history = useHistory();
const id = '123'; // 替换为你要传递的ID
const handleClick = () => {
history.push(`/example/${id}`);
};
return (
<div>
<h1>Hello React!</h1>
<button onClick={handleClick}>跳转到例子页面</button>
</div>
);
};
export default MyComponent;
在 Flutter 中我们会使用 Navigator
这个路由管理组件,它提供了打开和退出路由页方法。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// 定义路由
routes: {
'/': (context) => HomeScreen(),
'/example': (context) => ExampleScreen(),
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter App'),
),
body: Center(
child: RaisedButton(
child: Text('跳转到例子页面'),
onPressed: () {
final String id = '123'; // 替换为你要传递的ID
Navigator.pushNamed(context, '/example', arguments: id);
},
),
),
);
}
}
class ExampleScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final String id = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('例子页面'),
),
body: Center(
child: Text('参数值: $id'),
),
);
}
}
上面代码先在MaterialApp小部件内,定义了routes属性来处理应用程序的不同路由。/
路由对应HomeScreen小部件,/example
路由对应ExampleScreen小部件。当按钮被按下时,它使用Navigator.pushNamed()
方法导航到/example
路由。它还传递了一个参数(id)给路由。
那 /example
路由该如何获取这个 id 参数呢? 可以通过ModalRoute.of(context).settings.arguments
方法检索传递的参数(id),并在一个Text小部件中显示它。
结束语
通过本文,我们详细介绍了Flutter路由管理的不同方面,并与前端路由进行了对比。无论你是前端开发者还是Flutter开发者,理解如何有效地管理和使用路由都是非常重要的。
如果你觉得这篇文章有帮助,请点个赞和关注吧❤️!我将持续分享更多有价值的技术知识和经验。谢谢!
转载自:https://juejin.cn/post/7283798844235792419