颤振如何与单页网页和不同的路由网址一起工作?
Posted
技术标签:
【中文标题】颤振如何与单页网页和不同的路由网址一起工作?【英文标题】:how flutter work with single page web and different route url? 【发布时间】:2021-06-08 05:26:56 【问题描述】:我是 Flutter-web 的新手。
我正在使用flutter构建具有不同路由但不渲染整个页面的单页网站。
已经尝试过navigator.push & button导航栏,但是没用。
页面变更时如何构建不同url的单页网站?
抱歉英语不好!
【问题讨论】:
请通过发布一些代码来展示您已经尝试过的内容。 【参考方案1】:找到解决方案:
import 'package:flutter/material.dart';
void main()
runApp(NestedRouterDemo());
class Book
final String title;
final String author;
Book(this.title, this.author);
class NestedRouterDemo extends StatefulWidget
@override
_NestedRouterDemoState createState() => _NestedRouterDemoState();
class _NestedRouterDemoState extends State<NestedRouterDemo>
BookRouterDelegate _routerDelegate = BookRouterDelegate();
BookRouteInformationParser _routeInformationParser =
BookRouteInformationParser();
@override
Widget build(BuildContext context)
return MaterialApp.router(
title: 'Books App',
routerDelegate: _routerDelegate,
routeInformationParser: _routeInformationParser,
);
class BooksAppState extends ChangeNotifier
int _selectedIndex;
Book _selectedBook;
final List<Book> books = [
Book('Stranger in a Strange Land', 'Robert A. Heinlein'),
Book('Foundation', 'Isaac Asimov'),
Book('Fahrenheit 451', 'Ray Bradbury'),
];
BooksAppState() : _selectedIndex = 0;
int get selectedIndex => _selectedIndex;
set selectedIndex(int idx)
_selectedIndex = idx;
notifyListeners();
Book get selectedBook => _selectedBook;
set selectedBook(Book book)
_selectedBook = book;
notifyListeners();
int getSelectedBookById()
if (!books.contains(_selectedBook)) return 0;
return books.indexOf(_selectedBook);
void setSelectedBookById(int id)
if (id < 0 || id > books.length - 1)
return;
_selectedBook = books[id];
notifyListeners();
class BookRouteInformationParser extends RouteInformationParser<BookRoutePath>
@override
Future<BookRoutePath> parseRouteInformation(
RouteInformation routeInformation) async
final uri = Uri.parse(routeInformation.location);
if (uri.pathSegments.isNotEmpty && uri.pathSegments.first == 'settings')
return BooksSettingsPath();
else
if (uri.pathSegments.length >= 2)
if (uri.pathSegments[0] == 'book')
return BooksDetailsPath(int.tryParse(uri.pathSegments[1]));
return BooksListPath();
@override
RouteInformation restoreRouteInformation(BookRoutePath configuration)
if (configuration is BooksListPath)
return RouteInformation(location: '/home');
if (configuration is BooksSettingsPath)
return RouteInformation(location: '/settings');
if (configuration is BooksDetailsPath)
return RouteInformation(location: '/book/$configuration.id');
return null;
class BookRouterDelegate extends RouterDelegate<BookRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath>
final GlobalKey<NavigatorState> navigatorKey;
BooksAppState appState = BooksAppState();
BookRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>()
appState.addListener(notifyListeners);
@override
BookRoutePath get currentConfiguration
if (appState.selectedIndex == 1)
return BooksSettingsPath();
else
if (appState.selectedBook == null)
return BooksListPath();
else
return BooksDetailsPath(appState.getSelectedBookById());
@override
Widget build(BuildContext context)
return Navigator(
key: navigatorKey,
pages: [
MaterialPage(
child: AppShell(appState: appState),
),
],
onPopPage: (route, result)
if (!route.didPop(result))
return false;
if (appState.selectedBook != null)
appState.selectedBook = null;
notifyListeners();
return true;
,
);
@override
Future<void> setNewRoutePath(BookRoutePath path) async
if (path is BooksListPath)
appState.selectedIndex = 0;
appState.selectedBook = null;
else if (path is BooksSettingsPath)
appState.selectedIndex = 1;
else if (path is BooksDetailsPath)
appState.selectedIndex = 0;
appState.setSelectedBookById(path.id);
// Routes
abstract class BookRoutePath
class BooksListPath extends BookRoutePath
class BooksSettingsPath extends BookRoutePath
class BooksDetailsPath extends BookRoutePath
final int id;
BooksDetailsPath(this.id);
// Widget that contains the AdaptiveNavigationScaffold
class AppShell extends StatefulWidget
final BooksAppState appState;
AppShell(
@required this.appState,
);
@override
_AppShellState createState() => _AppShellState();
class _AppShellState extends State<AppShell>
InnerRouterDelegate _routerDelegate;
ChildBackButtonDispatcher _backButtonDispatcher;
void initState()
super.initState();
_routerDelegate = InnerRouterDelegate(widget.appState);
@override
void didUpdateWidget(covariant AppShell oldWidget)
super.didUpdateWidget(oldWidget);
_routerDelegate.appState = widget.appState;
@override
void didChangeDependencies()
super.didChangeDependencies();
// Defer back button dispatching to the child router
_backButtonDispatcher = Router.of(context)
.backButtonDispatcher
.createChildBackButtonDispatcher();
@override
Widget build(BuildContext context)
var appState = widget.appState;
// Claim priority, If there are parallel sub router, you will need
// to pick which one should take priority;
_backButtonDispatcher.takePriority();
return Scaffold(
appBar: AppBar(),
body: Router(
routerDelegate: _routerDelegate,
backButtonDispatcher: _backButtonDispatcher,
),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(
icon: Icon(Icons.settings), label: 'Settings'),
],
currentIndex: appState.selectedIndex,
onTap: (newIndex)
appState.selectedIndex = newIndex;
,
),
);
class InnerRouterDelegate extends RouterDelegate<BookRoutePath>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<BookRoutePath>
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
BooksAppState get appState => _appState;
BooksAppState _appState;
set appState(BooksAppState value)
if (value == _appState)
return;
_appState = value;
notifyListeners();
InnerRouterDelegate(this._appState);
@override
Widget build(BuildContext context)
return Navigator(
key: navigatorKey,
pages: [
if (appState.selectedIndex == 0) ...[
FadeAnimationPage(
child: BooksListScreen(
books: appState.books,
onTapped: _handleBookTapped,
),
key: ValueKey('BooksListPage'),
),
if (appState.selectedBook != null)
MaterialPage(
key: ValueKey(appState.selectedBook),
child: BookDetailsScreen(book: appState.selectedBook),
),
] else
FadeAnimationPage(
child: SettingsScreen(),
key: ValueKey('SettingsPage'),
),
],
onPopPage: (route, result)
appState.selectedBook = null;
notifyListeners();
return route.didPop(result);
,
);
@override
Future<void> setNewRoutePath(BookRoutePath path) async
// This is not required for inner router delegate because it does not
// parse route
assert(false);
void _handleBookTapped(Book book)
appState.selectedBook = book;
notifyListeners();
class FadeAnimationPage extends Page
final Widget child;
FadeAnimationPage(Key key, this.child) : super(key: key);
Route createRoute(BuildContext context)
return PageRouteBuilder(
settings: this,
pageBuilder: (context, animation, animation2)
var curveTween = CurveTween(curve: Curves.easeIn);
return FadeTransition(
opacity: animation.drive(curveTween),
child: child,
);
,
);
// Screens
class BooksListScreen extends StatelessWidget
final List<Book> books;
final ValueChanged<Book> onTapped;
BooksListScreen(
@required this.books,
@required this.onTapped,
);
@override
Widget build(BuildContext context)
return Scaffold(
body: ListView(
children: [
for (var book in books)
ListTile(
title: Text(book.title),
subtitle: Text(book.author),
onTap: () => onTapped(book),
)
],
),
);
class BookDetailsScreen extends StatelessWidget
final Book book;
BookDetailsScreen(
@required this.book,
);
@override
Widget build(BuildContext context)
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
FlatButton(
onPressed: ()
Navigator.of(context).pop();
,
child: Text('Back'),
),
if (book != null) ...[
Text(book.title, style: Theme.of(context).textTheme.headline6),
Text(book.author, style: Theme.of(context).textTheme.subtitle1),
],
],
),
),
);
class SettingsScreen extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
body: Center(
child: Text('Settings screen'),
),
);
【讨论】:
以上是关于颤振如何与单页网页和不同的路由网址一起工作?的主要内容,如果未能解决你的问题,请参考以下文章
如何设置NGINX以根据位置(在相同的server_name下)部署不同的单页应用程序(SPA的...即静态文件)和子路由