为了账号安全,请及时绑定邮箱和手机立即绑定

Flutter入门:新手快速上手指南

标签:
移动开发
概述

本文介绍了Flutter入门的相关知识,包括环境搭建、基础组件、状态管理以及动画和网络请求等内容,帮助新手快速上手Flutter开发。文章详细讲解了从安装Flutter SDK到创建第一个Flutter项目的过程,并提供了丰富的示例代码。Flutter入门所需的基础组件和布局管理也被详细阐述,包括常用的Widget、状态管理方法以及跨平台UI设计原则。此外,文章还涵盖了数据持久化、网络请求以及应用打包和发布的流程。

Flutter入门:新手快速上手指南
Flutter简介与环境搭建

Flutter是什么

Flutter 是由 Google 开发的一款开源软件开发框架,用于构建跨平台应用。它使用 Dart 语言作为开发语言,并提供了丰富的 Widget 组件来方便开发者构建美观且高效的应用程序。Flutter 的一大亮点是其强大的热重载功能,这使得开发者能够在短时间内看到代码更改的效果,极大提高了开发效率。Flutter 也可以用于开发原生 iOS、Android 应用,甚至桌面应用和Web应用,这也使得它成为许多开发者的选择。

选择安装Flutter SDK

安装 Flutter SDK 需要满足以下条件:

  • 操作系统:支持 Windows、macOS、Linux。
  • Dart SDK:Flutter 需要 Dart SDK 运行。
  • 编辑器:推荐使用 VS Code、Android Studio 或 IntelliJ IDEA。

安装步骤

  1. 下载 Flutter SDK:访问 Flutter 官方网站下载最新版本的 Flutter SDK。

  2. 安装 Dart SDK:确保 Dart SDK 已安装,或者在下载 Flutter SDK 时一并安装。

  3. 配置环境变量:将 Flutter 和 Dart SDK 的路径添加到系统环境变量中。
  4. 验证安装:在命令行中输入 flutter doctor,查看是否安装成功。
flutter doctor

配置开发环境

配置开发环境

在安装 Flutter SDK 和 Dart SDK 后,还需要配置开发环境。具体步骤如下:

  1. 安装 Flutter 插件:在开发工具中安装 Flutter 插件。以 VS Code 为例,可以通过插件市场安装 Flutter 和 Dart 插件。

  2. 配置 Flutter SDK 路径:在编辑器中配置 Flutter SDK 路径。以 VS Code 为例,可以通过设置将 Flutter SDK 路径指定为环境变量中的值。

  3. 配置模拟器或真机:确保 Android 或 iOS 模拟器或真机已正确配置。对于 Android,需要安装 Android SDK 和配置 Android SDK 路径。对于 iOS,需要安装 Xcode 并配置对应的开发环境。

创建第一个Flutter项目

创建第一个项目

  1. 在终端中输入以下命令创建一个新的 Flutter 项目:
flutter create first_flutter_app
cd first_flutter_app
  1. 使用编辑器打开项目文件夹,可以使用 VS Code 打开:
code .
  1. 查看项目文件结构:
first_flutter_app/
├── android/
├── ios/
├── lib/
│   └── main.dart
├── test/
├── pubspec.yaml
└── README.md
  1. main.dart 文件是项目的入口文件。打开 main.dart 文件,可以看到默认代码如下:
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
  1. 运行项目:
flutter run
  1. 运行结果将在模拟器或真机上显示一个带有按钮的界面,点击按钮会增加计数。
基础组件与布局

常用Widget介绍

在Flutter中,一切界面元素都是基于Widget构建的。以下是几个常用的Widget示例:

  • Text:显示文本内容。
  • Container:提供填充、边距、背景颜色、边框等属性。
  • Column:垂直布局。
  • Row:水平布局。
  • Stack:堆叠布局。
  • ListView:列表布局。
  • Scaffold:包含一个顶部AppBar和一个底部主体内容的布局。
  • Center:将子Widget居中显示。

StatelessWidget与StatefulWidget

StatelessWidget

StatelessWidget 是一个状态不可变的Widget。在生命周期中,如果它的输入没有改变,它就不会重新构建自身。它主要用来表示那些不需要改变状态的UI元素。

import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('Hello, StatelessWidget');
  }
}

StatefulWidget

StatefulWidget 是一个状态可以改变的Widget。在生命周期中,它可以通过状态的变化来重新构建自身。它主要用来表示那些需要动态更新的UI元素。

import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Counter: $_counter'),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

布局管理:Row, Column, Container等

Row与Column

RowColumn 是常用的布局Widget,它们分别用于水平和垂直的布局。

import 'package:flutter/material.dart';

class LayoutExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          children: [
            Text('Row 1'),
            Text('Row 2'),
          ],
        ),
        Column(
          children: [
            Text('Column 1'),
            Text('Column 2'),
          ],
        ),
      ],
    );
  }
}

Container

Container 是一个多功能的布局容器,可以设置颜色、边框、填充、对齐方式等。

import 'package:flutter/material.dart';

class ContainerExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 200,
      height: 200,
      color: Colors.blue,
      padding: EdgeInsets.all(10),
      child: Center(
        child: Text(
          'Container Example',
          style: TextStyle(color: Colors.white),
        ),
      ),
    );
  }
}

跨平台UI设计原则

  • 一致性:确保应用在iOS和Android平台上看起来和行为都一致。
  • 简洁性:保持界面简洁明了,避免过多复杂的布局和元素。
  • 响应性:确保应用在不同设备和屏幕尺寸上都能良好显示。
  • 可用性:确保用户容易理解和操作界面。
控制状态与事件处理

状态管理基础

状态管理是Flutter开发中的一个关键部分。常见的状态管理方式包括:

  • 状态嵌套(State Nesting):通过StatefulWidget嵌套多层状态。
  • 单一状态树(Single State Tree):使用Provider、Bloc、Riverpod等库管理全局状态。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class CounterProvider extends ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => CounterProvider(),
      child: MaterialApp(
        home: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterProvider = Provider.of<CounterProvider>(context);
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '${counterProvider.counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
            ElevatedButton(
              onPressed: () {
                counterProvider.increment();
              },
              child: Text('Increment'),
            ),
          ],
        ),
      ),
    );
  }
}

事件监听与响应

事件监听

事件监听通常通过设置事件处理器来实现。例如,点击按钮时的响应处理。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Event Listener Example')),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              print('Button Pressed');
            },
            child: Text('Click Me'),
          ),
        ),
      ),
    );
  }
}

事件响应

事件响应通常通过调用函数来实现。例如,点击按钮时的计数器增加。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Event Response Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Button pressed $_counter times',
                style: Theme.of(context).textTheme.headline4,
              ),
              ElevatedButton(
                onPressed: _incrementCounter,
                child: Text('Increment'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

数据绑定与形式验证

数据绑定

数据绑定通常通过TextEditingController来实现。例如,用于输入框的文本绑定。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController _textEditingController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Data Binding Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextField(
                controller: _textEditingController,
                decoration: InputDecoration(
                  labelText: 'Enter text',
                ),
              ),
              Text(
                _textEditingController.text,
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

形式验证

形式验证通常通过TextEditingControlleronChanged回调来实现。例如,验证输入内容是否为空。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  TextEditingController _textEditingController = TextEditingController();

  void _validateInput() {
    if (_textEditingController.text.isNotEmpty) {
      print('Input is valid');
    } else {
      print('Input is empty');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Form Validation Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextField(
                controller: _textEditingController,
                onChanged: (value) {
                  _validateInput();
                },
                decoration: InputDecoration(
                  labelText: 'Enter text',
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

导航与页面跳转

导航与页面跳转

导航与页面跳转是移动应用中常见的功能。Flutter 提供了丰富的导航机制,例如 NavigatorPageRouteBuilder

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondPage()),
            );
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back'),
        ),
      ),
    );
  }
}
动画与特效

Flutter动画分类

Flutter 的动画可以分为以下几类:

  • 基本动画:简单动画,如改变颜色、大小、位置等。
  • 复杂动画:通过组合多个动画效果实现更复杂的动画。
  • 自定义动画:根据需求自定义动画逻辑。
  • 物理动画:模拟物理效果的动画,如弹簧动画、惯性动画等。

基本动画实现

动画启动与停止

