浅谈 Vue & React & Flutter 框架

文章目录

    • 前言
    • 框架概述对比
    • 创建项目
      • [Vite + Vue,React 项目创建](#Vite + Vue,React 项目创建)
      • [Flutter 项目创建](#Flutter 项目创建)
    • [1. 计数器应用示例](#1. 计数器应用示例)
    • [2. 列表数据展示示例](#2. 列表数据展示示例)
      • [Vue 列表渲染](#Vue 列表渲染)
      • [React 列表渲染](#React 列表渲染)
      • [Flutter 列表渲染](#Flutter 列表渲染)
    • 核心差异分析
      • [1. 语法差异](#1. 语法差异)
      • [2. 数据绑定](#2. 数据绑定)
      • [3. 样式处理](#3. 样式处理)
    • 对比总结

前言

最近学习了 Vue.js、React、Flutter 这三个框架,如果用一句话来总结,那么:

bash 复制代码
# Web 端
Vue: 一切皆模板
React: 一切皆方法

# 移动端
Flutter: 一切皆对象

如果让我这个后端开发出身的人来选,Web 端我会选 React,移动端我会选 Flutter,我比较偏爱对象,方法,看到它们会感到很亲切。

框架概述对比

特性 Vue.js React Flutter
类型 JavaScript框架 JavaScript库 UI SDK(跨平台)
语言 JavaScript/TypeScript JavaScript/TSX Dart
架构模式 MVVM 组件化(虚拟DOM) 响应式(Widget树)
学习曲线 平缓 中等 较陡(需学Dart)
渲染方式 虚拟DOM 虚拟DOM Canvas/Skia直接渲染
跨平台 通过工具链 通过React Native 原生支持
性能 优秀 优秀 接近原生
状态管理 Vuex/Pinia Redux/MobX/Context Provider/Bloc/Riverpod

创建项目

Vite + Vue,React 项目创建

创建一个 vite 项目,可以选择 React,Vue 框架,这样我们就能得到一个基础的项目结构来运行对比,例如 Vue 项目创建:

bash 复制代码
$ pnpm create vite@latest
│
◇  Project name:
│  vite-project
│
◆  Select a framework:
│  ○ Vanilla
│  ● Vue
│  ○ React
│  ○ Preact
│  ○ Lit
│  ○ Svelte
│  ○ Solid
│  ○ Qwik
│  ○ Angular
│  ○ Marko
│  ○ Others
◆  Select a variant:
│  ● TypeScript
│  ○ JavaScript
│  ○ Official Vue Starter ↗
│  ○ Nuxt ↗
│  ○ Vike ↗
◆  Use rolldown-vite (Experimental)?:
│  ○ Yes
│  ● No
◆  Install with pnpm and start now?
│  ○ Yes / ● No
│
└  Done. Now run:

  cd vite-project
  pnpm install
  pnpm dev

Flutter 项目创建

创建一个 Flutter 项目,例如 counter_app

bash 复制代码
flutter create counter_app

1. 计数器应用示例

Vue 3 (Composition API)

src/components/HelloWorld.vue

html 复制代码
<!-- src/components/HelloWorld.vue -->
<script setup lang="ts">
import { ref } from "vue";

defineProps<{ msg: string }>();

const count = ref(0);
</script>

<template>
  <h1>{{ msg }}</h1>

  <div class="card">
    <button type="button" @click="count++">count is {{ count }}</button>
  </div>
</template>

src/components/index.ts

ts 复制代码
import HelloWorld from "./HelloWorld.vue";

export { HelloWorld };

src/App.vue

html 复制代码
<!-- src/App.vue -->
<script setup lang="ts">
import { HelloWorld } from "./components";
</script>

<template>
  <HelloWorld msg="Vite + Vue" />
</template>

React (函数组件 + Hooks)

src/App.tsx

ts 复制代码
import { useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import "./App.css";

function App(props: { name: string }) {
  const [count, setCount] = useState(0);

  return (
    <>
      <h1>{props.name}</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
      </div>
    </>
  );
}

export default App;

src/main.tsx,调用 App 组件 <App name="Vite + React" />,其实,可以这样看待 App(xxx),就像调用函数一样

ts 复制代码
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App name="Vite + React" />
  </StrictMode>,
);

运行对比:

Flutter (Dart)

lib/main.dart

dart 复制代码
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(colorScheme: .fromSeed(seedColor: Colors.deepPurple)),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,

        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: .center,
          children: [
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Flutter 就像是在做 java 开发,全是对象,通过对象的组合来构建 UI,我想后端应该可以无缝切换到 Flutter 开发吧。

运行效果:

2. 列表数据展示示例

Vue 列表渲染

html 复制代码
<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">
        {{ item.name }} - {{ item.price }}元
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
const items = [
  { id: 1, name: "苹果", price: 5 },
  { id: 2, name: "香蕉", price: 3 },
  { id: 3, name: "橙子", price: 4 },
];
</script>

React 列表渲染

js 复制代码
function ItemList() {
  const items = [
    { id: 1, name: "苹果", price: 5 },
    { id: 2, name: "香蕉", price: 3 },
    { id: 3, name: "橙子", price: 4 },
  ];

  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>
          {item.name} - {item.price}元
        </li>
      ))}
    </ul>
  );
}

Flutter 列表渲染

dart 复制代码
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    final item = items[index];
    return ListTile(
      title: Text(item.name),
      subtitle: Text('${item.price}元'),
    );
  },
);

核心差异分析

1. 语法差异

  • Vue: 模板语法,分离的HTML/CSS/JS
  • React: JSX,JavaScript中写HTML
  • Flutter: Widget树,完全用代码构建UI

2. 数据绑定

  • Vue: 双向绑定(v-model
html 复制代码
<input v-model="message" />
  • React: 单向数据流
js 复制代码
<input value={message} onChange={(e) => setMessage(e.target.value)} />
  • Flutter: 通过Controller
dart 复制代码
TextEditingController _controller = TextEditingController();
TextField(controller: _controller);

3. 样式处理

html 复制代码
<!-- Vue:Scoped CSS -->
<style scoped>
.button {
  background: blue;
}
</style>
js 复制代码
// React:CSS-in-JS
const styles = {
  button: {
    background: "blue",
  },
};
<button style={styles.button}>Click</button>;
dart 复制代码
// Flutter:完全代码化
ElevatedButton(
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
  ),
  child: Text('Click'),
)

对比总结

用 Vue 或 React 开发 Web 端应用,用浏览器访问,用 Flutter 开发移动端应用,可以在不同系统手机上运行。

  1. Vue 就像是模板中填充数据,React 就像是在 JS 中拼装 HTML,它们本质上还是 html,通过浏览器渲染出来
  2. Flutter 或原生(Android, iOS)开发就像是以前用 VB 开发应用一样,控件 要用它们自己的,而不是用 html 来写
相关推荐
前端摸鱼匠2 小时前
Vue 3 的ref在响应式对象中:介绍ref在reactive对象中的自动解包
前端·javascript·vue.js·前端框架·ecmascript
2501_921930832 小时前
基础入门 React Native 鸿蒙跨平台开发:Video 视频列表与轮播播放
react native·react.js
菜鸟una2 小时前
【微信小程序+Taro 3+NutUI 3】input (nut-input) 、 textarea (nut-texteare)类型使用避坑
前端·vue.js·微信小程序·小程序·taro
日光倾2 小时前
【Vue.js 入门笔记】 状态管理器Vuex
vue.js·笔记·flutter
Jiaberrr2 小时前
小程序setData性能优化指南:避开坑点,让页面丝滑如飞
前端·javascript·vue.js·性能优化·小程序
方安乐2 小时前
react笔记之tanstack
前端·笔记·react.js
2501_921930834 小时前
基础入门 React Native 鸿蒙跨平台开发:react-native-button三方库适配
react native·react.js·harmonyos
一起养小猫12 小时前
Flutter for OpenHarmony 进阶:体育计分系统与数据持久化深度解析
flutter·harmonyos
~牧马~13 小时前
【记录63】electron打包vue项目之踩坑
vue.js·electron·electron与node兼容