flutter架 构项目基础

This commit is contained in:
崔宝新
2026-09-04 15:22:20 +08:00
parent 70967229d0
commit 0c5aee59c0
265 changed files with 35484 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
# 【Demo】TextField 输入框(登录表单)
> 源文件:`lib/pages/demo/input_demo.dart` | 分类:基础布局
> 一句话:输入框 + 密码"小眼睛"切换 —— 表单最基础的零件。
---
## 一、这个 Demo 解决什么问题
做一个最简单的登录表单:手机号输入框 + 密码输入框(可切换明文/密文)。
核心是搞懂 **TextEditingController** 的用法——Flutter 里输入框不叫"双向绑定",
而是"控制器持有值,代码里随时读写"。
---
## 二、怎么运行 / 演示内容
```dart
runApp(const MaterialApp(home: InputDemoPage()));
```
- 手机号框:弹数字键盘(`keyboardType: TextInputType.phone`);
- 密码框:右侧眼睛图标切换密文/明文;
- 点"登录":控制台打印两个输入框的内容。
---
## 三、核心知识点(新手向)
### 1. 对照 Vue 的 v-model
| Vue | Flutter |
|---|---|
| `v-model="phone"` | `TextEditingController` + `controller.text` |
| 框架自动同步 | 手动 `controller.text` 读写 |
Flutter 没有隐式的双向绑定:`controller.text` 改了就同步到输入框,
输入框内容变了 `controller.text` 也会读到 —— 但**没有"响应式"**:
想根据输入内容实时刷新 UI(如"输入满 11 位才能点登录"),要自己 `addListener` 或 `setState`。
### 2. TextEditingController 生命周期(红线)
```dart
final TextEditingController _userCtrl = TextEditingController();
@override
void dispose() {
_userCtrl.dispose(); // 必须在 dispose 释放,防内存泄漏
super.dispose();
}
```
> 凡是用 `Controller` 命名的东西(Text/Scroll/Animation/Tab),基本都要 dispose。
### 3. 密码眼睛切换
```dart
bool _showPwd = false;
TextField(
controller: _pwdCtrl,
obscureText: !_showPwd, // 密文/明文由状态决定
decoration: InputDecoration(
labelText: "密码",
prefixIcon: const Icon(Icons.lock),
border: const OutlineInputBorder(),
suffixIcon: IconButton(
icon: Icon(_showPwd ? Icons.visibility : Icons.visibility_off),
onPressed: () => setState(() => _showPwd = !_showPwd),
),
),
)
```
### 4. InputDecoration 常用参数
- `labelText`:浮动标签(聚焦时缩小浮到边框上);
- `hintText`:灰色占位提示;
- `prefixIcon`:左侧图标;`suffixIcon`:右侧(按钮/图标);
- `border: OutlineInputBorder()`:带边框的圆角样式(默认是下划线)。
---
## 四、关键代码剖析
```dart
// 读取输入内容(点登录时)
String user = _userCtrl.text;
String pwd = _pwdCtrl.text;
if (kDebugMode) {
print("账号:$user,密码:$pwd"); // kDebugMode:只在 debug 包打印
}
```
要点:
- `kDebugMode`(来自 `package:flutter/foundation.dart`)保证打印不会出现在 release 包;
- 真实项目里读取后要走校验(见 [form_demo.md](form_demo.md))和登录接口(见 [dio_demo.md](dio_demo.md))。
---
## 五、踩坑记录
1. **Scaffold 没有 `padding` 参数!** 外间距要写在 body 的 `Padding` 上(新手必踩)。
2. `controller` 忘了 dispose → 内存泄漏(Flutter 分析器会提示)。
3. `suffixIcon` 用 `IconButton` 而不要用普通 `Icon` 包 `GestureDetector` —— IconButton 自带点击区域和涟漪反馈。
4. 想"输入即校验"别自己写监听,直接上 Form(见 form_demo)。
---
## 六、扩展思考
- 进阶校验:`TextFormField` + `validator`([form_demo.md](form_demo.md))—— 本项目表单校验全家桶;
- 真实登录页还要:防重复提交、加载动画、错误提示、密码安全存储(本项目用 flutter_secure_storage,见架构文档存储层);
- 输入法控制:`textInputAction: TextInputAction.next` 让回车键变成"下一项",最后一项变"完成"。