动画的启动与停止通常使用 AnimationController 来控制。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _startAnimation() {
    _controller.forward();
  }

  void _stopAnimation() {
    _controller.stop();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Basic Animation Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              AnimatedContainer(
                width: _controller.value * 100,
                height: _controller.value * 100,
                decoration: BoxDecoration(color: Colors.blue),
                duration: Duration(seconds: 1),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _startAnimation,
                child: Text('Start Animation'),
              ),
              ElevatedButton(
                onPressed: _stopAnimation,
                child: Text('Stop Animation'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

动画实现与应用实例

动画的实现可以通过 AnimatedBuilderAnimatedWidget 来实现。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
    _animation = CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _startAnimation() {
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Basic Animation Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              AnimatedBuilder(
                animation: _animation,
                builder: (context, child) {
                  return Container(
                    width: _animation.value * 100,
                    height: _animation.value * 100,
                    decoration: BoxDecoration(color: Colors.blue),
                    child: child,
                  );
                },
                child: Center(
                  child: Text('Hello'),
                ),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _startAnimation,
                child: Text('Start Animation'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

动画应用实例

进度条动画

进度条动画通过 FractionAnimation 来实现。

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _startAnimation() {
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Progress Bar Animation Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              LinearProgressIndicator(
                value: _animation.value,
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _startAnimation,
                child: Text('Start Progress'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

动画性能优化

性能优化策略

  • 避免不必要的动画:只在需要的地方使用动画。
  • 复用动画组件:如果同一个动画组件被多次使用,考虑复用。
  • 避免在动画中调用 setState:尽量减少不必要的状态更新。
  • 使用更轻量级的动画组件:如 AnimatedBuilder
数据持久化与网络请求

SharedPreferences简介

SharedPreferences 是 Flutter 中用于存储键值对的本地存储库。它支持基本的数据类型,如字符串、整数和布尔值,适用于保存一些轻量级的数据。

数据存取操作

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late String _storedData;

  @override
  void initState() {
    super.initState();
    _loadData();
  }

  void _saveData(String data) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('storedData', data);
  }

  void _loadData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String data = prefs.getString('storedData') ?? 'Initial Value';
    setState(() {
      _storedData = data;
    });
  }

  void _updateData(String newData) async {
    _saveData(newData);
    _loadData();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('SharedPreferences Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Stored Data: $_storedData',
                style: Theme.of(context).textTheme.headline4,
              ),
              ElevatedButton(
                onPressed: () {
                  _updateData('New Data');
                },
                child: Text('Update Data'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

使用HTTP库进行网络请求

http 库是 Flutter 中的一个常用网络请求库。它提供了简单的 API 来发送 HTTP 请求,并处理响应。

网络请求的错误处理与调试

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late String _response;
  late String _error;

  Future<void> _fetchData() async {
    try {
      final response = await http.get(Uri.parse('https://api.example.com/data'));

      if (response.statusCode == 200) {
        setState(() {
          _response = json.decode(response.body)['message'];
          _error = '';
        });
      } else {
        throw Exception('Request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      setState(() {
        _response = '';
        _error = e.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('HTTP Request Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                _response ?? 'No data yet',
                style: Theme.of(context).textTheme.headline4,
              ),
              Text(
                _error,
                style: TextStyle(color: Colors.red),
              ),
              ElevatedButton(
                onPressed: _fetchData,
                child: Text('Fetch Data'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

网络请求的错误处理与调试

在网络请求中,错误处理和调试是两个重要的方面。通常可以通过捕获异常和打印日志来处理错误。

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late String _response;
  late String _error;

  Future<void> _fetchData() async {
    try {
      final response = await http.get(Uri.parse('https://api.example.com/data'));

      if (response.statusCode == 200) {
        setState(() {
          _response = json.decode(response.body)['message'];
          _error = '';
        });
      } else {
        throw Exception('Request failed with status: ${response.statusCode}');
      }
    } catch (e) {
      setState(() {
        _response = '';
        _error = e.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('HTTP Request Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                _response ?? 'No data yet',
                style: Theme.of(context).textTheme.headline4,
              ),
              Text(
                _error,
                style: TextStyle(color: Colors.red),
              ),
              ElevatedButton(
                onPressed: _fetchData,
                child: Text('Fetch Data'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
发布与打包应用

应用打包流程

打包应用程序是开发过程中的最后一步,主要步骤如下:

  • 清理构建缓存:确保没有残留的构建信息干扰打包。
  • 选择打包平台:根据目标平台选择相应的打包命令。
  • 运行打包命令:使用 flutter build 命令来打包应用。
  • 生成安装文件:生成可分发的安装文件,如 .apk.ipa
  • 上传到应用商店:将安装文件上传到相应的应用商店。

清理构建缓存

flutter clean

打包应用

  • 打包 Android 应用:
flutter build apk
  • 打包 iOS 应用:
flutter build ios --release

生成安装文件

  • 生成 Android 安装文件:
flutter build apk --release
  • 生成 iOS 安装文件:
flutter build ios --release

上传到应用商店

上传到Google Play商店

  1. 登录 Google Play 开发者控制台。
  2. 创建一个新的应用列表。
  3. 填写应用的基本信息,如应用名称、图标、版本号等。
  4. 上传生成的 .apk 文件。
  5. 提交审核。

上传到App Store商店

  1. 登录 Apple Developer Connect。
  2. 创建一个新的应用列表。
  3. 填写应用的基本信息,如应用名称、图标、版本号等。
  4. 上传生成的 .ipa 文件。
  5. 提交审核。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消