Flutter部件内部状态管理小结之实现Vue的v-model功能
flutter部件内部状态管理
本文是 flutter 部件内部状态管理的小结,从部件的基础开始,到部件的状态管理,并且在过程中实现一个类似 vue 的 v-model 的功能。
widget 基础
widget(部件)
如 react 里万物皆组件, java 里万物皆对象, flutter 里,能看到的一切都是 widget(部件),如按钮、文本框等等。
flutter 内部已经为我们做了一些基础的 widget ,例如:
- text : 这个就是一个文本部件,里面用于放置文本
- row , column : 行列布局部件
- container : 可以理解为 html 里的 div
状态
状态可以理解为 widget 内拥有的成员变量
无状态 widget
无状态是指该成员变量不可改变,即使用 final 修饰符,为常量,创建无状态组件步骤如下:
创建一个类继承 statelesswidget
实现 build 方法(类比写 html + css )
import 'package:flutter/material.dart'; class statelessdemowidget extends statelesswidget { /// 如果定义非final修饰的成员变量,会提示 /// this class (or a class which this class inherits from) is marked as '@immutable', but one or more of its instance fields are not final: statelessdemowidget.listinde /// int [listindex]; @override widget build(buildcontext context) { return container(); } }
有状态 widget
有状态则是指该 widget 内部的成员变量可以不使用 final 修饰符,并通过 setstate() 方法改变成员变量的值时,引起 widget 的状态改变并重绘(例如文本框绑定变量a,通过改变变量a修改文本框的值,这里的变量a可以理解为可变状态)
有状态 widget 通过实现 statefulwidget 和 state 两个子类实现,步骤如下:
- 创建一个 widget 类,继承 statefulwidget
- 创建一个继承 state 的类
- 在 state 类里创建状态(成员变量),和实现 build 方法(画界面)
import 'package:flutter/material.dart'; /// 创建一个继承[statefulwidget]的widget类 /// 这个类的效果类似收藏,有个空心的爱心图标 /// 点击一下爱心填充红色,再点击一次就取消填充 class favoritewidget extends statefulwidget { @override _favoritewidgetstate createstate() => _favoritewidgetstate(); } /// [state]类,favoritewidget的具体实现 /// 包含一个状态[_isfavorited] class _favoritewidgetstate extends state<favoritewidget> { bool _isfavorited = true; @override widget build(buildcontext context) { return row( mainaxissize: mainaxissize.min, children: [ container( padding: edgeinsets.all(0), child: iconbutton( /// [_isfavorited] 为 true 时使用图标 icons.star 否则使用 icons.star_border icon: (_isfavorited ? icon(icons.star) : icon(icons.star_border)), color: colors.red[500], /// 当点击时,改变状态 onpressed: _togglefavorite, ), ), ], ); } /// 改变[_isfavorited]的状态 void _togglefavorite() { setstate(() { if (_isfavorited) { _isfavorited = false; } else { _isfavorited = true; } }); } }
widget 管理内部状态的三种方式
widget 自己管理状态
其实和上边的 有状态部件 示例一样的,直接上代码
import 'package:flutter/material.dart'; class tapboxa extends statefulwidget { @override _tapboxastate createstate() => _tapboxastate(); } /// [tapboxa]拥有状态[_active],通过[_handletap]方法管理[_active] class _tapboxastate extends state<tapboxa> { bool _active = false; void _handletap() { setstate(() { _active = !_active; }); } widget build(buildcontext context) { return gesturedetector( ontap: _handletap, child: center( child: text( _active ? 'active' : 'inactive', ), ), ); } }
父widget 管理 子widget 状态
这一小节将实现一个和 vue 的 v-model 一样的功能,父部件管理子部件的步骤如下:
- 创建一个无状态部件作为子部件,构造函数中需要接收状态的值和状态改变时的回调函数
- 创建一个有状态部件作为父部件,并定义需要管理的状态
- 在父部件中创建子部件,并绑定状态和回调事件
import 'package:flutter/material.dart'; /// 父部件管理tapboxb的状态 /// /// 父部件[parentwidget]定义了[_active]状态,并和[tapboxb]的[active]绑定 /// 当[tapboxb]被点击时,通过[onchanged]方法通知父部件,父部件修改[_active]的值 /// 也就间接修改了[tapboxb]的[active] /// /// 如果了解过vue的v-model原理的话比较好理解,其实这个和vue的v-model一样的 //------------------------ parentwidget -------------------------------- class parentwidget extends statefulwidget { @override _parentwidgetstate createstate() => _parentwidgetstate(); } class _parentwidgetstate extends state<parentwidget> { bool _active = false; void _handletapboxchanged(bool newvalue) { setstate(() { _active = newvalue; }); } @override widget build(buildcontext context) { return container( child: tapboxb( active: _active, onchanged: _handletapboxchanged, ), ); } } //------------------------- tapboxb ---------------------------------- // 注意[tapboxb]是无状态部件,所有成员变量使用 final 修饰 class tapboxb extends statelesswidget { // 必须传递onchanged,用于通知父部件 tapboxb({key key, this.active: false, @required this.onchanged}) : super(key: key); final bool active; final valuechanged<bool> onchanged; void _handletap() { // 通知父部件修改 active 的值 onchanged(!active); } widget build(buildcontext context) { return gesturedetector( // 被点击时 ontap: _handletap, child: center( child: text( // active 改变时修改文本的内容 active ? 'active' : 'inactive', ), ), ); } }
混合管理
在这种管理模式下,和父管理子部件的区别是,子部件也需要管理自己的状态,所以子部件也将是有状态部件(区别)。
步骤如下:
- 创建一个【有状态部件】作为子部件,构造函数中需要接收状态的值和状态改变时的回调函数
- 为子部件定义子部件内部的状态(多的一步)
- 创建一个有状态部件作为父部件,并定义需要管理的状态
- 在父部件中创建子部件,并绑定状态和回调事件
import 'package:flutter/material.dart'; //---------------------------- parentwidget ---------------------------- class parentwidget extends statefulwidget { @override _parentwidgetstate createstate() => _parentwidgetstate(); } class _parentwidgetstate extends state<parentwidget> { bool _active = false; void _handletapboxchanged(bool newvalue) { setstate(() { _active = newvalue; }); } @override widget build(buildcontext context) { return container( child: tapboxc( active: _active, onchanged: _handletapboxchanged, ), ); } } //----------------------------- tapboxc ------------------------------ class tapboxc extends statefulwidget { tapboxc({key key, this.active: false, @required this.onchanged}) : super(key: key); final bool active; final valuechanged<bool> onchanged; _tapboxcstate createstate() => _tapboxcstate(); } class _tapboxcstate extends state<tapboxc> { /// [tapboxc]管理内部的边框是否高亮,通过状态[_highlight]来修改 bool _highlight = false; void _handletapdown(tapdowndetails details) { setstate(() { _highlight = true; }); } void _handletapup(tapupdetails details) { setstate(() { _highlight = false; }); } void _handletapcancel() { setstate(() { _highlight = false; }); } void _handletap() { // 通知父组件 widget.onchanged(!widget.active); } widget build(buildcontext context) { return gesturedetector( // onxxx都是事件处理 ontapdown: _handletapdown, ontapup: _handletapup, ontap: _handletap, ontapcancel: _handletapcancel, child: container( child: center( child: text(widget.active ? 'active' : 'inactive', style: textstyle(fontsize: 32.0, color: colors.white)), ), width: 200.0, height: 200.0, decoration: boxdecoration( color: widget.active ? colors.lightgreen[700] : colors.grey[600], // 边框是否高亮显示 border: _highlight ? border.all( color: colors.teal[700], width: 10.0, ) : null, ), ), ); } }
总结
以上所述是小编给大家介绍的flutter部件内部状态管理小结之实现vue的v-model功能,希望对大家有所帮助
上一篇: 完美解决Python 2.7不能正常使用pip install的问题
下一篇: 那是照相馆