flutter 创建一个项目后,代码目录结构介绍信息
flutter 创建一个项目后,代码目录结构介绍信息如下:
创建一个项目后,选择了安卓、IOS、web后,生成的代码目录结构如下
所有平台共用同一个 Dart 入口:lib/main.dart; android/、ios/、web/ 只是平台壳工程(嵌入器),负责启动 Flutter 引擎、平台权限、打包配置,不是业务代码入口Flutter
一、目录分别代表什么
your_project/
├── lib/ ✅ 【核心业务dart代码】
│ └── main.dart ✅ Flutter全局入口(安卓/iOS/Web都从这里跑)
├── android/ 🤖 Android平台壳
├── ios/ 🍎 iOS平台壳
├── web/ 🌐 Web网页平台壳
├── test/ 单元测试
├── pubspec.yaml 依赖、资源、版本配置(最重要配置文件)
├── build/ 编译输出产物,不要手动改
└── .dart_tool/ dart工具缓存,忽略
1. android/ 安卓目录
android/app/src/main/AndroidManifest.xml:安卓清单,权限、包名、Activity 声明、应用图标、启动页android/app/build.gradle:gradle 打包配置、签名、版本号、minSdk、targetSdkandroid/app/src/main/kotlin/.../MainActivity.kt:安卓原生 Activity,是安卓侧原生入口,作用:创建 FlutterEngine、加载 Flutter 页面,一般不用改
流程:安卓系统启动 MainActivity → 启动 Flutter 引擎 → 引擎去执行
lib/main.dart的 main ()
2. ios/iOS 目录
ios/Runner/Info.plist:iOS 配置,权限、BundleId、图标、白名单、屏幕方向ios/Runner/AppDelegate.swift:iOS 原生 AppDelegate,iOS 原生入口,负责初始化 Flutter 引擎、生命周期、通知回调
流程:iOS 启动 Runner.app → 执行 AppDelegate → 拉起 Flutter 引擎 → 执行
lib/main.dart
3. web/ Web 目录
web/index.html:网页 html 宿主,Web 原生入口- 里面有
flutter.js加载脚本,作用:浏览器加载 html 后,js 加载编译后的 dart.js,启动 Flutter
流程:浏览器打开 index.html → flutter.js 加载 Flutter runtime → 执行
lib/main.dart
✅ 重点区分:
- 平台原生入口:
MainActivity.kt/AppDelegate.swift/index.html(平台系统识别的启动点)- Flutter 业务入口:
lib/main.dart(Flutter 框架统一入口,写界面、业务从这里开始)
二、入口文件最低可运行代码
✅ 1. lib/main.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 const MaterialApp(
home: Scaffold(
body: Center(child: Text("Hello Flutter")),
),
);
}
}
解释:
main()是 dart 程序固定入口函数;runApp()是 Flutter 函数,挂载根 Widget
✅ 2. Android 原生入口 MainActivity.kt(默认最低,几乎不用改)
package com.example.xxx
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
继承 FlutterActivity,自动帮你初始化 Flutter 引擎,是安卓最小实现。
✅ 3. iOS 原生入口 AppDelegate.swift(默认最简)
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
✅ 4. web/index.html 最简(web 宿主)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Flutter Web</title>
<script src="flutter.js" defer></script>
</head>
<body>
<script>
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: async (engineInitializer) => {
let appRunner = await engineInitializer.initializeEngine();
await appRunner.runApp();
}
});
</script>
</body>
</html>
三、启动链路总结(非常容易记)
- 安卓:系统 → MainActivity → Flutter 引擎 →
main.dart - iOS:系统 → AppDelegate → Flutter 引擎 →
main.dart - Web:浏览器 → index.html + flutter.js → Flutter 引擎 →
main.dart
开发 99% 场景:只改
lib下面 dart 代码;只有平台权限、打包签名、原生插件、渠道配置才去碰 android /ios/web 目录。
创建好项目后,默认的启动文件代码如下:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: .fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
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的设计思想是:一切皆Widget
在Flutter中自定义组件其实就是一个类,这个类需要继承StatelessWidget/StatefulWidget
StatelessWidget 是无状态组件,状态不可变的widget
StatefulWidget 是有状态组件,持有的状态可能在widget生命周期改变
StatelessWidget(无状态):界面上的内容不会变。比如图标、背景文字、图片,它们只是显示出来,不需要根据用户点击就改变颜色或数字。
•
StatefulWidget(有状态):如果加一个需求——“点击按钮,星星图标变成红色”,那就需要 StatefulWidget 来管理“是否点击过”这个状态了
我们改成这个文件代码如下也可以
需求是:在手机屏幕(或模拟器)的正中央显示一行文字 "Flutter msg"
import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件
//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
//runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
/**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
* Center 是 Flutter 中的一个布局组件(Widget)。
* 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。
child 是 Flutter 里非常常见的一个属性名,中文意思就是“孩子/子组件”。
含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
* */
runApp(
Center(
child: new Text(
"Flutter msg", // 显示的文字内容
textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
style: TextStyle(
color: Color.fromARGB(255, 201, 8, 50),//第一个是参数是透明度,后面3个是RGB颜色值
fontSize: 30.0,//字体大小
fontWeight: FontWeight.w900,//控制文字笔画的粗细程度
),
),
// child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
),
);
}

