[soc]
对比网站
$ flutter create project_foo
$ cd project_foo
$ flutter pub add get
$ flutter run
响应式
声明
vue3
<script setup>
import { ref } from "vue";
const name = ref("张三");
</script>
<template>
<h1>你好 {{ name }}</h1>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
// 使用 GetMaterialApp 替代 MaterialApp
home: HomeScreen(),
);
}
}
class NameController extends GetxController {
var name = "张三".obs; // 使用 GetX 的响应式变量
void updateName(String newName) {
name.value = newName; // 更新响应式变量
}
}
class HomeScreen extends StatelessWidget {
final NameController controller = Get.put(NameController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GetX 示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text("你好 ${controller.name.value}",
style: const TextStyle(fontSize: 24))), // 使用 Obx 实现响应式更新
const SizedBox(height: 20)
],
),
),
);
}
}
更新
vue3
<script setup>
import { ref } from "vue";
const name = ref("张三");
name.value = "李四";
</script>
<template>
<h1>你好 {{ name }}</h1>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// 主应用入口
void main() {
runApp(MyApp());
}
// 主应用
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "GetX 动态更新示例",
home: HomeScreen(),
);
}
}
// 定义 GetX 控制器
class NameController extends GetxController {
var name = "张三".obs; // 使用 GetX 的响应式变量
void updateName(String newName) {
name.value = newName; // 更新响应式变量
}
}
// 主页面
class HomeScreen extends StatelessWidget {
// 初始化控制器
final NameController controller = Get.put(NameController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GetX 动态更新示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text("你好 ${controller.name.value}",
style: const TextStyle(fontSize: 24))),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 动态更新名字
controller.updateName("李四");
},
child: const Text("更改名字"),
),
],
),
),
);
}
}
计算属性
vue3
<script setup>
import { ref, computed } from "vue";
const count = ref(10);
const doubleCount = computed(() => count.value * 2);
</script>
<template>
<div>{{ doubleCount }}</div>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "GetX Computed 示例",
home: HomeScreen(),
);
}
}
// 控制器
class NameController extends GetxController {
var count = 10.obs; // 基础响应式变量
// Getter 方法,计算
int get doubleCount => count.value * 2;
// 增加计数的方法
void increment() {
count.value += 1;
}
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final NameController controller = Get.put(NameController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GetX Computed 示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text("Count: ${controller.count.value}",
style: const TextStyle(fontSize: 24))),
Obx(() => Text("Double Count: ${controller.doubleCount}",
style: const TextStyle(fontSize: 24))),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 增加计数
controller.increment();
},
child: const Text("Increment"),
),
],
),
),
);
}
}
最简模板
vue3
<template>
<h1>这是一段示例文字</h1>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 示例"),
),
body: const Center(
child: Text(
"这是一段示例文字",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
);
}
}
样式
vue3
<template>
<h1 class="title">
我是红色的
</h1>
<button style="font-size: 10rem">
我是一个按钮
</button>
</template>
<style scoped>
.title {
color: red;
}
</style>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 样式示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 样式示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 红色标题文本
const Text(
"我是红色的",
style: TextStyle(
color: Colors.red,
fontSize: 24, // 字体大小
fontWeight: FontWeight.bold, // 字体加粗
),
),
const SizedBox(height: 20), // 添加间距
// 自定义样式的按钮
ElevatedButton(
onPressed: () {
// 按钮点击事件
Get.snackbar("按钮点击", "你点击了按钮!");
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, // 按钮背景颜色
foregroundColor: Colors.white, // 按钮文字颜色
padding: const EdgeInsets.all(20), // 按钮内边距
),
child: const Text(
"我是一个按钮",
style: TextStyle(fontSize: 20), // 字体大小
),
),
],
),
),
);
}
}
DOM循环
vue3
<script setup>
const colors = ["红", "绿", "蓝"];
</script>
<template>
<ul>
<li
v-for="color in colors"
:key="color"
>
{{ color }}
</li>
</ul>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 列表示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
// 定义颜色列表
final List<String> colors = ["红", "绿", "蓝"];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 列表示例"),
),
body: ListView.builder(
itemCount: colors.length, // 列表项的数量
itemBuilder: (context, index) {
return ListTile(
title: Text(colors[index]), // 显示颜色名称
);
},
),
);
}
}
点击事件
vue3
<script setup>
import { ref } from "vue";
const count = ref(0);
function incrementCount() {
count.value++;
}
</script>
<template>
<p>计数器: {{ count }}</p>
<button @click="incrementCount">
+1
</button>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 计数器示例",
home: HomeScreen(),
);
}
}
// 控制器
class CountController extends GetxController {
var count = 0.obs; // 响应式变量
void incrementCount() {
count.value++; // 更新响应式变量
}
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final CountController controller = Get.put(CountController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 计数器示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(
"计数器: ${controller.count.value}", // 使用 Obx 实现响应式更新
style: const TextStyle(fontSize: 24),
)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
controller.incrementCount(); // 调用控制器中的方法
},
child: const Text("+1"),
),
],
),
),
);
}
}
DOM引用
vue3
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter Focus 示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late FocusNode _focusNode; // 定义 FocusNode
@override
void initState() {
super.initState();
_focusNode = FocusNode(); // 初始化 FocusNode
}
@override
void dispose() {
_focusNode.dispose(); // 销毁 FocusNode
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter Focus 示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
focusNode: _focusNode, // 将 FocusNode 绑定到 TextField
decoration: const InputDecoration(
hintText: "请输入内容",
border: OutlineInputBorder(),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
_focusNode.requestFocus(); // 请求焦点
},
child: const Text("聚焦输入框"),
),
],
),
),
);
}
}
条件渲染
vue3
<script setup>
import { ref, computed } from "vue";
const TRAFFIC_LIGHTS = ["红灯", "黄灯", "绿灯"];
const lightIndex = ref(0);
const light = computed(() => TRAFFIC_LIGHTS[lightIndex.value]);
function nextLight() {
lightIndex.value = (lightIndex.value + 1) % TRAFFIC_LIGHTS.length;
}
</script>
<template>
<button @click="nextLight">
下一个灯
</button>
<p>现在亮着的是: {{ light }}</p>
<p>
你应该
<span v-if="light === '红灯'">停下</span>
<span v-else-if="light === '黄灯'">慢行</span>
<span v-else-if="light === '绿灯'">赶紧走</span>
</p>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 交通灯示例",
home: TrafficLightScreen(),
);
}
}
class TrafficLightController extends GetxController {
final TRAFFIC_LIGHTS = ["红灯", "黄灯", "绿灯"];
final lightIndex = 0.obs; // 响应式变量
final light = ''.obs; // 响应式变量
final instruction = ''.obs; // 响应式变量
@override
void onInit() {
super.onInit();
_updateLight();
}
void nextLight() {
lightIndex.value = (lightIndex.value + 1) % TRAFFIC_LIGHTS.length;
_updateLight();
}
void _updateLight() {
light.value = TRAFFIC_LIGHTS[lightIndex.value];
switch (light.value) {
case "红灯":
instruction.value = "停下";
break;
case "黄灯":
instruction.value = "慢行";
break;
case "绿灯":
instruction.value = "赶紧走";
break;
}
}
}
class TrafficLightScreen extends StatelessWidget {
final TrafficLightController controller = Get.put(TrafficLightController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("交通灯示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: controller.nextLight,
child: const Text("下一个灯"),
),
const SizedBox(height: 20),
Obx(() => Text(
"现在亮着的是: ${controller.light.value}",
style: const TextStyle(fontSize: 20),
)),
const SizedBox(height: 20),
Obx(() => Text(
"你应该 ${controller.instruction.value}",
style: const TextStyle(fontSize: 20),
)),
],
),
),
);
}
}
生命周期
组件加载时
<script setup>
import { ref, onMounted } from "vue";
const pageTitle = ref("");
onMounted(() => {
pageTitle.value = document.title;
});
</script>
<template>
<p>页面标题: {{ pageTitle }}</p>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 页面标题示例",
home: HomeScreen(),
);
}
}
class PageTitleController extends GetxController {
var pageTitle = "".obs; // 响应式变量
@override
void onInit() {
super.onInit();
pageTitle.value = "初始页面标题"; // 初始化页面标题
}
void updateTitle(String newTitle) {
pageTitle.value = newTitle; // 更新页面标题
}
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final PageTitleController controller = Get.put(PageTitleController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 页面标题示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(
"页面标题: ${controller.pageTitle.value}",
style: const TextStyle(fontSize: 20),
)),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
controller.updateTitle("新的页面标题");
},
child: const Text("更新页面标题"),
),
],
),
),
);
}
}
组件卸载时
vue3
<script setup>
import { ref, onUnmounted } from "vue";
const time = ref(new Date().toLocaleTimeString());
const timer = setInterval(() => {
time.value = new Date().toLocaleTimeString();
}, 1000);
onUnmounted(() => {
clearInterval(timer);
});
</script>
<template>
<p>当前时间: {{ time }}</p>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'dart:async'; // 确保导入 dart:async 库
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 时间示例",
home: TimeScreen(),
);
}
}
class TimeController extends GetxController {
var time = "".obs; // 响应式变量
late Timer _timer; // 定时器
@override
void onInit() {
super.onInit();
time.value = DateTime.now().toString(); // 初始化时间
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
time.value = DateTime.now().toString(); // 每秒更新时间
});
}
@override
void onClose() {
super.onClose();
_timer.cancel(); // 清理定时器
}
}
class TimeScreen extends StatelessWidget {
final TimeController controller = Get.put(TimeController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter 时间示例"),
),
body: Center(
child: Obx(() => Text(
"当前时间: ${controller.time.value}",
style: const TextStyle(fontSize: 24),
)),
),
);
}
}
组件组合
组件Props传参
vue3
<script setup>
const props = defineProps({
name: {
type: String,
required: true,
default: "",
},
age: {
type: Number,
required: true,
default: null,
},
favouriteColors: {
type: Array,
required: true,
default: () => [],
},
isAvailable: {
type: Boolean,
required: true,
default: false,
},
});
</script>
<template>
<p>My name is {{ props.name }}!</p>
<p>My age is {{ props.age }}!</p>
<p>My favourite colors are {{ props.favouriteColors.join(", ") }}!</p>
<p>I am {{ props.isAvailable ? "available" : "not available" }}</p>
</template>
<script setup>
const props = defineProps({
name: {
type: String,
required: true,
default: "",
},
age: {
type: Number,
required: true,
default: null,
},
favouriteColors: {
type: Array,
required: true,
default: () => [],
},
isAvailable: {
type: Boolean,
required: true,
default: false,
},
});
</script>
<template>
<p>My name is {{ props.name }}!</p>
<p>My age is {{ props.age }}!</p>
<p>My favourite colors are {{ props.favouriteColors.join(", ") }}!</p>
<p>I am {{ props.isAvailable ? "available" : "not available" }}</p>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter UserProfile 示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter UserProfile 示例"),
),
body: const Center(
child: UserProfile(
name: "张三",
age: 20,
favouriteColors: ["green", "blue", "red"],
isAvailable: true,
),
),
);
}
}
// -----------------------------------------------------------------------------
// import 'package:get/get.dart';
class UserProfile extends StatelessWidget {
// 定义构造函数参数
final String name;
final int age;
final List<String> favouriteColors;
final bool isAvailable;
const UserProfile({
super.key,
required this.name,
required this.age,
required this.favouriteColors,
required this.isAvailable,
});
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("My name is $name!"),
Text("My age is $age!"),
Text("My favourite colors are ${favouriteColors.join(", ")}!"),
Text("I am ${isAvailable ? "available" : "not available"}"),
],
);
}
}
向父组件emit事件
vue3
<script setup>
import { ref } from "vue";
import AnswerButton from "./AnswerButton.vue";
let isHappy = ref(true);
function onAnswerNo() {
isHappy.value = false;
}
function onAnswerYes() {
isHappy.value = true;
}
</script>
<template>
<p>你快乐吗?</p>
<AnswerButton
@yes="onAnswerYes"
@no="onAnswerNo"
/>
<p style="font-size: 50px">
{{ isHappy ? "😀" : "😥" }}
</p>
</template>
<script setup>
const emit = defineEmits(["yes", "no"]);
function clickYes() {
emit("yes");
}
function clickNo() {
emit("no");
}
</script>
<template>
<button @click="clickYes">
是的!
</button>
<button @click="clickNo">
不是!
</button>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter 状态管理示例",
home: HomeScreen(),
);
}
}
class IsHappyController extends GetxController {
var isHappy = true.obs; // 响应式变量
void setHappy(bool value) {
isHappy.value = value; // 更新状态
}
}
class HomeScreen extends StatelessWidget {
final IsHappyController controller = Get.put(IsHappyController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("你快乐吗?"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("你快乐吗?", style: TextStyle(fontSize: 24)),
AnswerButton(
onYes: () => controller.setHappy(true),
onNo: () => controller.setHappy(false),
),
const SizedBox(height: 20),
Obx(() => Text(
controller.isHappy.isTrue ? "😀" : "😥",
style: const TextStyle(fontSize: 50),
)),
],
),
),
);
}
}
// -----------------------------------------------------------------------------
// import 'package:flutter/material.dart';
class AnswerButton extends StatelessWidget {
final VoidCallback onYes;
final VoidCallback onNo;
const AnswerButton({
super.key,
required this.onYes,
required this.onNo,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: onYes,
child: const Text("是的!"),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: onNo,
child: const Text("不是!"),
),
],
);
}
}
Slot插槽
vue3
<script setup>
import FunnyButton from "./FunnyButton.vue";
</script>
<template>
<FunnyButton> 点我! </FunnyButton>
</template>
<template>
<button
style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
"
>
<slot />
</button>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter FunnyButton 示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter FunnyButton 示例"),
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FunnyButton(child: Text("点我!", style: TextStyle(fontSize: 30))),
SizedBox(height: 20),
FunnyButton(), // 显示默认内容
],
),
),
);
}
}
// -----------------------------------------------------------------------------
// import 'package:flutter/material.dart';
class FunnyButton extends StatelessWidget {
final Widget? child; // 接收外部传入的子组件
const FunnyButton({super.key, this.child});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {}, // 空实现,按钮点击事件
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black.withOpacity(0.4),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
textStyle: const TextStyle(fontSize: 30),
side: const BorderSide(color: Colors.white, width: 2),
shadowColor: Colors.black.withOpacity(0.4),
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: child ?? const Text("默认内容"), // 如果没有传入子组件,则显示默认内容
);
}
}
Slot插槽内容
vue3
<script setup>
import FunnyButton from "./FunnyButton.vue";
</script>
<template>
<FunnyButton />
<FunnyButton> 这是传到slot的内容! </FunnyButton>
</template>
<template>
<button
style="
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding: 10px 20px;
font-size: 30px;
border: 2px solid #fff;
margin: 8px;
transform: scale(0.9);
box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
outline: 0;
"
>
<slot>
<span>默认slot内容</span>
</slot>
</button>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter FunnyButton 示例",
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter FunnyButton 示例"),
),
body: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FunnyButton(), // 显示默认内容
FunnyButton(
child: Text("这是传到slot的内容!", style: TextStyle(fontSize: 30)),
),
],
),
),
);
}
}
// -----------------------------------------------------------------------------
// import 'package:flutter/material.dart';
class FunnyButton extends StatelessWidget {
final Widget? child; // 接收外部传入的子组件
const FunnyButton({super.key, this.child});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {}, // 空实现,按钮点击事件
style: ElevatedButton.styleFrom(
backgroundColor: Colors.black.withOpacity(0.4),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
textStyle: const TextStyle(fontSize: 30),
side: const BorderSide(color: Colors.white, width: 2),
shadowColor: Colors.black.withOpacity(0.4),
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: child ?? const Text("默认slot内容"), // 如果没有传入子组件,则显示默认内容
);
}
}
上下文
vue3
<script setup>
import { ref, provide } from "vue";
import UserProfile from "./UserProfile.vue";
const user = ref({
id: 1,
username: "abcdefg",
email: "abcdefg@example.com",
});
function updateUsername(username) {
user.value.username = username;
}
provide("user", { user, updateUsername });
</script>
<template>
<h1>欢迎回来, {{ user.username }}</h1>
<UserProfile />
</template>
<script setup>
import { inject } from "vue";
const { user, updateUsername } = inject("user");
</script>
<template>
<div>
<h2>我的简介</h2>
<p>用户名: {{ user.username }}</p>
<p>邮箱: {{ user.email }}</p>
<button @click="() => updateUsername('李四')">
更新用户名为 李四
</button>
</div>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class User {
int id;
String username;
String email;
User({required this.id, required this.username, required this.email});
}
class UserController extends GetxController {
var user = User(id: 1, username: "abcdefg", email: "abcdefg@example.com").obs;
void updateUsername(String newUsername) {
user.update((val) {
val?.username = newUsername;
});
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 示例",
home: HomeScreen(),
initialBinding: BindingsBuilder(() {
Get.put(UserController()); // 初始化控制器
}),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("欢迎回来, ${Get.find<UserController>().user.value.username}"),
),
body: Center(
child: UserProfile(),
),
);
}
}
//------------------------------------------------------------------------------
// import 'package:flutter/material.dart';
// import 'package:get/get.dart';
class UserProfile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final userController = Get.find<UserController>();
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("我的简介", style: TextStyle(fontSize: 24)),
Obx(() => Text("用户名: ${userController.user.value.username}",
style: const TextStyle(fontSize: 20))),
Obx(() => Text("邮箱: ${userController.user.value.email}",
style: const TextStyle(fontSize: 20))),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
userController.updateUsername("李四");
},
child: const Text("更新用户名为 李四"),
),
],
);
}
}
表单输入
输入框
vue
<script setup>
import { ref } from "vue";
const text = ref("这是一段示范文字");
</script>
<template>
<p>{{ text }}</p>
<input v-model="text">
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 示例",
home: HomeScreen(),
);
}
}
class TextController extends GetxController {
var text = "这是一段示范文字".obs; // 响应式变量
final TextEditingController textEditingController = TextEditingController();
@override
void onInit() {
super.onInit();
textEditingController.text = text.value; // 初始化文本内容
textEditingController.addListener(() {
text.value = textEditingController.text; // 更新响应式变量
});
}
@override
void onClose() {
textEditingController.dispose(); // 销毁控制器
super.onClose();
}
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final TextController controller = Get.put(TextController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter GetX 示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(
controller.text.value,
style: const TextStyle(fontSize: 24),
)),
const SizedBox(height: 20),
TextField(
controller: controller.textEditingController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: "请输入内容",
),
),
],
),
),
);
}
}
复选框
vue3
<script setup>
import { ref } from "vue";
const isAvailable = ref(true);
</script>
<template>
<input
id="is-available"
v-model="isAvailable"
type="checkbox"
>
<label for="is-available">这是一个checkbox</label>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 示例",
home: HomeScreen(),
);
}
}
class CheckboxController extends GetxController {
var isAvailable = true.obs; // 响应式变量
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final CheckboxController controller = Get.put(CheckboxController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter GetX 示例"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Checkbox(
value: controller.isAvailable.value,
onChanged: (value) {
controller.isAvailable.value = value ?? false;
},
)),
const Text("这是一个checkbox"),
],
),
),
);
}
}
单选框
vue3
<script setup>
import { ref } from "vue";
const picked = ref("red");
</script>
<template>
<div>你选择了: {{ picked }}</div>
<input
id="blue-pill"
v-model="picked"
type="radio"
value="blue"
>
<label for="blue-pill">蓝色</label>
<input
id="red-pill"
v-model="picked"
type="radio"
value="red"
>
<label for="red-pill">红色</label>
</template>
flutter_getx
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 示例",
home: HomeScreen(),
);
}
}
class RadioController extends GetxController {
var picked = "red".obs; // 响应式变量
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final RadioController controller = Get.put(RadioController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter GetX 示例"),
),
body: Center(
child: Obx(
() => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"你选择了: ${controller.picked.value}",
style: const TextStyle(fontSize: 24),
),
RadioListTile(
title: const Text("蓝色"),
value: "blue",
groupValue: controller.picked.value,
onChanged: (value) {
controller.picked.value = value!;
},
),
RadioListTile(
title: const Text("红色"),
value: "red",
groupValue: controller.picked.value,
onChanged: (value) {
controller.picked.value = value!;
},
),
],
),
)),
);
}
}
选择器
vue3
<script setup>
import { ref } from "vue";
const selectedColorId = ref(2);
const colors = [
{ id: 1, text: "红" },
{ id: 2, text: "蓝" },
{ id: 3, text: "绿" },
{ id: 4, text: "灰", isDisabled: true },
];
</script>
<template>
<select v-model="selectedColorId">
<option
v-for="color in colors"
:key="color.id"
:value="color.id"
:disabled="color.isDisabled"
>
{{ color.text }}
</option>
</select>
</template>
flutter_gex
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Flutter GetX 示例",
home: HomeScreen(),
);
}
}
class ColorPickerController extends GetxController {
var selectedColor = ColorModel(id: 2, text: "蓝").obs; // 响应式变量
final List<ColorModel> colors = [
ColorModel(id: 1, text: "红"),
ColorModel(id: 2, text: "蓝"),
ColorModel(id: 3, text: "绿"),
ColorModel(id: 4, text: "灰", isDisabled: true),
];
}
class ColorModel {
final int id;
final String text;
final bool isDisabled;
ColorModel({
required this.id,
required this.text,
this.isDisabled = false,
});
}
class HomeScreen extends StatelessWidget {
// 初始化控制器
final ColorPickerController controller = Get.put(ColorPickerController());
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Flutter GetX 示例"),
),
body: Obx(
() => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"你选择了: ${controller.selectedColor.value.text}",
style: const TextStyle(fontSize: 24),
),
...controller.colors.map((color) => RadioListTile(
title: Text(color.text),
value: color.id,
groupValue: controller.selectedColor.value.id,
onChanged: color.isDisabled
? null
: (value) {
controller.selectedColor.value = color;
},
subtitle: color.isDisabled
? const Text("不可选", style: TextStyle(color: Colors.grey))
: null,
)),
],
),
),
);
}
}