Flutter Web:混合开发的最佳实践

Flutter Web:混合开发的最佳实践

一次编写,多端运行。Flutter Web 让前端开发更加高效。

一、Flutter Web 的优势

作为一名追求像素级还原的 UI 匠人,我对跨平台解决方案有着严格的要求。Flutter Web 不仅让我们能够使用相同的代码库构建 Android、iOS 和 Web 应用,还提供了出色的性能和一致的用户体验。它就像是一把瑞士军刀,为前端开发带来了前所未有的便利。

二、环境搭建

1. 启用 Web 支持

# 启用 Web 支持 flutter config --enable-web # 检查可用设备 flutter devices # 创建项目 flutter create my_web_app cd my_web_app # 运行 Web 应用 flutter run -d chrome 

2. 项目结构

my_web_app/ lib/ main.dart # 主入口 home_screen.dart # 主屏幕 components/ # 组件 services/ # 服务 web/ # Web 特定文件 index.html # HTML 入口 manifest.json # PWA 配置 icons/ # 图标 pubspec.yaml # 依赖配置 

三、基础实现

1. 简单的 Web 应用

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 Web Demo', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override _HomeScreenState createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter Web Demo'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } 

四、Web 特定功能

1. 响应式布局

class ResponsiveLayout extends StatelessWidget { final Widget mobileLayout; final Widget tabletLayout; final Widget desktopLayout; const ResponsiveLayout({ Key? key, required this.mobileLayout, required this.tabletLayout, required this.desktopLayout, }) : super(key: key); @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth < 600) { return mobileLayout; } else if (constraints.maxWidth < 1024) { return tabletLayout; } else { return desktopLayout; } }, ); } } // 使用 class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return ResponsiveLayout( mobileLayout: MobileHome(), tabletLayout: TabletHome(), desktopLayout: DesktopHome(), ); } } 

2. 平台检测