图片中的悬浮框是 VS Code(或类似编辑器)显示的代码提示(悬浮信息),它展示的是 Flutter 源码中 Center 组件的构造函数定义。
代码里能写 child:,是因为 child 本身就是这些参数中的一个。以下是具体的对应关系:
1. 图片里其实有 child
仔细看悬浮框里的第三行参数,写着:
Widget? child,
Widget?是参数的类型(表示这里需要传入一个 Widget 组件,问号表示可以为空)。child就是参数的名字。
悬浮框里的其他参数含义:
Key? key,:组件的唯一标识键。double? widthFactor,:宽度缩放倍数。double? heightFactor,:高度缩放倍数。
底部的英文说明 Creates a widget that centers its child.(创建一个将其子组件居中的组件)也印证了这一点。
快速修复是免费的,点右边的修复要登录,可能是调用AI功能修复的


修复后的代码如下
import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件
//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
//runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
/**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
* Center 是 Flutter 中的一个布局组件(Widget)。
* 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。
child 是 Flutter 里非常常见的一个属性名,中文意思就是“孩子/子组件”。
含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
* */
runApp(
Center(
child: Text(
"Flutter msg", // 显示的文字内容
textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
style: TextStyle(
color: Color.fromARGB(255, 201, 8, 50),//第一个是参数是透明度,后面3个是RGB颜色值
fontSize: 30.0,//字体大小
fontWeight: FontWeight.w900,//控制文字笔画的粗细程度
),
),
// child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
),
);
}
在 Flutter 里:
- 只能装一个组件时,属性名叫做
child(单数,后面直接跟一个 Widget)。 - 可以装多个组件时,属性名叫做
children(复数,后面跟一个 Widget 列表[])
|
场景 |
属性名 |
传值方式 |
常见组件 |
|---|---|---|---|
|
单个子组件 |
|
|
|
|
多个子组件 |
|
|
|
多组件写法举例(使用 Column 垂直排列)
Column 是一个可以让子组件从上到下垂直排列的布局组件,它接受的就是 children(多个孩子)
import 'package:flutter/material.dart';
void main() {
runApp(
Center(
// Center 还是只有一个 child
child: Column(
// Column 可以包含多个子组件,所以用 children
// mainAxisSize: MainAxisSize.min 表示 Column 高度只包住内容,不撑满全屏
mainAxisSize: MainAxisSize.min,
// children 后面是中括号 [],里面可以放任意多个 Widget
children: [
Text("第一个文本", textDirection: TextDirection.ltr),
Text("第二个文本", textDirection: TextDirection.ltr),
Text("第三个文本", textDirection: TextDirection.ltr),
],
),
),
);
}
运行效果:
屏幕正中间会显示三行文字,垂直排列:
第一个文本
第二个文本
第三个文本
因为 children 要求的是一个 List<Widget>(Widget 列表),而 Flutter 里几乎所有的东西(文本、图片、按钮、图标、容器、甚至别的布局)全部都是 Widget,所以它们可以随意混搭组合,混合了多种不同类型组件的例子如下:
import 'package:flutter/material.dart';
void main() {
runApp(
Center(
child: Column(
mainAxisSize: MainAxisSize.min, // 让 Column 高度只包住内容
// children 里放了一个列表,里面混合了 4 种完全不同的组件
children: [
// 1. 图标组件 (Icon)
Icon(
Icons.star, // 使用 Flutter 自带的星星图标
color: Colors.orange, // 图标颜色
size: 50, // 图标大小
),
// 2. 容器组件 (Container) —— 相当于一个“万能盒子”,可以设置背景色、边距等
Container(
margin: EdgeInsets.all(10), // 外边距
padding: EdgeInsets.all(10), // 内边距
color: Colors.lightBlue[100], // 背景色
child: Text("这是一个带蓝色背景的文字"), // Container 里面再用 child 放了一个 Text
),
// 3. 图片组件 (Image) —— 这里用网络图片举例
Image.network(
'https://picsum.photos/200/100', // 随便一个网络图片地址
width: 200,
height: 100,
),
// 4. 按钮组件 (ElevatedButton)
ElevatedButton(
onPressed: () {
// 按钮点击事件(暂时为空)
},
child: Text('我是一个按钮'), // 按钮里面也是用 child 放了一个 Text
),
],
),
),
);
}
|
组件名 |
类型 |
作用 |
|---|---|---|
|
|
布局组件 |
让子组件垂直排列(用的是 |
|
|
展示组件 |
显示 Material 风格的图标 |
|
|
布局/装饰组件 |
用来给子组件添加背景色、边距、尺寸限制等 |
|
|
展示组件 |
显示网络图片 |
|
|
交互组件 |
一个可点击的凸起按钮 |
|
|
展示组件 |
显示文字(被嵌套在了 |
核心概念:万物皆可嵌套
从上面的例子你会发现两个很有趣的点:
children列表里什么都能装:图标、容器、图片、按钮,随意混搭。- 组件可以无限嵌套:
Column用的是children(因为要装多个)。Container和ElevatedButton自己里面又用了child(因为它们各自只装一个内部元素,比如一段文字)。- 这种“大盒子套小盒子”的方式,就是 Flutter 构建界面的核心逻辑。
当 children 里的组件越来越多、嵌套越来越深时,代码就会变得很长很难读。这时候就正好用得上你最开始提取的那段知识——把其中一部分内容单独抽离成一个自定义组件(继承 StatelessWidget)。
比如,你可以把上面那个 Column 里的“图标+文字+图片”抽离成一个 MyCard 组件,然后 children 里只需要写一句 MyCard() 就行了,代码会瞬间清爽很多
重构后的完整代码
我们把之前那一堆混在一起的代码,拆成了两个自定义组件:一个负责整体布局(MyHomeWidget),一个负责显示那组混合内容(MyCard)
// 1️⃣ 引入 Flutter 的 Material Design 组件库
// 有了它,才能用 MaterialApp、Scaffold、Center、Column、Icon、Container 这些组件
import 'package:flutter/material.dart';
// ============================================================
// 2️⃣ main 函数:Dart/Flutter 程序的入口
// 程序一启动,就会从 main() 开始执行
// ============================================================
void main() {
// runApp():Flutter 的启动函数,把传入的 Widget 作为根组件渲染到屏幕上
runApp(
// ✅ MaterialApp:Flutter 应用的根组件(必须)
// 作用:
// - 自动提供 Directionality(解决文字/图标方向报错)
// - 提供主题、路由、本地化等基础配置
// - 如果不包 MaterialApp,Icon/Text 等组件会报红屏错误
MaterialApp(
// home:指定应用的首页(也就是一启动看到的页面)
home: Scaffold(
// Scaffold:页面脚手架,提供了标准的页面结构
// 它内部可以放 appBar(顶部导航栏)、body(页面主体)、floatingActionButton 等
// 这里我们主要用它的 body 属性来放内容
body: Center(
// Center:让它的子组件在屏幕正中间(水平+垂直都居中)
// child:只能放【一个】子组件
child: MyHomeWidget(), // 调用我们自定义的主页面组件
),
),
),
);
}
// ============================================================
// 3️⃣ 自定义组件 1:MyHomeWidget(主页面内容)
// StatelessWidget:无状态组件
// - 意思是:这个组件一旦创建,内部数据就不会再变了(静态的)
// - 适合用来展示固定内容、布局组合
// - 必须重写 build() 方法,Flutter 通过 build() 知道要画什么
// ============================================================
class MyHomeWidget extends StatelessWidget {
// build 方法:每次组件需要渲染时,Flutter 会自动调用它
// BuildContext context:组件的上下文,用来获取主题、尺寸、导航等信息
@override
Widget build(BuildContext context) {
// Column:垂直布局组件,把子组件从上到下排列
return Column(
// mainAxisSize:主轴(垂直方向)占多大空间
// MainAxisSize.min:只占用刚好够用的高度(包裹内容)
// 如果写 MainAxisSize.max(默认),会撑满整个屏幕高度
mainAxisSize: MainAxisSize.min,
// children:子组件列表,可以放【多个】组件
children: [
// 复用我们自定义的 MyCard 组件(下面定义的)
// 这里相当于"画了第一个卡片"
MyCard(),
// SizedBox:空白间距组件
// 这里创建一个高 20 像素的透明盒子,用来在两个卡片之间留空隙
SizedBox(height: 20),
// 再画第二个卡片
MyCard(),
],
);
}
}
// ============================================================
// 4️⃣ 自定义组件 2:MyCard(一个卡片,包含图标+文字+图片+按钮)
// 同样是无状态组件,只负责展示
// ============================================================
class MyCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 内部也用 Column 让内容垂直排列
return Column(
mainAxisSize: MainAxisSize.min, // 只占用刚好需要的高度
children: [
// ---------- 1. 图标 ----------
Icon(
Icons.star, // 图标样式:星星(Flutter 内置的 Material 图标)
color: Colors.orange, // 图标颜色:橙色
size: 50, // 图标大小:50×50 像素
),
// ---------- 2. 带背景的文字容器 ----------
Container(
// margin:外边距,Container 和其他组件之间的距离
margin: EdgeInsets.all(10), // 上下左右各 10 像素的外边距
// padding:内边距,文字和 Container 边框之间的距离
padding: EdgeInsets.all(10), // 上下左右各 10 像素的内边距
// color:背景颜色
// Colors.lightBlue[100]:浅蓝色(100 是色阶,数值越大颜色越深,最大 900)
color: Colors.lightBlue[100],
// child:Container 里面放的子组件
child: Text("这是一个带蓝色背景的文字"),
// Text:文字组件,直接显示一段文本
),
// ---------- 3. 网络图片 ----------
Image.network(
// 图片的网络地址(从互联网加载)
'https://picsum.photos/200/100',
// 注意:如果手机/模拟器网络不好,图片可能加载失败显示破裂图标
width: 200, // 图片宽度 200 像素
height: 100, // 图片高度 100 像素
// 如果不指定宽高,图片会按原始尺寸显示
),
// ---------- 4. 按钮 ----------
ElevatedButton(
// onPressed:点击事件回调
// 当用户点击按钮时,花括号里的代码会执行
// 现在里面是空的({}),所以点击不会有任何反应
// 以后可以写:onPressed: () { print('按钮被点了'); }
onPressed: () {},
// child:按钮上显示的内容
child: Text('我是一个按钮'),
// ElevatedButton:凸起按钮(有阴影、有背景色)
// 还有 TextButton(文字按钮)、OutlinedButton(边框按钮)等其他样式
),
],
);
}
}
效果如下:

还有另一个组件如下
import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件
//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
//runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
/**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
* Center 是 Flutter 中的一个布局组件(Widget)。
* 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。
child 是 Flutter 里非常常见的一个属性名,中文意思就是"孩子/子组件"。
含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
* */
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Flutter标题"), backgroundColor: Colors.red),
body: MyApp(),
),
),
);
}
//无状态组件
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Text(
"Flutter msg", // 显示的文字内容
textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
style: TextStyle(
color: Color.fromARGB(255, 11, 11, 146), //第一个是参数是透明度,后面3个是RGB颜色值
fontSize: 30.0, //字体大小
fontWeight: FontWeight.w900, //控制文字笔画的粗细程度
),
),
// child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
);
}
}
为什么属性名不一样?
这是 Flutter 的设计约定,记住就行:
|
组件 |
属性名 |
原因 |
|---|---|---|
|
|
|
它不只放一个东西,还有 |
|
|
|
它只放一个东西,统一叫 child |
|
|
| 它只放一个东西,统一叫 child |
|
|
|
能放多个东西,所以用复数 |
💡 本质都一样:都是"往这个组件里塞一个(或几个)子组件"
更多推荐



所有评论(0)