from_vue3_to_flutter_getx

[soc]

对比网站

component-party

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容