flutter快速入门笔记(1)
本系列不包含 Dart 语法笔记,以掌握 Dart 语法为前提记录。不懂可以百度搜一下Dart快速入门教程,如果你本来就懂js,基本可以一两小时内掌握Dart的语法,比如看下Flutter实战上的Dart简介
启动
flutter 入口文件 main.dart
1 | import 'package:flutter/material.dart'; // 导入md风格组件 |
用 vue3 项目来类比,main.dart 相当于 main.ts/js。runApp 相当于 createApp,MyApp 相当传进 createApp 的根组件,MyHomePage 相当于首页组件。
build 相当于 vue 的 h 或者 createVNode。
flutter 的三棵树
flutter 的三棵树分别是 widget、element、renderObject 树。
用 vue 类比就是 widget->template/jsx、element->虚拟 dom、renderObject->浏览器 dom 树。
可能不太准确,但是适合对 flutter 没有概念的人理解 flutter 整个渲染原理。
StatelessWidget
StatelessWidget 非常好理解,就是一个不可变的,没有状态的 widget,用 vue 类比就是一个.vue 文件里面只写个 template 标签,或者再 import 别的组件然后用到 template 上,而且没用 data 函数定义组件的状态。
比如上面的:
1 | class MyApp extends StatelessWidget { |
相当于 vue 的这样的代码
1 | <template> |
vue3编译器会发现这个div和p是静态的,会编译成_hoisted_1、_hoisted_2 这样的对象,提升到render函数之外,组件实例化时只会构建一次,避免每次执行render都要重新构建。
StatefulWidget
在 flutter 中,Widget 是不可变的,发生变化时需要销毁重建,所以谈不上状态。既然 widget 不可变,那则么实现有状态的 widget 呢,那就是用另一个类帮我们代理生成 widget,每次状态发生改变,那就让代理类生成一个新的 widget。
1 | class MyHomePage extends StatefulWidget { // 其实StatefulWidget和StatelessWidget一样不可变 |
用 vue 来理解:
1 | import { h } from 'vue' |
总结:StatefulWidget 不是万金油,要慎用。Widget 是不可变的,更新则意味着销毁 + 重建(build)。StatelessWidget 是静态的,一旦创建则无需更新;而对于 StatefulWidget 来说,在 State 类中调用 setState 方法更新数据,会触发视图的销毁和重建,也将间接地触发其每个子 Widget 的销毁和重建。
所以 StatefulWidget 要用对地方,比如如果根 Widget 是 StatefulWidget 的话,那么他状态一改变整个 widget 树都要重建,可想而知对性能的影响有多严重。
生命周期
对于这种数据驱动的框架,一般都会提供生命周期函数钩子,像 vue 的 onMounted、onUpdated 等等。State 的生命周期可以分为 3 个阶段:创建(插入视图树)、更新(在视图树中存在)、销毁(从视图树中移除)
创建
State 初始化时会依次执行 :构造方法(上面的 createState 方法) -> initState(像 vue 的 create 过程,生命周期只调用一次,用于设置默认值) -> didChangeDependencies -> build,随后完成页面渲染。
更新
Widget 的状态更新,主要由 3 个方法触发:
- setState:相当于 vue 的 this.xxx = xxx,告诉代理,状态发生了改变,需要去更新视图
- didChangeDependencies:依赖值发生改变,比如 vue 的全局状态改变,如果组件依赖了全局状态,那么也需要去更新视图
- didUpdateWidget:比如父 Widget 状态发生改变,会触发子组件的这个方法,还有热更新也是系统会使用这个方法去更新视图。
一旦这三个方法被调用,Flutter 随后就会销毁老 Widget,并调用 build 方法重建 Widget。
销毁
组件被移除,或是页面销毁的时候,系统会调用 deactivate 和 dispose,来移除或销毁组件。相当于 vue 组件的 unmounte 过程,貌似vue组件卸载和销毁是一个周期内执行完,并提供beforeUnmount和unmounted钩子函数。
几种常见过程的生命周期过程
父 widget 状态变化
父 widget:setState -> build
子 widget: didUpdateWidget -> build
Navigator.push
下一个 Widget:构建方法 -> (initState) -> didChangeDependencies -> build
当前 Widget: deactivate -> build
Navigator.pop
上一个 Widget:deactivate(还是调用 deactivate,设计的有点奇怪) -> build
当前 Widget: deactivate -> dispose
App 生命周期
除了 widget 的生命周期,app 也有生命周期,在 widget 中可以通过WidgetsBindingObserver类来调用 App 的生命周期钩子:
1 | abstract class WidgetsBindingObserver { |
生命周期回调
didChangeAppLifecycleState 回调函数中,有一个参数类型为 AppLifecycleState 的枚举类,这个枚举类是 Flutter 对 App 生命周期状态的封装。它的常用状态包括 resumed、inactive、paused 这三个。
- resumed:可见的,并能响应用户的输入。
- inactive:处在不活动状态,无法处理用户响应。
- paused:不可见并不能响应用户的输入,但是在后台继续活动中。
1 | class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver{ |
以上就是 flutter 的基本知识了,如果会 vue 的话入手 flutter 也是简简单单。如果点赞多就继续写一下布局、组件的快速入门教程XD