欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Flutter部件内部状态管理小结之实现Vue的v-model功能

程序员文章站 2022-11-20 08:54:55
flutter部件内部状态管理 本文是 flutter 部件内部状态管理的小结,从部件的基础开始,到部件的状态管理,并且在过程中实现一个类似 vue...

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',
 ),
 ),
 );
 }
}

混合管理

在这种管理模式下,和父管理子部件的区别是,子部件也需要管理自己的状态,所以子部件也将是有状态部件(区别)。

步骤如下:

  1. 创建一个【有状态部件】作为子部件,构造函数中需要接收状态的值和状态改变时的回调函数
  2. 为子部件定义子部件内部的状态(多的一步)
  3. 创建一个有状态部件作为父部件,并定义需要管理的状态
  4. 在父部件中创建子部件,并绑定状态和回调事件
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功能,希望对大家有所帮助