Flutter 是借鉴 React 的开发思想实现的,在子组件的插槽上,React 有this.props.children
,Vue 有<slot></slot>
。
当然 Flutter 也有类似的 Widget,那就是Navigator
,不过是以 router 的形式实现(像<router-view></router-view>
???)。
Navigator 的使用无非 3 个属性
-
initialRoute
: 初始路由 -
onGenerateRoute
: 匹配路由 -
onUnknownRoute
: 404
在实现层面
首先:Navigator 的高度为 infinity。如果直接父级非最上级也是 infinity 会产生异常,例如,Scaffold -> Column -> Navigator。所以:Navigator 需要附件限制高度,例如:Scaffold -> Column -> Container(height: 300)-> Navigator
然后:在 onGenerateRoute 属性中,使用第一个 BuildContext 参数,能够在 MaterialApp 未设置 route 的情况下使用 Navigator.pushNamed(nContext, '/efg');
跳到对应的子路由中。
最后:Navigator 执行寻找路由顺序是 initialRoute -> onGenerateRoute -> onUnknownRoute,这个和 React 的 Route 是类似的。
最后附上源码
import 'package:flutter/material.dart';
class NavigatorPage extends StatefulWidget {
@override
_NavigatorPageState createState() => _NavigatorPageState();
}
class _NavigatorPageState extends State<NavigatorPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Navigator'),
),
body: Column(
children: <Widget>[Text('Navigator 的高度为 infinity'),
Text('如果直接父级非最上级也是 infinity 会产生异常'),
Container(
height: 333,
color: Colors.amber.withAlpha(111),
child: Navigator( // Navigator
initialRoute: '/abc',
onGenerateRoute: (val) {
RoutePageBuilder builder;
switch (val.name) {
case '/abc':
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Column(
// 并没有在 MaterialApp 中设定 /efg 路由
// 因为 Navigator 的特性 使用 nContext 可以跳转 /efg
children: <Widget>[Text('呵呵呵'),
RaisedButton(child: Text('去 /efg'),
onPressed: () {Navigator.pushNamed(nContext, '/efg');
},
)
],
);
break;
case '/efg':
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Row(
children: <Widget>[
RaisedButton(child: Text('去 /hhh'),
onPressed: () {Navigator.pushNamed(nContext, '/hhh');
},
)
],
);
break;
default:
builder = (BuildContext nContext, Animation<double> animation, Animation<double> secondaryAnimation) => Center(
child: RaisedButton(child: Text('去 /abc'),
onPressed: () {Navigator.pushNamed(nContext, '/abc');
},
)
);
}
return PageRouteBuilder(
pageBuilder: builder,
// transitionDuration: const Duration(milliseconds: 0),
);
},
onUnknownRoute: (val) {print(val);
},
observers: <NavigatorObserver>[]),
),
Text('Navigator 执行寻找路由顺序'),
Text('initialRoute'),
Text('onGenerateRoute'),
Text('onUnknownRoute'),
],
),
);
}
}
项目地址:https://github.com/zhongmeizhi/fultter-example-app
撸完代码记得给颗星哦。