Flutter、Vue 3 和 React 在 UI 布局比较

文章目录

  • 前言
    • [🧩 总体设计哲学对比](#🧩 总体设计哲学对比)
    • [🧱 布局方式详解对比](#🧱 布局方式详解对比)
    • [🧭 示例对比:Flex 布局(横向排列)](#🧭 示例对比:Flex 布局(横向排列))
      • [Flutter 示例](#Flutter 示例)
      • [Vue 3 示例(template)](#Vue 3 示例(template))
      • [React 示例(JSX)](#React 示例(JSX))
    • [🧩 场景 1:页面加载时淡入(入场动画)](#🧩 场景 1:页面加载时淡入(入场动画))
      • [Flutter 示例(使用 `AnimatedOpacity`)](#Flutter 示例(使用 AnimatedOpacity))
      • [Vue 3 示例(使用 `<transition>`)](#Vue 3 示例(使用 <transition>))
      • [React 示例(使用 CSS Transition + `useEffect`)](#React 示例(使用 CSS Transition + useEffect))
    • [🧭 场景 2:Tab 切换布局](#🧭 场景 2:Tab 切换布局)
      • [Flutter 示例(`TabBar` + `TabBarView`)](#Flutter 示例(TabBar + TabBarView))
      • [Vue 3 示例(配合 Element Plus 或自定义 Tab)](#Vue 3 示例(配合 Element Plus 或自定义 Tab))
      • [React 示例(配合 Ant Design 或自定义 Tab)](#React 示例(配合 Ant Design 或自定义 Tab))
    • [🎮 场景 3:点击按钮后元素平移动画(Translate 动画)](#🎮 场景 3:点击按钮后元素平移动画(Translate 动画))
      • [Flutter 示例(`AnimatedPositioned` + `Stack`)](#Flutter 示例(AnimatedPositioned + Stack))
      • [Vue 3 示例(CSS 动画 + 绑定 style)](#Vue 3 示例(CSS 动画 + 绑定 style))
      • [React 示例(CSS 绑定 style)](#React 示例(CSS 绑定 style))
    • [📦 响应式/状态管理对比](#📦 响应式/状态管理对比)
    • [🧠 总结对比学习建议](#🧠 总结对比学习建议)

前言

Flutter、Vue 3 和 React 在 UI 布局方式上的设计哲学和实现方式比较


🧩 总体设计哲学对比

项目 Flutter Vue 3 React
编程语言 Dart JavaScript / TypeScript JavaScript / TypeScript
渲染方式 自绘 UI(Skia 引擎) HTML + CSS(DOM) HTML + CSS(DOM)
样式机制 通过 Widget 实现 单文件组件 + CSS(或 scoped CSS) JSX + CSS-in-JS / CSS Modules 等
布局方式 Widget 嵌套布局 基于 HTML 结构和 CSS 布局模型 同 Vue,靠 CSS 控制布局

🧱 布局方式详解对比

对比项 Flutter Vue 3 React
布局核心机制 使用 Widget 树 ,一切皆组件,比如 RowColumnExpanded HTML 标签 + CSS,如 div + flex JSX + CSS(或 styled-components)
样式设置方式 通过属性传递(如 padding: EdgeInsets.all(10) CSS 样式或 scoped 样式 CSS、styled-components、emotion、Tailwind 等
响应式布局 使用 LayoutBuilderMediaQueryFlexible 控制自适应 使用媒体查询 + CSS Flex/Grid 等 同 Vue,依赖 CSS 的能力
Flex布局 Row/Column + Expanded/Flexible 控制主轴和交叉轴方向 CSS Flex,例如 display: flex; justify-content: space-between JSX中用 div 加 class 控制 CSS Flex 或 styled-components
Grid布局 GridView, SliverGrid 等自带 widget CSS Grid 同 Vue
Absolute 定位 Stack + Positioned 实现层叠与绝对定位 CSS 的 position: absolute 同 Vue
条件渲染 使用 if/? : 表达式嵌入 widget v-if, v-show, 三元表达式 if () return ...,或三元表达式

🧭 示例对比:Flex 布局(横向排列)

Flutter 示例

dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Text("Left"),
    Text("Right"),
  ],
)

Vue 3 示例(template)

html 复制代码
<template>
  <div class="flex-container">
    <span>Left</span>
    <span>Right</span>
  </div>
</template>

<style scoped>
.flex-container {
  display: flex;
  justify-content: space-between;
}
</style>

React 示例(JSX)

js 复制代码
function App() {
  return (
    <div style={{ display: 'flex', justifyContent: 'space-between' }}>
      <span>Left</span>
      <span>Right</span>
    </div>
  );
}

好的,我们来通过 实际开发中常见的 UI 场景 ,对比 Flutter、Vue 3 和 React 的实现方式,重点包括 布局、动画、交互、状态管理等方面。每个场景都提供三者的代码示例,以便你直观对比和学习。


🧩 场景 1:页面加载时淡入(入场动画)

Flutter 示例(使用 AnimatedOpacity

dart 复制代码
class FadeInDemo extends StatefulWidget {
  @override
  _FadeInDemoState createState() => _FadeInDemoState();
}

class _FadeInDemoState extends State<FadeInDemo> {
  double _opacity = 0.0;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration(milliseconds: 300), () {
      setState(() {
        _opacity = 1.0;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedOpacity(
      duration: Duration(milliseconds: 600),
      opacity: _opacity,
      child: Text("Hello World"),
    );
  }
}

Vue 3 示例(使用 <transition>

js 复制代码
<template>
  <transition name="fade">
    <div v-if="show" class="text">Hello World</div>
  </transition>
</template>

<script setup>
import { ref, onMounted } from 'vue'
const show = ref(false)

onMounted(() => {
  setTimeout(() => show.value = true, 300)
})
</script>

<style scoped>
.fade-enter-active {
  transition: opacity 0.6s;
}
.fade-enter-from {
  opacity: 0;
}
.fade-enter-to {
  opacity: 1;
}
</style>

React 示例(使用 CSS Transition + useEffect

js 复制代码
import { useState, useEffect } from "react";
import "./App.css";

export default function App() {
  const [show, setShow] = useState(false);
  useEffect(() => {
    setTimeout(() => setShow(true), 300);
  }, []);
  
  return <div className={`text ${show ? "fade-in" : ""}`}>Hello World</div>;
}
css 复制代码
.text {
  opacity: 0;
  transition: opacity 0.6s;
}
.fade-in {
  opacity: 1;
}

🧭 场景 2:Tab 切换布局

Flutter 示例(TabBar + TabBarView

dart 复制代码
DefaultTabController(
  length: 2,
  child: Scaffold(
    appBar: AppBar(
      bottom: TabBar(
        tabs: [
          Tab(text: "Home"),
          Tab(text: "Profile"),
        ],
      ),
    ),
    body: TabBarView(
      children: [
        Center(child: Text("Home Page")),
        Center(child: Text("Profile Page")),
      ],
    ),
  ),
)

Vue 3 示例(配合 Element Plus 或自定义 Tab)

js 复制代码
<template>
  <el-tabs v-model="activeTab">
    <el-tab-pane label="Home" name="home">Home Page</el-tab-pane>
    <el-tab-pane label="Profile" name="profile">Profile Page</el-tab-pane>
  </el-tabs>
</template>

<script setup>
import { ref } from 'vue'
const activeTab = ref('home')
</script>

React 示例(配合 Ant Design 或自定义 Tab)

js 复制代码
import { Tabs } from "antd";
const { TabPane } = Tabs;

export default function App() {
  return (
    <Tabs defaultActiveKey="1">
      <TabPane tab="Home" key="1">Home Page</TabPane>
      <TabPane tab="Profile" key="2">Profile Page</TabPane>
    </Tabs>
  );
}

🎮 场景 3:点击按钮后元素平移动画(Translate 动画)

Flutter 示例(AnimatedPositioned + Stack

dart 复制代码
class SlideDemo extends StatefulWidget {
  @override
  _SlideDemoState createState() => _SlideDemoState();
}

class _SlideDemoState extends State<SlideDemo> {
  bool moved = false;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        AnimatedPositioned(
          left: moved ? 200 : 0,
          duration: Duration(milliseconds: 500),
          child: ElevatedButton(
            onPressed: () => setState(() => moved = !moved),
            child: Text("Move Me"),
          ),
        ),
      ],
    );
  }
}

Vue 3 示例(CSS 动画 + 绑定 style)

js 复制代码
<template>
  <button :style="style" @click="toggle">Move Me</button>
</template>

<script setup>
import { ref, computed } from 'vue'
const moved = ref(false)
const toggle = () => moved.value = !moved.value
const style = computed(() => ({
  transform: `translateX(${moved.value ? '200px' : '0px'})`,
  transition: 'transform 0.5s'
}))
</script>

React 示例(CSS 绑定 style)

js 复制代码
import { useState } from "react";

export default function App() {
  const [moved, setMoved] = useState(false);
  return (
    <button
      onClick={() => setMoved(!moved)}
      style={{
        transform: `translateX(${moved ? "200px" : "0px"})`,
        transition: "transform 0.5s"
      }}
    >
      Move Me
    </button>
  );
}

📦 响应式/状态管理对比

功能 Flutter Vue 3 React
响应式机制 setState / Provider / Riverpod 等 ref, reactive useState, useEffect
组件更新机制 自动刷新使用该状态的 widget 响应式引用追踪 函数组件执行时重新渲染

🧠 总结对比学习建议

特性 Flutter Vue 3 React
动画支持 强大,组件级支持(如 Animated* 原生 CSS 动画 + transition 插件 原生 CSS 或动画库(framer-motion)
样式控制 属性式控制,强结构性 类 + CSS,配合 scoped 或 tailwind JSX 样式 + styled-components 等
状态响应 setState / Riverpod / GetX ref/reactive + watch useState / useEffect
生命周期 initState, build, dispose onMounted, onUnmounted useEffect(() => {}, [])

相关推荐
飞翔的佩奇1 小时前
基于SpringBoot+MyBatis+MySQL+VUE实现的经方药食两用服务平台管理系统(附源码+数据库+毕业论文+部署教程+配套软件)
数据库·vue.js·spring boot·mysql·毕业设计·mybatis·经方药食两用平台
故事与九4 小时前
vue3使用vue-pdf-embed实现前端PDF在线预览
前端·vue.js·pdf
半个烧饼不加肉8 小时前
React + ts + react-webcam + CamSplitter 实现虚拟摄像头解决win摄像头独占的问题
前端·react.js·前端框架
小喷友10 小时前
第 6 章:API 路由(后端能力)
前端·react.js·next.js
用户7360043755610 小时前
【Flutter 必备插件】HTTP 封装 dio
flutter
桃桃乌龙_952710 小时前
vue-demi打通pnpm替换npm导致的pinia使用问题
前端·vue.js
Linsk10 小时前
前端开发:不处理浏览器兼容性,才是最佳的浏览器兼容性处理方式
前端·vue.js·前端工程化
jqq66610 小时前
Vue3脚手架实现(十、补之前配置)
前端·javascript·vue.js
风清云淡_A11 小时前
【Flutter3.8x】flutter从入门到实战基础教程(四):自定义实现一个自增的StatefulWidget组件
前端·flutter
代码的余温12 小时前
React核心:组件化与虚拟DOM揭秘
前端·react.js·前端框架