做为一个开发人员,选择一款得心应手的开发框架对提高生产效率和愉悦编码体验是尤为重要的。近两年我从后端开发转向web端开发,开发重心也由之前数据层面转变为现今的展现层面。web端有很多出色的开发框架,Vue.js、React、Angular、Ember.js 等等都深受广大web端开发的喜爱,也都是非常不错的选择,挑来选去在众多开发框架中选择了Angular。
Angular
只所以选择Angular是因为Angular中的很多理念对一个曾经的后端开发来说并不陌生,甚至还会带有几分亲切,Module、依赖注入、守卫、provider等等,每一项都那么熟悉。但是,除了这些最能吸引到我的更是她优雅的数据绑定功能,Angular的数据绑定“语法”非常简洁、明了,就算是新手,扫几眼也就懂了。使用起来也非常方便,几乎就像操作js原生对象,简单易懂。
Angular中的数据绑定
<h2>{{ title }}</h2>
<div *ngIf="status === 1">hello world!</div>
数据绑定是Angular的核心,它可以大大简化开发人员对页面dom树控制的复杂度,使我们可以从原本复杂的页面操控中解脱出来。其实不光是Angular,Vue.js、React、Ember.js 等框架也都有类似实现,业界将这种通过数据绑定驱动视图变化的模式称之为 MVVM
(https://zh.wikipedia.org/wiki/MVVM)。
Flutter
最近在学习Flutter,要构建一个Flutter app,大部分工作就是构建各种widget树(UI),widget树结构其实很像html里的dom树,对于web端开发人员来说并不难理解。但是上手之后就会发现,对于widget树的操控仿佛回到了html中的getElementById时代,即使是很简单的widget变更操作,也都需要开发人员手动管理非常多的逻辑代码。如果碰到多个widget变更的复杂场景,摆在开发人员面前的必然是更加繁重的工作量。如果要终日以这样的方式写Flutter代码,估计我撑不过三天,这对于我这样懒惯了的Angular开发来说是没法接受的!〜
Flutter中实现widget变更大概需要如下几个步骤
- 创建一个从
StatefulWidget
继承的类
- 创建一个对应的
Widget
的 state 类
- 编写 widget 变更逻辑,并最终使用 setState() 更新到UI
Flutter MVVM
既然Flutter中的widget树和html里的dom树很像,而web端各大框架又都能以数据绑定(MVVM)来简化对dom树的控制操作,那么 在Flutter中能不能像web框架那样通过数据绑定(MVVM)来简化对widget树的操控呢? 带着这样的疑问,在我家二狗还没睡醒的清晨,尝试着实现了一个Flutter的MVVM。
它大概可以帮你解决Flutter开发过程中如下几个问题
- 我有选择困难症,我不想选择用StatelessWidget还是StatefulWidget。
- 我是一个懒人,当我变更widget(UI显示)时,我不想每次都手动 setState
- 我有洁癖,当我开发功能时,我希望各个环节职能能够更加清晰。
- 最重要的,我希望我能从复杂的widget树结构控制中解脱出来。
什么?说了这么多,不如看几行代码?
在项目中使用她需要如下几个步骤
1. 在项目中添加依赖
找到项目中 pubspec.yaml
文件, 并在 dependencies
部分加入下面内容
mvvm: ^0.1.3
2. 添加包引用
在代码页中加入
import 'package:mvvm/mvvm.dart';
3. 创建视图模型(ViewModel)
视图模型类需从 ViewModel
类继承, 并在构造方法中使用 propertyValue
方法创建需要绑定支持的属性
import 'package:mvvm/mvvm.dart';
import 'dart:async';
// define ViewModel
class Demo1ViewModel extends ViewModel {
Demo1ViewModel() {
// define bindable
propertyValue<DateTime>("time", initial: DateTime.now());
// start timer
start();
}
start() {
Timer.periodic(const Duration(seconds: 1), (_) {
// call setValue
setValue<DateTime>("time", DateTime.now());
});
}
}
与 propertyValue
类似的创建属性的方法还有 propertyAdaptive
、propertyAsync
用法详见源码中示例
4. 创建视图(View)
视图类需从 View
类继承, 并指定使用刚刚创建的视图模型。重写 Widget BuildCore(BuildContext)
方法,并在方法内使用 $
(ViewContext) 和 $Model
(ViewModel) 辅助属性构建视图 Widget
import 'package:mvvm/mvvm.dart';
import 'package:flutter/widgets.dart';
// define View
class Demo1 extends View<Demo1ViewModel> {
// call super
Demo1() : super(Demo1ViewModel());
@override
Widget buildCore(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 100),
padding: EdgeInsets.all(40),
child: Column(children: [
// binding
$.watchFor("time",
builder: $.builder1((t) => Text(
"${t.hour}:${t.minute}:${t.second}",
textDirection: TextDirection.ltr))),
// binding
$.$ifFor("time",
builder: $.builder0(
() => Text("hello world!", textDirection: TextDirection.ltr)),
valueHandle: (t) => t.second % 2 == 0)
]));
}
}
与 $.watchFor(..)
类似的还有 $.watch(..)
、$.if(..)
、$.cond(..)
、$.condFor(..)
、$.switch(..)
、$.switchFor(..)
等,后续还可以扩展更多,用法详见源码中示例
5. 应用视图
// run
void main() => runApp(Demo1());
web端开发的小伙伴们是不是觉的 $.watchFor(..)
、$.ifFor(..)
等语法能更亲切一些呢?其实这些就是前边提到的数据绑定语法的类似实现了。
在这个Flutter的MVVM实现中,我们将原有混在一起的widget树和逻辑数据,拆分为视图逻辑(ViewModel)与视图展示(View)两部分,并通过数据绑定在两者之间建立关联,最终用视图逻辑(ViewModel)结合数据绑定器驱动视图(widget树)变化。可以看到示例中我们在 View
类中能更加专注的处理视图展示,所有与视图逻辑相关的数据操作都由 ViewModel
来管理,在职责上有着清晰的划分界限。
最后
MVVM模式由来已久,在很多展现层框架中都有应用,并且深受开发人员喜爱。这个Flutter的实现还很简陋,还有很多可以扩展的地方,但相信她能越来越完善,也希望她能给你带来编码的快乐,感谢阅读!
她是不是能拉近你与app端开发的距离呢?快来尝试一下吧,期待你的答案。。
相关链接
相关推荐
【flutter-mvvm-provider-demo】是一个基于Flutter框架的项目示例,展示了如何在移动应用开发中运用MVVM(Model-View-ViewModel)架构模式,并结合Provider作为状态管理工具。这个项目适用于Android、iOS平台,同时...
Ionic 是一个基于 Cordova 的移动跨平台APP开发框架,优点是漂亮的界面,追求性能,专注原生,免费开源,Angular JS MVVM 开发理念,数据双向绑定,继承自 Cordova,可以使用 Cordova 的插件。但是,它也有缺点,如 ...
Flutter是由谷歌开发的开源UI软件开发工具包,它允许开发者通过单一的代码库来创建跨平台的应用程序。Flutter不仅支持iOS和Android平台,还可以编译到Web和桌面操作系统(例如Windows、macOS和Linux)上运行。...
- **kjb_lei_sign-master**:这个文件名很可能指的是该APP的源码仓库,开发者可以下载源码,根据自身需求进行二次开发,例如添加新的功能模块,调整UI设计,优化性能等。 - **版本控制**:使用Git进行版本控制,...
【压缩包子文件的文件名称列表】:提到的“赚钱项目”可能是指包含在ZIP文件中的一个具体项目或者章节,它可能探讨了如何通过iOS应用开发来实现盈利的策略,或者是介绍了一个能够帮助开发者创收的开源项目。...
1. **应用框架**:一个app范本往往基于某种应用框架,例如React Native、Flutter或Ionic等。这些框架提供了跨平台的开发能力,允许开发者使用一套代码库来构建iOS和Android应用。框架通常包含了一系列预定义的组件、...
8. 开源App示例:如Clean Architecture、MVP、MVVM架构的实战项目,供开发者参考学习。 每个项目通常会附带详细的README文件,介绍项目背景、功能特性、使用方法、依赖项以及如何贡献代码。这为开发者提供了学习新...
一个用于学校管理的开源项目 状态管理:+ MVVM(模型-视图-(视图)模型)体系结构 注意:此应用程序尚未完全开发,仍然存在很多错误,我仍在研究中(目前,父母,老师和学生的所有登录数据均已手动添加到firestore...
"安卓开发-企业级discuz论坛安卓苹果客户端.zip.zip" 这个标题揭示了我们讨论的主题是关于安卓(Android)和苹果(iOS)两大移动平台上的应用开发,具体来说是一个针对企业级的Discuz! 论坛客户端。Discuz! 是一个...
总的来说,“datizhuanqian”开源项目为开发者提供了一个实践和学习移动应用开发的鲜活案例,尤其对于想要深入了解答题赚钱模式的开发者来说,这是一个不可多得的资源。通过研究其代码,我们可以提升对Android或iOS...
Flutter是由Google推出的开源UI工具包,旨在帮助开发者快速构建高性能、高保真度的跨平台应用,支持Android和iOS,同时也正在扩展到Web和桌面平台。 在这款应用中,Dart语言扮演了核心角色。Dart是Google开发的一种...
"联想Android开发工程师面试题(实用1).zip" 这个标题表明这是一个与联想公司Android开发工程师面试相关的资料包。通常这样的资源会包含一系列的问题和可能的解答,旨在帮助求职者准备面试,了解面试官可能关注的技术...
Router 是指应用程序中的路由机制,负责将用户从一个页面路由到另一个页面。在混合应用平台中,Router 可以提供给用户一个统一的应用体验。 Page Features Page Features 是指应用程序中的页面特性,包括页面布局...
"AndroidKnowledgeSystem"是一个开源项目,它提供了一个最全面的Android高级路线知识图谱,旨在帮助开发者系统性地规划和深化Android技术栈。这个资源集合不仅包括了理论知识,还包含了丰富的实践资料,对于想要在...
Flutter是Google推出的一个开源UI工具包,旨在帮助开发者快速、高效地为Android和iOS平台构建高质量的原生应用。Dart是一种面向对象的、现代的、强类型的编程语言,它提供了简洁的语法和高性能,是Flutter的主要编程...
标题“devlin-mobileapps”可能指的是一个开源项目或者教程,专注于移动应用开发,可能是由Devlin主导或创建的。由于没有具体的描述,我们只能根据常见的移动应用开发实践来推测可能涉及的知识点。以下是一些可能的...
通过深入研究这个源码,开发者不仅可以学习到如何构建一个功能完备的企业级论坛应用,还能了解到Android开发的最佳实践和前沿技术。同时,这也为自定义和扩展论坛功能提供了基础,以适应不同企业的特定需求。
开源Github客户端App,更好的体验,更丰富的功能,有望更好的日常管理和维护个人Github,提供更好更方便的驾车体验Σ( ̄。 ̄ ノ)ノ。同款Weex版本:https:github.comCarGuoGSYGithubAppWeex,同款React本机版本:...
【标题】"maimai:脉脉社交APP原始码"所指的,是社交应用“脉脉”的源代码公开,这在IT行业中属于一个典型的开源项目。脉脉是一款专为职场人士设计的社交平台,其核心功能包括职业人脉拓展、行业资讯分享、招聘信息...
"FindStuff:行动应用程式原始码-Mobile app source code" 是一个关于移动应用程序源代码的项目,从标题可以推测,这可能是一个开源的应用程序,允许开发者查看、学习甚至修改其内部工作原理。源代码通常是程序员之间...