11、Flutter Fish redux component实现登录界面

本文主要记录个人在学习fish redux中的component部分,通过编写一个登录框架来加深理解。
首先在lib下创建login包,通过右键fish redux Template,创建LoginPage。
fish redux中的component是用来组成page中view的,所以是不能单独使用的,其中的用法在代码上表现的很直接:

class LoginPage extends Page<LoginState, Map<String, dynamic>> {
  LoginPage()
      : super(
            initState: initState,
            effect: buildEffect(),
            reducer: buildReducer(),
            view: buildView,
            dependencies: Dependencies<LoginState>(
                adapter: null,
                slots: <String, Dependent<LoginState>>{
                  'smsComponent':
                    SmsLoginConnector() + SmsComponent(),
                  'pwdComponent':
                    PwdLoginConnector() + PwdComponent(),
                }),
            middleware: <Middleware<LoginState>>[
            ],);
}

代码中的slots,依赖于smsComponent及pwdComponent两个子组件,通过连接器将LoginPage与SmsComponent、PwdComponent联系起来。
看到这里,明白SmsComponent跟PwdComponent是LoginPage的子组件,在login目录下面,按照创建LoginPage方式,创建出来两个component——PwdComponent&SmsComponent。至此,已经完成了login界面目录结构上的搭建。

loginPage结构图.png

然后,开始使用component来组装页面(page)了:
第一步,在LoginState(State文件)中,初始化state,loginState是Loginpage的state,其中应该包含子组件的state的初始化及创建联系:

class LoginState implements Cloneable<LoginState> {
  SmsState smsState;
  PwdState pwdState;
  bool isSmsModel;

  @override
  LoginState clone() {
    return LoginState()
      ..smsState = smsState
      ..pwdState = pwdState
      ..isSmsModel=isSmsModel;
  }
}

LoginState initState(Map<String, dynamic> args) {
  return LoginState()..isSmsModel = true
  ..pwdState = PwdState(loginBtnEnable: false)//初始化pwdComponent中按键的状态
  ..smsState = SmsState(loginBtnEnable: false);//初始化smsComponent中按键的状态
}
//smsComponent与page的连接器
class SmsLoginConnector extends ConnOp<LoginState,SmsState>{
  @override
  SmsState get(LoginState state) {
    return state.smsState;
  }
  @override
  void set(LoginState state, SmsState subState) {
    state.smsState = subState;
  }
}
//pwdComponent与page的连接器
class PwdLoginConnector extends ConnOp<LoginState,PwdState>{
  @override
  PwdState get(LoginState state) {
    return state.pwdState;
  }
  @override
  void set(LoginState state, PwdState subState) {
    state.pwdState = subState;
  }
}

第二步,在view中引用smsComponent及pwdComponent。
通过 state中的isSmsModel来确定引用当前那个子组件:

Widget buildView(LoginState state, Dispatch dispatch, ViewService viewService) {
  return Scaffold(
    backgroundColor: Colors.white,
    body: Container(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
        ......
          _getLoginView(state,viewService),//引入子组件
        ],
      ),
    ),
  );
}
//判断当前的isSmsModel,加载不同的组件
Widget _getLoginView(LoginState state,ViewService viewService){
  if(!state.isSmsModel){
    return Container(
      child: viewService.buildComponent('smsComponent'),
    );
  }else{
    return Container(
      child: viewService.buildComponent('pwdComponent'),
    );
  }
}

state.isSmsModel是由页面顶部的“密码登录”跟“验证码登录”两个按键控制的,具体实现可以参考GitHub中的具体代码。
第三步,实现验证码登录及密码登录的切换
在login的Action中创建pwdLogin,及smsLogin两个意图,view中的密码登录及验证码登录按键,触发这两个意图,并发送(dispatch)给effect,拿到pwdLogin及smsLogin两个意图的effect将该意图,再次发生(dispatch)给reducer,然后通过reducer来更新当前的state,并更新view。

......
LoginState _pwdLogin(LoginState state, Action action){
  final LoginState newState = state.clone();
  newState.isSmsModel = false;
  return newState;
}

第四步,完善component
component的state中包含一个bool类型的状态loginBtnEnable,表示登录按钮是否可用。在LoginPage state中默认值为false。接下来是component的view:

Widget buildView(PwdState state, Dispatch dispatch, ViewService viewService) {
  return Container(
    margin: EdgeInsets.only(left: 30, top: 40, right: 30),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          child: TextField(
            decoration: InputDecoration(
              hintText: "请输入手机号码",
              hintStyle: TextStyle(color: Colors.grey[300], fontSize: 14),
              border: InputBorder.none,
            ),
            cursorColor: Color(0xFF009274),
          ),
          decoration: BoxDecoration(
              // 下滑线浅灰色,宽度1像素
              border: Border(
                  bottom: BorderSide(color: Colors.grey[300], width: 0.5))),
        ),
        Stack(
          children: <Widget>[
            Container(
              margin: EdgeInsets.only(top: 20),
              child: TextField(
                decoration: InputDecoration(
                  hintText: "请输入验证码",
                  hintStyle: TextStyle(color: Colors.grey[300], fontSize: 14),
                  border: InputBorder.none,
                ),
                obscureText: true,
                cursorColor: Color(0xFF009274),
              ),
              decoration: BoxDecoration(
                // 下滑线浅灰色,宽度1像素
                  border: Border(
                      bottom: BorderSide(color: Colors.grey[300], width: 0.5))),
            ),
          ......//详细代码,请参考Github
}

到这里,我们就完成了多个component组件组装一个page,以上都是开发思路,具体实现可参考https://github.com/zjt19870816/fish_redux_login

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容