import 'package:flutter/foundation.dart'; class PlatformAwareWidget extends StatelessWidget { @override Widget build(BuildContext context) { if (kIsWeb) { // Web 特定实现 return WebSpecificWidget(); } else if (Platform.isAndroid) { // Android 特定实现 return AndroidSpecificWidget(); } else if (Platform.isIOS) { // iOS 特定实现 return IOSSpecificWidget(); } else { // 通用实现 return CommonWidget(); } } } 

3. 与 Web API 交互

import 'dart:js' as js; class WebInteropWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ ElevatedButton( onPressed: () { // 调用 JavaScript 函数 js.context.callMethod('alert', ['Hello from Flutter!']); }, child: Text('Show Alert'), ), ElevatedButton( onPressed: () { // 访问 DOM js.context['document'].callMethod('title', ['Flutter Web App']); }, child: Text('Change Title'), ), ], ); } } 

五、性能优化

1. 代码分割

// main.dart void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( routes: { '/': (context) => HomePage(), '/details': (context) => DetailsPage(), }, ); } } // details_page.dart class DetailsPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Details')), body: Center(child: Text('Details Page')), ); } } 

2. 图片优化

class OptimizedImage extends StatelessWidget { final String src; final double? width; final double? height; const OptimizedImage({ Key? key, required this.src, this.width, this.height, }) : super(key: key); @override Widget build(BuildContext context) { return Image.network( src, width: width, height: height, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, ), ); }, errorBuilder: (context, error, stackTrace) { return Container( width: width, height: height, color: Colors.grey[200], child: Icon(Icons.error), ); }, ); } } 

六、PWA 支持

1. 配置 manifest.json

{ "name": "Flutter Web App", "short_name": "FlutterApp", "description": "A Flutter Web application", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#4285f4", "icons": [ { "src": "icons/Icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" } ] } 

2. 配置 service_worker.js

// service_worker.js const CACHE_NAME = 'flutter-app-cache'; const ASSETS = [ '/', '/index.html', '/manifest.json', '/icons/Icon-192.png', '/icons/Icon-512.png', ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(ASSETS); }) ); }); self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); }) ); }); 

七、部署

1. 构建 Web 应用

# 开发模式 flutter build web # 生产模式(优化) flutter build web --release --web-renderer canvaskit # 生产模式(体积更小) flutter build web --release --web-renderer html 

2. 部署到静态网站托管

  • Firebase Hosting
  • Netlify
  • Vercel
  • GitHub Pages

Flutter Web 让跨平台开发变得简单优雅,就像好的设计一样自然。

#flutter #web #hybrid #cross-platform #frontend

Read more

uni-app——uni-app 小程序 之 【按钮失效问题排查(前端+后端)】

一、问题背景 在某业务流程系统中,当业务单据进入特定待处理状态后,用户需要在对应操作页面完成核心操作,点击页面中的两个关键操作按钮(提交类、完结类)以推进流程流转。 然而实际操作时,两个按钮均出现报错提示,无法正常触发流程跳转,业务无法继续推进。 二、问题复现 操作步骤: 1. 登录系统账号(具备对应操作权限) 2. 进入业务单据列表,找到一条处于特定待处理状态的单据 3. 点击进入该单据的操作详情页面 4. 填写页面所需基础信息、上传相关附件 5. 点击页面中的提交类或完结类按钮 6. 结果:按钮点击后报错,流程无法流转到下一节点,操作失败。 三、问题分析 经过多轮排查,发现问题并非单一环节导致,而是涉及前端和后端两层,属于接口调用、参数传递及数据校验的联动异常,具体分析如下: 1. 前端:页面加载时未获取核心业务数据 操作详情页面进入后,未先调用查询接口获取单据关联的核心数据,直接使用空值的关键标识调用操作接口,导致后端无法查询到对应业务记录,接口调用失败。

【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键

【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键

目录 【年终总结】从非科班无实习到准字节前端:我始终相信,开发之外的事,才是破局关键 一、求其外,善其内 1、坚持出发点正确的博文写作 2、博文更新对我心态的淬炼 3、社区交流对我视野的启发 4、向外拓展,反哺内修 二、陷入前端则前端死,跳出前端则前端活 1、从不务正业到泛前端 2、从泛前端到大前端,从有形到无形 三、秋招多少事 四、结语         作者:watermelo37         ZEEKLOG优质创作者、华为云云享专家、阿里云专家博主、腾讯云“创作之星”特邀作者、火山KOL、支付宝合作作者,全平台博客昵称watermelo37。         一个假装是giser的coder,做不只专注于业务逻辑的前端工程师,Java、Docker、Python、LLM均有涉猎。 --------------------------------------------------------------------- 温柔地对待温柔的人,包容的三观就是最大的温柔。

【Electron架构解析】打破浏览器沙盒:从 Web 前端到桌面客户端的技术跨越

【Electron架构解析】打破浏览器沙盒:从 Web 前端到桌面客户端的技术跨越

在现代企业级应用开发中,纯粹的 B/S(Browser/Server)架构有时难以满足日益复杂的业务需求。当项目交付形态从 Web 链接转变为桌面可执行程序(.exe/.dmg)时,这标志着我们进入了 Electron 的领域。对于习惯了 Chrome 开发者工具的前端工程师而言,理解 Electron 的本质,是完成从“网页开发”到“应用开发”思维转型的关键一步。 本文将深入剖析 Electron 的双进程架构,并以实际工程中的配置文件为例,解读它是如何利用 Web 技术栈突破浏览器安全沙盒的限制。 目录 一、 混合运行时:Chromium 与 Node.js 的深度融合 二、 核心中枢:主进程 (Main Process) 的权限突破 三、 安全桥梁:

OpenClaw Skills扩展:nanobot通过webhook对接钉钉/飞书,实现跨平台消息同步

OpenClaw Skills扩展:nanobot通过webhook对接钉钉/飞书,实现跨平台消息同步 1. nanobot简介 nanobot是一款受OpenClaw启发的超轻量级个人人工智能助手,仅需约4000行代码即可提供核心代理功能。相比传统方案,代码量减少了99%,但功能依然强大。 这个轻量级助手内置了vllm部署的Qwen3-4B-Instruct-2507模型,使用chainlit进行推理交互。最吸引人的是,你可以轻松配置它作为QQ聊天机器人使用,或者通过webhook对接企业通讯工具如钉钉和飞书。 2. 基础环境验证 2.1 检查模型服务状态 在开始扩展功能前,我们需要确认基础服务运行正常。通过以下命令检查模型部署状态: cat /root/workspace/llm.log 如果看到服务启动成功的日志信息,说明模型已准备就绪。常见的成功标志包括"Model loaded successfully"或"Service started on port xxxx"等提示。 2.2 测试基础问答功能