阿里卖家 Flutter for Web 工程实践
liuian 2025-05-21 14:59 98 浏览
作者:马坤乐(坤吾)
Flutter 自 2015 年初次亮相以来,经过了多年的发展已经相当成熟,在阿里、美团、拼多多等互联网公司都有广泛的应用。在 ICBU 阿里卖家上 90+% 的新业务使用 Flutter 开发,ICBU 客户端开发组拥有众多的 Flutter 开发人员。
Flutter for Web (FFW) 早期试验版于 2019 年发布,在当时已经有很多感兴趣同学对其进行调研,当时由于刚发布存在诸多问题不适合在生产环境中使用。在今年(2021)三月份,Flutter 2.0 发布,FFW 正式进入 stable 分支。
阿里卖家外贸资讯版块主要使用 Flutter 开发,在本财年的目标中,外贸资讯的App外推广为开源引流的重要一环。App外资讯推广需要一个承载内容Web页面,对该Web页面的要求如下:
- 复刻App端相关页面的 UI、功能(主要包含一个dart编写的自定义html解析渲染引擎)【主要工作量】
- 快速上线
- App端功能同步
由于缺乏前端同学的支持,想要完成此页面只能由 App 端上同学自己投入,经过一定的考虑我们选择了 FFW,理由如下:
- 切换到前端技术栈 Rax 等成本稍高,同时目标页面功能复刻需要较多时间
- 使用 FFW 目标页面上绝大部分代码可复用端上现成 dart 代码
- App 端上 Flutter 技术栈同学覆盖广
经过以上思考,正式开启 FFW 填坑之旅。
Demo
目前阿里卖家FFW相关页面已上线,从 FFW 发布至今产物 js 文件大的问题就一直存在,理论上会很影响页面加载体验,实际测试中观察到在 PC、移动设备上加载体验尚可,运行很流畅,相关 Demo 如下:
- 外投内容展示页 demo:https://alisupplier.alibaba.com/content_page/#/web_news_detail?courseCode=PX8K3IYX&sourceId=cata_0
- 阿里卖家 App 下载页面:https://alisupplier.alibaba.com/content_page/#/sellerapp?s=c_ata
问题总览
创建 FFW 工程比较简单,Flutter 切换到 stable 版本,之后运行命令 flutter create xxxProject 进入工程后点击运行一个 Demo 工程便可运行起来。要将 FFW 应用到实际的工程中,需要考虑的是工程的问题和如何融入阿里的体系的问题,如:怎么发布、开发流程如何管控、怎么请求接口等,总结如下:
以上为阿里卖家 FFW 开源引流最小闭环实践中遇到的问题,除此之外 FFW 待建设的问题还有:
工程基础
接下来是对最小闭环实践中,工程基础问题的出现原因和解决方案的说明。
环境和复用
参考 App 端 Flutter 开发,FFW 中首先要考虑选择 Flutter 的什么版本,其次是考虑如何复用已有的 Flutter 代码。
1Flutter 版本选择
版本选择问题因 FFW 和 Flutter for App (FFA) 的 Flutter 版本无法统一产生。FFW 需要的 Flutter 版本为 2.0+,而目前我们 App 端内的 Flutter 版本为 1.X+ ,要升级到 2.0+ 版本还需等待不确定的时间。经过一定的考虑目前我们 FFW 和 FFA 选择版本如下:
FFA: hummer/release/v1.22.6.3 -- UC的Hummer分支
FFW: origin/flutter-2.8-candidate.9 -- 官方分支FFW 不选用 stable 版本是因为在最近刚发布的 iOS 15 上 FFW 页面会因 webGL 问题会卡死,该问题修复方案目前已集成到了candidate版本。(当前最新stable版本为2.10.0,问题已解决)
2代码复用
FFA 代码复用到 FFW 中要考虑的问题分两块:
- Dart 代码复用
- 平台相关插件能力复用
Dart 代码复用
FFW 需要 Flutter 2.0+ 版本对应的 dart 版本为 2.12,此版本的 dart 引入了空安全 (Sound null safety) 特性。FFA 上使用的 Flutter 版本为 1.+ 版本对应的 dart 还未引入空安全。同时 Flutter 中新老版本 dart 库代码无法混合编译,所以目前对已有 App 端代码库还无法做到无缝复用,只能通过修改已有代码进行复用,代码修改主要的点有:
- 可为空的变量,类型后添加?
User? nullableUser;- 操作可为空的变量时使用 ? 或 !
nullableUser?.toString(); // 空安全,如为空不会出现NPE
nullableUser!.toString(); // 强制指定非空,如为空会报错- 可选参数 @required 注解替换为 required 保留字
/// 老版本
User({
@required this.name,
@required this.age,
});
/// 新版本
User({
required this.name,
required this.age,
});低版本代码经过这三步修改后基本可在新版本编译通过,除此之外还会有部分 API 由于版本升级产生变更,也需要相应的修改,如:
/// 老版本
typedef ValueWidgetBuilder<T>
= Widget Function(BuildContext context, T value, Widget child);
/// 新版本
typedef ValueWidgetBuilder<T>
= Widget Function(BuildContext context, T value, Widget? child);在 API 变更中这类问题占大多数,修改起来较简单。另外还有一类改动,如在抽象类 TextSelectionControls中,handleCut等方法参数的个数发生了变更:
/// 老版本
void handleCut(TextSelectionDelegate delegate) {...}
/// 新版本
void handleCut(TextSelectionDelegate delegate,
ClipboardStatusNotifier? clipboardStatus) {...}这类改动需根据实际情况进行修改,难度中等,新加的参数大概率是可以不使用的。
平台相关插件
平台相关的插件会调用 Native 的能力,要在 FFW 上使用 FFA 中的插件,需要为插件在 Web 平台实现相应的能力,下文 js 调用部分会进行说明。如果使用的是pub.dev 中的库,且该库满足如下条件则可直接使用相应的版本:
- 代码库有 Web 版本
- 发布的版本中有支持 Null safety 的版本(支持 Web 也会支持这个)
支持 Web 版本 | 支持空安全 |
发布体系
本地Demo工程创建并运行成功后,接下来要考虑几个问题:
- 开发到发布的流程如何管控
- 如何将页面发布到线上公网可访问
- 怎么打包构建
- 怎么发布
对于开发到发布流程的管控,参考前端选用 DEF 平台(阿里内部前端开发发布平台)通过创建 WebApp 方式管理,这里不详细说明。对于页面发布涉及内容如下:
1工程构建
FFW 的构建方式有两种,构建的产物在应用中并非全部需要需要进行一定的精简;另外要在 DEF 平台上发布产物还需对产物进行一些额外的处理。在构建中主要考虑如何构建,FFW 编译构建可选命令如下:
/// canvaskit方式渲染
flutter build web --web-renderer canvaskit
/// html方式渲染
flutter build web --web-renderer html两条命令的区别是目标页面以何种方式渲染,Flutter 官方对两种方式区别的解释如下:
总结来说如下:
- Html 方式:页面使用 Html 的基础元素渲染,优点是页面资源文件小;
- CanvasKit 方式:使用了 WebAssembly 技术,具有更好的性能,但是因为需要加载 WebAssembly 相关的 wasm 文件从而多加载 2.+ MB 的资源文件,更适合对页面性能有较高要求的场景。
在空工程上两种方式资源加载对比如下,基于对页面大小和页面性能考虑我们选择使用html的方式。
Html 方式 | CanvasKit 方式 |
2产物精简和处理
对于新创建的工程,编译后产物位于 ./build/web目录下,结构为:
build
└── [ 384] web
├── [ 224] assets
│ ├── [ 2] AssetManifest.json
│ ├── [ 82] FontManifest.json
│ ├── [740K] NOTICES
│ └── [ 96] fonts
│ └── [1.2M] MaterialIcons-Regular.otf
├── [ 917] favicon.png
├── [6.5K] flutter_service_worker.js
├── [ 128] icons
│ ├── [5.2K] Icon-192.png
│ └── [8.1K] Icon-512.png
├── [3.6K] index.html 【发布保留】
├── [1.2M] main.dart.js 【发布保留】
├── [ 570] manifest.json
└── [ 59] version.json其中各目录和文件的作用和说明如下:
- assets: 图片、字体等资源文件,对应 yaml 文件中配置的 assets,在 FFW 中图片配置在 TPS 上且不使用 IconFont 的情况下,该目录可不需要;
- favicon.png: 页面的 icon,使用 TPS 资源时可不需要;
- flutter_service_worker.js:本地 debug 时控制页面加载、reload、关闭等,发布时不需要;
- icons:icon 资源,发布到 TPS 可不需要;
- index.html:页面入口文件,主要工作是引入 main.dart.js 还有一些其他资源,类似 App 的壳工程,需要;
- main.dart.js:工程中 dart 编译后的产物,需要;
- manifest.json: 页面作为 webapp 使用的配置,可不需要;
- version.json: 构建信息,可不需要。
在实际发布中,需要的构建产物只有 index.html 和 main.dart.js ,对于每次的迭代,不涉及到 “壳工程” 变更时只需要 main.dart.js 即可。
选定了需要的产物后,在 DEF 平台发布前还需要对这两个文件进行一些处理:
- html 中对 main.dart.js 的引用替换为相应迭代的cdn地址(根据迭代号、发布环境拼接);
- html 中 <base> 标签修改,参考 https://docs.flutter.dev/development/ui/navigation/url-strategies#hosting-a-flutter-app-at-a-non-root-location;
- js 和 html 文件内注释移除(def发布门神检查);
- js 中替换 ?? 运算符(钉钉 H5 容器中该运算符报错);
- 将index.html 和 main.dart.js 移动到 DEF 平台上的产物文件夹。
3页面发布
在DEF平台上,产物文件处理完成后 js 和 html 文件会被发布到相应的cdn,同时html会被部署到特定的地址上:
预发:
- https://dev.g.alicdn.com/algernon/alisupplier_content_web/1.0.10/index.html
- https://dev.g.alicdn.com/algernon/alisupplier_content_web/1.0.10/main.dart.js
- https://market.wapa.taobao.com/app/algernon/alisupplier_content_web/index.html (部署地址)
线上:
- https://g.alicdn.com/algernon/alisupplier_content_web/1.0.10/index.html
- https://g.alicdn.com/algernon/alisupplier_content_web/1.0.10/main.dart.js
- https://market.m.taobao.com/app/algernon/alisupplier_content_web/index.html (部署地址)
对于线上环境index.html内容如下:
<!DOCTYPE html>
<html>
<head>
<!-- 发布到域名的二级目录时使用 -->
<base href="/content_page/" />
</head>
<body>
<!-- 替换为 main.dart.js 相应的 cdn 地址 -->
<script type="text/javascript" src="https://g.alicdn.com/algernon/alisupplier_content_web/1.0.10/main.dart.js"></script>
</body>
</html>至此使用页面部署地址就可以访问到我们的目标页面了如果页面是一次性打开的,且不需要在内部进行多页面跳转,到这一步发布工作就完成了。如果涉及到多页面跳转,还需要将相关的内容发布到自己的域名下,比较简单的方式为配置重定向,除此之外直接引用产物也可:
- 目标域名地址重定向:将自己域名下地址重定向到页面部署地址,如将https://alisupplier.alibaba.com/page_content/index.html*映射到 https://market.m.taobao.com/app/algernon/alisupplier_content_web/index.html*。这样def每次发布后不需做额外修改。注意:要求FFW的UrlStrategy为hash tag方式(默认的UrlStrategy);
- 目标域名地址重定向:在目标域名下创建 index.html 并引用 main.dart.js 文件,或者目标页面内嵌发布的页面。参照:https://docs.flutter.dev/deployment/web#embedding-a-flutter-app-into-an-html-page。
代码调试
基础链路跑通后就可以进行需求的开发了,开发过程中比较重要的环境是代码的调试,FFW 可在 Chrome 中以类似 App 的方式调试且体验较好。在 Debug 环境下在 IDE 中设置断点后,即可在 IDE 中调试断点,也可在 Chrome 中查看断点,Chrome 中甚至可看到 dart 代码。以 VSCode 为例 Debug 过程和体验如下:
启动Flutter调试
VSCode 和 Chrome 中可见的断点
能力支持
进入到实际的开发中后,就需要诸如路由、接口请求等能力的支持了,首先是页面路由和地址。
页面路由和地址
在 FFW 应用中出现多页面,或者需要通过 Http 链接传参时,就需要进行相应的路由配置。类似FFA,可在根MaterialApp中配置相应的 Route,之后使用Navigator.push跳转或通过页面地址直接打开页面即可。如下代码可实现命名跳转和页面地址跳转:
/// MaterialApp 配置
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
onGenerateRoute: RouteConfiguration.onGenerateRoute,
onGenerateInitialRoutes: (settings) {
return [RouteConfiguration.onGenerateRoute(RouteSettings(name: settings))];
},
);
}
}/// 命名路由配置
class RouteConfiguration {
static Map<String, RouteWidgetBuilder?> builders = {
/// 页面A
'/page_a': (context, params) {
return PageA(title: params?['title']);
},
/// 页面B
'/page_b': (context, params) {
return PageB(param1: params?['param1'], param2: params?['param2']);
},
};
static Route<dynamic> onGenerateRoute(RouteSettings settings) {
return NoAnimationMaterialPageRoute(
settings: settings,
builder: (context) {
var uri = Uri.parse(settings.name ?? '');
var route = builders[uri.path];
if (route != null) {
return route(context, uri.queryParameters);
} else {
return CommonPageNotFound(routeSettings: settings);
}
},
);
}
}配置完成后即可在页面能进行跳转,或者通欧冠浏览器地址直接跳转:
- 应用内跳转:配置完成之后,在应用内部可通过Navigator跳转到目标页面
/// Navigator 跳转页面 B
Navigator.of(context).restorablePushNamed('/page_b?param1=123Pm2=abc');- 地址跳转:在浏览器地址栏中输入页面的地址跳转到页面
/// 页面 B 访问地址
https://xxx.xx/#/page_b?param1=123Pm2=abc注意:上述地址跳转方式要求 FFW 的 UrlStrategy 为 hash tag 方式(默认的UrlStrategy)。
Web 平台的 Native —— JS 调用
通过使用 pub.dev 等仓库,可以在 FFW 中轻松的使用各种能力。对于仓库中没有的能力就要考虑进行扩展了。在 FFA 上可通过插件的方式使用 native 的能力,同样在 FFW 上可通过扩展使用 js 的能力。通过调用 js 的能力前端海量的技术积累便可应用到 FFW 上。
FFW 中的 dart 最终会编译成 js ,在 FFW 中理应可以天然使用 js。为了在 dart 中支持 js 的调用,dart 官方发布了 js 库,通过使用该库中的注解可是很方便的在 dart 中调用 js。
比如需要调用 alert 方法时,进行如下定义:
/// 文件:js_interface.dart
/// 调用js方法的工具类库,需在 dependencies 中引入 js 库
@JS()
library lib.content;
import 'package:js/js.dart';
/// alert 弹窗
@JS('alert')
external void jsAlert(String msg);之后在需要alert的地方引入js_interface.dart 并调用 jsAlert方法即可:
import 'package:mtest/js_interface.dart';
...
jsAlert('测试消息');
...更多用法详见 pub.dev 中 js 库的说明:
https://pub.dev/packages/js。打通了 js 的能力后,接下来的很多问题迎刃而解。
Mtop接口
鉴于 App 端现有 Mtop (阿里App使用的一种网关)的建设,如果能在 FFW 中调用现有的 Mtop 将可以减少很多的工作量。为此需要为 FFW 添加 Mtop 调用的能力,要完成这个工作需要两部分的工作:
- FFW 端支持 Mtop 调用
- 服务端支持 H5 方式的 Mtop 调用
1FFW 支持 Mtop
通过调用 mtop.js 的能力便可在 FFW 中引入 mtop 的能力。整体流程如下:
1、在index.html 中引入 mtop.js
<script src="//g.alicdn.com/mtb/lib-mtop/2.6.1/mtop.js"></script>2、定义接口文件 js_mtop_interface.dart
@JS()
library lib.mtop;
import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'dart:convert';
import 'dart:js';
/// mtop请求的参数
@anonymous
@JS()
class MtopParams {
external String get api;
external String get v;
external dynamic get data;
external String get ecode;
external String get dataType;
external String get type;
external factory MtopParams({
required String api,
required String v,
required dynamic data,
required String ecode,
required String dataType,
required String type,
});
}
/// lib.mtop 请求函数
@JS('lib.mtop.request')
external dynamic _jsMtopRequest(MtopParams params);
/// dart map 转为 js 的 object
Object mapToJSObj(Map<String, dynamic> a) {
var object = newObject();
a.forEach((k, v) {
var key = k;
var value = v;
setProperty(object, key, value);
});
return object;
}
/// mtop js 请求接口
Future mtopRequest(String api, Map<String, dynamic> params, String version, String method) {
var jsPromise = _jsMtopRequest(
MtopParams(
api: api,
v: version,
data: mapToJSObj(params),
ecode: '0',
type: method,
dataType: 'json',
),
);
return promiseToFuture(jsPromise);
}
/// 返回结果解析使用
@JS('JSON.stringify')
external String stringify(Object obj);3、进行 mtop 接口调用
import 'package:mtest/mtop/js_mtop_interface.dart';
...
try {
var res = await mtopRequest(apiName, params, version, method);
print('res $res');
} catch (err) {
data = stringify(err);
}4、解析结果:接口请求返回的结果是一个 jsObject,可通过 js 方法 JSON.stringify 转成 json 后在 dart 层面使用
String jsonStr = stringify(res);2服务端 H5 Mtop 配置
FFW 中接入 mtop.js 后,需要对目标 mtop 接口进行相应的处理才可调用:
- mtop 发布 h5 版本
- 申请配置CORS域名白名单
打点
同 mtop 请求,FFW 中可引入黄金令箭的 js 库进行打点,流程如下:
1、index.html 引入 js 文件
<script type="text/javascript" src="https://g.alicdn.com/alilog/mlog/aplus_v2.js"></script>2、定义接口文件 js_goldlog_interface.dart
@JS()
library lib.goldlog;
import 'package:js/js.dart';
/// record 函数
@JS('goldlog.record')
external dynamic _jsGoldlogRecord(String t, String e, String n, String o, String a);
void goldlogRecord(String logkey, String eventType, String queryParams) {
_jsGoldlogRecord(logkey, eventType, queryParams, 'GET', '');
}3、打点调用
import 'package:mtest/track/js_goldlog_interface.dart';
...
goldlogRecord(logkey, eventType, queryParams);
...之后在 log 平台进行相应的点位配置即可。
监控
监控能力接入较为简单,这里选择 arms(应用实时监控服务),直接在 index.html 中引入 arms 即可。流程如下:
1、在 index.html 中引入相关库
<script type="text/javascript">
var trace = window.TraceSdk({
pid: 'as-content-web',
plugins: [
[window.TraceApiPlugin, { sampling: 1 }],
[window.TracePerfPlugin],
[window.TraceResourceErrorPlugin]
],
});
// 启动 trace 并监听全局 JS 异常,debug时问题暂时注释
trace.install();
trace.logPv();
</script>2、在 arms 平台上进行相关配置
注意:trace.install() 在 Debug 环境下会导致页面不展示,可在 Debug 环境中禁用。
优化和兼容
完成了上述基础能力建设后,FFW 基本可满足简单需求的开发。需求开发之外还需考虑体验、兼容性等问题。
加载优化
FFW 从发布至今都存在的一个问题就是包大小问题,对与一个空的 helloworld 工程,单 js 包大小是 1.2 MB(未压缩前),在移动设备上网络不好的时候可能需要加载好些秒。为了提升页面加载的体验,考虑可以做的事情如下:
1等待过程优化
FFW 页面在 js 加载完成之前都是白屏,给人一种页面卡死的感觉,为此可以在 js 加载完成前增加加载动画不至于让页面一直白屏。参考App上管用的做法,可在数据加载出来之间插入骨骼屏,实现如下:
<iframe src="https://g.alicdn.com/algernon/alisupplier_content_web/0.9.1/skeleton/index.html" id="iFrame" frameborder="0" scrolling="no"></iframe>
<script>
function setIframeSize() {
<!-- 骨骼屏尺寸设置,占满全屏 -->
}
function removeIFrame() {
var iframe = document.getElementById("iFrame");
iframe.parentNode.removeChild(iframe);
}
setIframeSize();
</script>
<!-- load 完成之后移除骨骼屏 -->
<script type="text/javascript" src="https://g.alicdn.com/algernon/alisupplier_content_web/1.0.10/main.dart.js"
onload="removeIFrame()"></script>2TODO JS拆包&优化
等待过程优化可在一定程度上提升等待体验,单治标不治本,要想加载快还得让加载的资源小,对于多页面应用,可以将整个 main.dart.js 拆分成多个小的包,在使用的过程中逐步加载,目前了解到美团有相应的技术,但实现细节未知,有待研究。可参考 https://github.com/flutter/flutter/issues/46589
兼容问题
类似 App 在不同设备上会有体验问题,FFW 在不同的 H5 容器中页会存在兼容问题,在我们的实践中不同 H5 容器踩坑记录如下:
钉钉H5容器内白屏问题:
- 不支持 ?? 语法,替换后解决
- FFW产物js中包含大量try{}finally{}无catch操作,在钉钉H5容器中会报错,打包时使用脚本统一替换解决
微信H5容器内白屏问题:
- 移除MaterialIcons,改用图片代替
iOS 15 上页面卡死问题:
- iOS 15 webGL2.0问题导致,目前已有解决方案待稳定版发布 https://github.com/flutter/flutter/issues/89655
iOS兼容性问题:
- 可点击的RichText,设置下划线属性后,紧跟着图片的链接会被遮挡,暂未找到解法,只能先不使用RichText自带的下划线
- 可点击的RichText点击后屏幕会自动滚动。验证为InteractiveSelectionu属性导致,设置为false后表现和Android一致
其他问题
除了 H5 容器的兼容问题外,在实践中还遇到 FFW 自身的一些问题,记录如下:
provider 库问题:
- provider 库中 /lib/src/provider.dart ProviderNotFoundException类toString()方法中包含一个巨长的错误说明String,该String编译后的js语法会出错,删除后即可
JsonConverter问题:
- JsonConverter().convert 运行时会报错,谨慎使用,dart array 转 js array 可手动转换
TODO 的内容
当前实践中只完成了业务可用的一个小闭环建设,FFW 中仍有很多 TODO 的内容,如下:
工程构建:
- DEF 云端构建:经尝试DEF云端构建平台安装 Flutter 环境的时候对阿里外内容的请求都会 403,而 Flutter 中有很多内容需要在线拉取,如 Flutter 根目录下 packages 中的内容,目前使用本地构建,待解决;
- 本地debug时mtop访问:mtop请求需配置CORS白名单且端口需是80,本地debug时使用的是ip、端口为一个随机数,强行设置时报无权操作,目前只能本地运行http服务器设置host后在chrome中debug,断点debug待解决。
基础功能:
- 视频、音频播放能力待研究
兼容和优化
- js 包拆分加载待研究
- 自定义字体文件优化待研究
畅想:
- App 中 Flutter 动态化:将 App 内的 Flutter 页面替换为 FFW,做成类似 weex 的动态化方案
- App WebApp 化:Flutter 实现的 App 通过 FFW 可以低成本转成 WebApp,解决诸如 App 没 Mac 版本的问题
关注【阿里巴巴移动技术】微信公众号,每周 3 篇移动技术实践&干货给你思考!
- 上一篇:Flutter——按钮
- 下一篇:Flutter如何内存优化
相关推荐
-
- 驱动网卡(怎么从新驱动网卡)
-
网卡一般是指为电脑主机提供有线无线网络功能的适配器。而网卡驱动指的就是电脑连接识别这些网卡型号的桥梁。网卡只有打上了网卡驱动才能正常使用。并不是说所有的网卡一插到电脑上面就能进行数据传输了,他都需要里面芯片组的驱动文件才能支持他进行数据传输...
-
2026-01-30 00:37 liuian
- win10更新助手装系统(微软win10更新助手)
-
1、点击首页“系统升级”的按钮,给出弹框,告诉用户需要上传IMEI码才能使用升级服务。同时给出同意和取消按钮。华为手机助手2、点击同意,则进入到“系统升级”功能华为手机助手华为手机助手3、在检测界面,...
- windows11专业版密钥最新(windows11专业版激活码永久)
-
Windows11专业版的正版密钥,我们是对windows的激活所必备的工具。该密钥我们可以通过微软商城或者通过计算机的硬件供应商去购买获得。获得了windows11专业版的正版密钥后,我...
-
- 手机删过的软件恢复(手机删除过的软件怎么恢复)
-
操作步骤:1、首先,我们需要先打开手机。然后在许多图标中找到带有[文件管理]文本的图标,然后单击“文件管理”进入页面。2、进入页面后,我们将在顶部看到一行文本:手机,最新信息,文档,视频,图片,音乐,收藏,最后是我们正在寻找的[更多],单击...
-
2026-01-29 23:55 liuian
- 一键ghost手动备份系统步骤(一键ghost 备份)
-
步骤1、首先把装有一键GHOST装系统的U盘插在电脑上,然后打开电脑马上按F2或DEL键入BIOS界面,然后就选择BOOT打USDHDD模式选择好,然后按F10键保存,电脑就会马上重启。 步骤...
- 怎么创建局域网(怎么创建局域网打游戏)
-
1、购买路由器一台。进入路由器把dhcp功能打开 2、购买一台交换机。从路由器lan端口拉出一条网线查到交换机的任意一个端口上。 3、两台以上电脑。从交换机任意端口拉出网线插到电脑上(电脑设置...
- 精灵驱动器官方下载(精灵驱动手机版下载)
-
是的。驱动精灵是一款集驱动管理和硬件检测于一体的、专业级的驱动管理和维护工具。驱动精灵为用户提供驱动备份、恢复、安装、删除、在线更新等实用功能。1、全新驱动精灵2012引擎,大幅提升硬件和驱动辨识能力...
- 一键还原系统步骤(一键还原系统有哪些)
-
1、首先需要下载安装一下Windows一键还原程序,在安装程序窗口中,点击“下一步”,弹出“用户许可协议”窗口,选择“我同意该许可协议的条款”,并点击“下一步”。 2、在弹出的“准备安装”窗口中,可...
- 电脑加速器哪个好(电脑加速器哪款好)
-
我认为pp加速器最好用,飞速土豆太懒,急速酷六根本不工作。pp加速器什么网页都加速,太任劳任怨了!以上是个人观点,具体性能请自己试。ps:我家电脑性能很好。迅游加速盒子是可以加速电脑的。因为有过之...
- 任何u盘都可以做启动盘吗(u盘必须做成启动盘才能装系统吗)
-
是的,需要注意,U盘的大小要在4G以上,最好是8G以上,因为启动盘里面需要装系统,内存小的话,不能用来安装系统。内存卡或者U盘或者移动硬盘都可以用来做启动盘安装系统。普通的U盘就可以,不过最好U盘...
- u盘怎么恢复文件(u盘文件恢复的方法)
-
开360安全卫士,点击上面的“功能大全”。点击文件恢复然后点击“数据”下的“文件恢复”功能。选择驱动接着选择需要恢复的驱动,选择接入的U盘。点击开始扫描选好就点击中间的“开始扫描”,开始扫描U盘数据。...
- 系统虚拟内存太低怎么办(系统虚拟内存占用过高什么原因)
-
1.检查系统虚拟内存使用情况,如果发现有大量的空闲内存,可以尝试释放一些不必要的进程,以释放内存空间。2.如果系统虚拟内存使用率较高,可以尝试增加系统虚拟内存的大小,以便更多的应用程序可以使用更多...
-
- 剪贴板权限设置方法(剪贴板访问权限)
-
1、首先打开iphone手机,触碰并按住单词或图像直到显示选择选项。2、其次,然后选取“拷贝”或“剪贴板”。3、勾选需要的“权限”,最后选择开启,即可完成苹果剪贴板权限设置。仅参考1.打开苹果手机设置按钮,点击【通用】。2.点击【键盘】,再...
-
2026-01-29 21:37 liuian
- 平板系统重装大师(平板重装win系统)
-
如果你的平板开不了机,但可以连接上电脑,那就能好办,楼主下载安装个平板刷机王到你的个人电脑上,然后连接你的平板,平板刷机王会自动识别你的平板,平板刷机王上有你平板的我刷机包,楼主点击下载一个,下载完成...
- 联想官网售后服务网点(联想官网售后服务热线)
-
联想3c服务中心是联想旗下的官方售后,是基于互联网O2O模式开发的全新服务平台。可以为终端用户提供多品牌手机、电脑以及其他3C类产品的维修、保养和保险服务。根据客户需求层次,联想服务针对个人及家庭客户...
- 一周热门
-
-
飞牛OS入门安装遇到问题,如何解决?
-
用什么工具在Win中查看8G大的log文件?
-
如何在 Windows 10 或 11 上通过命令行安装 Node.js 和 NPM
-
Trae IDE 如何与 GitHub 无缝对接?
-
如何修改图片拍摄日期?快速修改图片拍摄日期的6种方法
-
5步搞定动态考勤表!标记节假日、调休日?Excel自动变色!
-
RK3588-HDMIRX(瑞芯微rk3588芯片手册)
-
用纯Python轻松构建Web UI:Remi 动态更新,实时刷新界面内容
-
tplink无线路由器桥接教程(tplink路由器如何进行无线桥接)
-
都说Feign是RPC,没有侵入性,为什么我的代码越来越像 C++
-
- 最近发表
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)
- c++ 字符串查找 (35)
- mysql刷新权限 (34)
