Flex入门指南—PHP开发者 第1部

作者: Mihai Corlan— Adobe  Platform Evangelist

从上个世纪 90 年代末开始,我一直从事与 Web 相关的技术,而且我接触的第一个服务器端技术是 PHP 。后来,我转向 ColdFusion  Java  的开发工作,但我始终认为自己是一个 PHP 开发人员。当 AJAX 技术出现时,我开始与 Prototype  script.aculo.us 等架构打交道,并且着手创建自己的架构。

2006 年底,我开始体验进行 Flex 开发。这有点类似速成学习班,因为我需要在大约 4-6 个星期内为 FDS (( Flex Data Services,  现在称为 LiveCycle Data Services )将要问世的版本创建一个演示应用程序。尽管当时我是一个 Flex  FDS 的新手,但该项目进展顺利,而且我非常享受这次开发以及学习过程。

然而,在享受的同时,我感觉到 Flex 的不同之处。我的意思是当我在进行 ColdFusion  Java Web  的开发工作时,我并没有觉得其与 PHP 相比有不同之处。这仅仅是一个寻找正确的 API 以及适应特定语言的问题。后来,当我开始在 DHTML 之上进行 AJAX 开发时,我感觉也没有不同之处。你仍然使用相同的技巧、利用服务器端语言来创建大多数网站,以及在网站各处插入一些趣味画面(对于本案例来说,它们是一些 AJAX widgets )。

当我使用 Flex 创建我的第一个 Web 项目时,我的天啊,这是一个巨大的转变。客户端和服务器之间的清晰分离(除了服务器侧的业务逻辑之外的客户端侧业务逻辑)、需要进行编译而不是翻译的客户端侧技术、以及客户端的两种语言等,所有这些均需要用一种不同于传统 Web 开发的思维方式进行思考。

这就是我写作本文的原因。我希望与你分享一些与 PHP 相关的 Flex 特定的技巧。同时,我还希望通过将 Flex PHP 进行比较引入 Flex 概念,当然它们的比较必须是有意义的。因此本文的目标读者是:

·  希望学习更多关于 Flex  Action Script 3  而不只是通过简单定义能够提供的内容的 PHP 开发人员

·  已经进行 Flex 应用程序编码尝试并且希望更广更深地了解 Flex PHP 开发人员

本文没有涉及的内容是什么?试图改变你或说服你让你相信 Flex 优于 X Y 不是我的本意。我坚信项目具有各种各样的类型,并且利用不同的工具能够完成这些项目。

另外,本文没有为 Flex  ActionScript 3 提供完整的文件资料。目前,市面上有几十本专著的数百页资料论述该主题。关于 Flex 的文章也有成千上万篇。而我的意图是在将 Flex 概念与 PHP 类似概念进行关联是有意义的情形下,针对最重要的议题为你提供足够的信息。为了使得本文更为实用,我对其结构进行适当的安排并且尽力避免对细节进行过多的赘述。在本文的结尾部分,我提供了 Adobe AIR  的简介和一些附加参考资料,以便于你能够查阅与本主题相关的更多详细信息。

最后需要说明的是,对于本文给出的大部分范例,我选择使用 Flex 3 进行编程。作出这样的选择有如下几个原因:首先,在写作本文时, Flex 4 仍然是 beta 版本。其次,由于 Flex 4 主要是 Flex 3 的演化版本,因此这里涉及的大部分应用程序能够适用于 Flex4 ,只需进行少许更改即可。在一些范例中,我将指出这些不同之处。对于 PHP 范例,我选择使用 PHP 5.3 作为编程参考语言。前面已经给出说明,现在让我们来看看下面的本文目录,然后开始用功学习。

 

1.  什么是 Flex ?  

1.  Flex:  一个框架绑定的两种语言

2.  为什么你需要关注 Flex

3.  从瘦客户端向智能 / 富客户端演化

2.  MXML 语言简介  

1.  MXML ActionScript 3 之间的混合

2.  CSS  式样

3.  在运行时修改 MXML 代码

3.  ActionScript 3 语言简介  

1.  隔离语句

2.  数据类型、变量和常量

3.  函数和匿名函数(闭包)

4.  OOP :类和 接口

5.  变量作用域

6.  数组

7.  命名空间

8.  XML 的配合

9.  动态 ActionScript

4.  Flex  是异步的

5.  Data  绑定、元数据标签和 反射

6.  我的数据在哪里?将它显示出来 !

7.  Flex PHP  项目的用户鉴权

8.  建立 Flex PHP  项目  

1.  Flex SDK

2.  Flex Builder / Flash Builder

3.  调试 Flex  应用程序

9.  什么是 Adobe AIR?

10.  下一步计划是什么  ?

11.  总结

 

什么是 Flex

最简单的回答是: Flex 仅仅是创建 Flash 应用程序的另一种方法。 Flash 应用程序是在 SWF 文件中编译的,并且由 Flash Player 在浏览器中进行播放。为什么我们需要使用另一种方法创建 Flash 应用程序?传统的 Flash 应用程序是使用 Flash 制作工具创建的。如果你查看一下该工具,你会发现它主要适用于设计人员。其中包括一个舞台( stage ),一条时间轴线( timeline )以及各种绘画工具等。

当你在开发应用程序并且追求开发效率时,你需要各种组件,你希望通过重用代码尽可能地提高开发效率,最后但并不是最不重要的一点是,你需要一个新型的 IDE  

因此,一种修正的回答可能是: Flex 是一种能够帮助开发人员快速创建富因特网应用程序( Rich Internet Application )的开源框架,这些应用程序能够在 Flash Player 中运行。在 2006 年的今天,随着 Flex 2 Flash Player 9  ActionScript 3 的推出,该框架已经趋于定型。目前的版本是 Flex 3 2010 初,其下一个版本 Flex 4 将要面世。

 

Flex:  一个框架绑定的两种语言

 

Flex 之下,你将发现下列语言和工具:

·  两种语言: MXML ActionScript 3 Flex 提供两种语言以便创建 Flex 应用程序。在下面的章节中,我将进一步地讨论每种语言。

·  一个富组件库

·  各种编译器和调试器

·  用于编译和调试 Flex 应用程序的各种命令行工具

由于 Flex 是一种开源框架,因此我极力推荐你访问该计划的主页 http://opensource.adobe.com/flex 并且下载相关的 SDK 。你能够从组建库中查阅到所有组件的源代码,你能够查询相关的开放程序缺陷和功能库( http://bugs.adobe.com/flex ),以及查看各种规范的 wiki  页面。

Flex 提供的部分效率改善应该归功于其海量组件库。该组件库包含了所有你能够想象的 UI 组件(例如,各种输入框( input box )、面板( panel )、视窗( window )、滑动条( slider )、数据网格( data grid )、组合框( combo box )、折叠显示( accordio )和 Tab 设置( tab set )等等)。另外,该组件库还包含各种布局容器和表单元素。在下面的图中,你能够看到 Flex 3 可以提供的各种 UI 组件的屏幕截图(点击可以放大)。

 

如果这些组件仍然不够使用,则你可以进入相应的源代码,扩展这些组件以创建你自己的组件或从零开始创建新的组件。

 

为什么你需要关注 Flex

 

在深入探讨什么是 Flex 之前,让我们暂停一下,重温为什么你需要关注 Flex 的原因。

传统的 HTML Web 应用程序具有 请求 - 响应 架构。在浏览器发送一个请求之后,相应的服务器回送一个页面,这样的周期不断重复。 HTML   CSS 为呈现该信息提供了卓越的选择,   正如可提出证据加以证明的那样,这是目前最佳的选择之一。然而,随着时间的推移,这种架构不仅局限于静态呈现,而已经扩展至应用程序平台。利用脚本技术,我们尝试创建动态页面以及设计服务器使得其能够对特定请求给出响应。更进一步地,通过添加 DHTML  AJAX  ,我们能够将新的气息带入由 Web 服务器支持的页面:用户能够与载入页面互动并且在无需刷新整个页面的情形下改变相关的视图。

随着这些技术的演化,各种复杂的应用程序不断出现。一些 Web 应用程序已经开始复制许多桌面应用程序的功能而且同时能够保持 Web 应用程序的便利性(只要有浏览器和因特网连接的地方就能够使用 Web 应用程序)。因此,各种在线版本的电子制表软件和文本编辑器不断涌现。

然而,从可用性的角度来看,在线应用程序的用户友好界面要比桌面应用程序差。同时,如需创建这些复杂的 Web 应用程序,你必须掌握许多技术( JavaScript DHTML CSS AJAX  库以及服务器端等技术   )的各种技巧,并且你必须具有处理不同浏览器之间差异的经验以及了解他们是如何实现 HTML/CSS/JS 的。因此, 2002 年, Macromedia 提出了术语 RIA Rich Internet Applications )来描述一种结合了 Web 应用程序的优势和桌面应用程序的益处的新型应用程序。能够实现这一新型应用程序的技术就是 Flash Player

通常,如果你希望创建应用程序(而不仅仅是一个 Web 站点或 Web 页面),你可以使用 Flex 来实现。一些应用程序几乎不能使用 HTML/JavaScript 来创建,而另外一些应用程序很难跨浏览器一致运行。 Flash Player  能够提供最好的图形引擎,它已经安装于 98%  的具有因特网连接的计算机,并且能够将声音和图像视为 一等公民 。它支持麦克风( microphone )和 Web 摄像( webcam )功能、支持流媒体和数据推送( streaming and data pushing )服务、以及提供卓越的字体排印( typography )功能,其支持的功能可以填满很长的清单。

请看看下面三个应用程序以便了解使用 Flex 能够出现什么样的奇迹 :

·  SumoPaint   是一个免费使用的图像编辑应用程序;

·  Mindomo 是一个思维导图应用程序;

·  Times Reader 是一个源自《纽约时报》( The New York Times )的应用程序。

随着时间的推移,其他技术已经进入 RIA 领域。除了使得如 Gmail   Google Spreadsheets  等应用程序成为现实的 AJAX  不断发展之外,今天,我们还能够看到源自 Microsoft Silverlight 应用程序以及源自 Sun JavaFX 应用程序。

 

从瘦客户端向智能 / 富客户端演化

让我们回到浏览器以及 Web 应用程序是如何传送的。当浏览器发出一个请求,相应的服务器将使用静态内容( HTML/CSS/JS  代码)和脚本(这些脚本可能查询数据库或调用其他脚本,但最终他们会输出 HTML/CSS/JS )的组合来准备一个页面。该页面由浏览器载入并且显示出来。在此,一个关键元素是,通常该页面(或响应)具有显示标记( presentation markup  )以及烘焙至相同消息的数据。

当应用程序的新状态需要呈现时,浏览器发出一个新的请求,之后相应的服务器将准备请求的页面。而客户端 仅仅 显示该数据。

Flex 应用程序以不同的方式工作。服务器发送已编译过的 Flex 应用程序  (SWF  文件 ,该应用程序能够在浏览器中使用 Flash Player 插件运行。通常,该 SWF 文件只能支持客户端侧的业务逻辑。如果需要数据(例如来自数据库),则 Flex 应用程序能够发送请求以获得这些数据。服务器只发送数据(数据的格式可以为 XML JSON AMF3 ),并且客户端能够知道如何显示该数据。我们这里讨论的是面向服务的架构:

Flex 应用程序实际上是客户端 一种能够使用由服务器提供的数据服务的客户端。该应用程序能够在浏览器不刷新页面或不重新装载 SWF 文件的情形下变更状态。该应用程序是一种能够不仅仅显示数据的客户端。因此,通过利用 Flex  Flash Player 能够创建几乎任何对象,这些对象对于在 Web 上部署各种游戏、应用程序以及 widget 具有重要意义,而这些游戏、应用程序以及 widget 能够与 古典 ”Web 应用程序以及其他应用程序进行集成。

到此为止,已经谈论太多的枯燥理论,让我们看看一些程序代码吧!

MXML 语言简介

MXML 是一种陈述性的、基于 XML 的语言。在 Flex 应用程序中,你可以使用 MXML 语言快速地创建应用程序的结构 / 外观。在 Flex 中,你使用 MXML 能够创建的应用程序,也可以使用 ActionScript 3 来创建。然而,反向操作不能成立。

如果你能够使用 ActionScript 3 来创建可以使用 MXML 完成的应用程序,那么为什么 MXML 会首先出现?通常学习和理解利用 XML 语言描述的用户界面比利用命令式语言描述的用户界面要简单得多。这样利用 XML 语言编写的用户界面将会具有较少的代码。另外,为陈述性语言建立工具比为命令式语言也简单得多。下面是利用 MXML 实现的一个范例 “Hello world!”

   1:  <Label text= "Hello World!"  fontSize= "14"  color= "red"  x= "100"  y= "50" />

在这段代码中,我使用了一个名称为 Label Flex 组件在屏幕上显示若干文本字符。我将文本的属性设置为我期望的文本格式。另外,我希望能够对外观及该 Label 在屏幕上的位置进行(少许)客户化处理。因此,我使用了属性 fontSize color  y 。我相信你会同意这是非常易于理解和学习的范例。

现在,考察一下利用 ActionScript 3 实现的相同范例:

我使用了 7 行代码来实现前面我仅用包含一个标记和若干属性的 MXML 实现的范例!现在,可以设想一下在一个真正的应用程序中,你采用大量的控件,并且在不同的容器中进行分组。那么,维护利用 MXML 编写的代码要比维护使用几百行 ActionScript 3 编写的代码更为简单。

尽管你能够使用 MXML 描述你的应用程序,但你不能使用 MXML 实现你的应用程序的业务逻辑。而你可以利用 ActionScript 3 实现这一目的。

Flex 应用程序能够运行于 Flash Player ,而 Flash Player 只能支持 ActionScript 2  ActionScript 3 。这意味着你在应用程序中编写的任何 MXML 代码必须通过相应的 MXML 编译器转换成 ActionScript 3 代码。然后,该代码通过 ActionScript 编译器被转换成 Flash Player 支持的字节代码( bytecode )( SWF 文件)。

因此,几乎每个 MXML 组件的后面均存在一个 ActionScript 3 类(实际上,有些 MXML 标记没有相应的 ActionScript  类,例如 Script     Model )。在下面的范例中,这是一个源自 Label   类的一个代码片段(  snippet  ):

在任何 Flex 应用程序中,你应该至少具有一个 MXML 文件,这是主应用程序。例如,下面是 “Hello World!”  应用程序的完整代码。

根节点必须总是 Application ,而且这是定义命名空间的位置。在本范例中,我仅仅提供一个用于 MXML 语言和 Flex 组件的命名空间: mx (上面的代码是使用 Flex 3 编写的。如果使用 Flex 4 ,则代码具有微小的差异,其中声明了多个命名空间)。

如果你编写自定义组件,则必须为其添加一个命名空间。例如,在下面的代码中,我声明了第二个命名空间指向我所创建的所有组件(在本范例中,我使用了一个我自己创建的名称为 MyCustomLabel   的自定义 label  组件):

到目前为止,你也许想知道 Flex 应用程序是如何处理不同页面的。对于 HTML Web 站点,通常不同状态是在不同页面实现的。而 Flex 应用程序与桌面应用程序非常相似。这意味着你只需使用一个 MXML 文件,即可在该页面上显示应用程序的不同状态。 Flex 能够提供许多手段来实现这一目的,这些方法包括使用如折叠显示( Accordion )、 Tab 设置浏览器( Tabsets navigator )和牌布局管理器( Card layout )的 Flex 组件以及 Flex 模块等。

你已经看到 MXML 代码能够用于定义应用程序的外观。但你也能够利用它并且通过扩展现有 Flex 组件创建自定义组件。让我们来看一个范例。假设在你的应用程序中具有若干表单,这些表单具有两个按钮: Save  Cancel 。观察一下该 MXML 自定义应用程序的代码(该代码是在一个名称为 FormButtons.mxml 的文件中创建的。所有 MXML 文件必须使用 mxml   扩展名)。

当你创建自定义应用程序时,你能够选择需要扩展的任何组件(但你不能对 Application 进行扩展)。我选择扩展 HBox  (Horizontal Box) ,这是一个能够在相同行显示所有 children 的容器。在该容器的内部,我添加了两个按钮,一个用于 Save ,另一个用于 Cancel 。我还为每个按钮设置了 id   属性。你可以使用 id   属性值作为引用代码其他部分的对象的一种方式。这与在 ActionScript 代码中声明一个变量的方式是相同的。

现在,让我们看看你如何在一个 Flex 应用程序中使用该自定义组件:

Below you can see how the application looks:

你也许会认为在 MXML 中你只能使用视觉 Flex 组件(即最终能够被显示的组件)。实际上,这是不确切的。你可以使用表示数据的 MXML 标签(用于存储数据的对象)或操作数据的组件(能够从服务器查询数据或向服务器发送数据的组件)。下面,你能够看到一个 generic 对象组件的范例,该组件具有一个名称为 name 的特性( property ):

   1:  <mx:Object id= "myObj"  name= "Mihai Corlan" />

正如我前面所述的那样,与 Flex 相伴的所有(几乎所有) Flex 组件均具有 ActionScript 类,该类能够实现视觉外观(如果有的话)以及相应的逻辑。当你选择使用 ActionScript  而不是  MXML 创建一个自定义组件(不论其是否是视觉组件)时,你必须记住存在以下限制:在不带自变量的情形下,该类的构造器( constructor )必须能够被调用(如果具有自变量,则这些自变量应该具有默认值)。

 

MXML ActionScript 3 之间的混合

返回到自定义组件 FormButtons  ( 具有两个按钮的组件 ) ,你也许注意到一个问题:如果你希望在一个 Save     Cancel   标签不起作用的地方使用该组件将会怎样?你应该创建另一个带有你期望的标签(例如 Show     Hide )的自定义组件吗?当然,这是一个选择,但这个组件不能缩放或外观不太优雅!你所真正期望的是一个更为通用的组件,以及一种使用代码变更组件的方法。这是为什么迟早你不得不在 MXML 代码中添加 ActionScript 代码。

在下面的范例中,我在组件的 MXML 代码中添加了 ActionScript 代码以定义两个存储了按钮使用的标签的变量。注意,我使用了一个新的标签 Script ,并且在该标签之中使用了 CDATA 这是因为在 XML 文档之中,像 > < 等字符是非法的(如果它们没有换码)。另外,现在我将不会把太多重点放在 ActionScript 代码上,但我将在后面的章节中更深入地讨论 ActionScript 代码。

我定义的变量可以在使用该组件的 Flex 应用程序中设置。下面,让我们来看看在使用新的自定义组件之后,变更的 Flex 应用程序代码的构成。

注意, FormButtons   标签具有两个属性:   label1   label2 。这是为什么你能够在这些按钮上设置期望显示的文本。并且这是你使用的机制以便将更多的行为添加至 MXML 组件(使用 ActionScript 代码)。在真正的应用程序中,你可能希望将一个行为与每个按钮进行绑定,以便当按下按钮时,就会产生相应的结果。你可以使用 ActionScript 代码编写通过按下按钮即可触发的各种函数。

另外,还有一种在 MXML 至添加 ActionScript  代码的方法。你可以先创建一个 ActionScript  文件(在本范例中,该文件的名称为 buttons.as ),然后将该文件包含于 MXML 文件中。你可以通过添加一个具有 source   属性的   Script   标签实现这一操作   ,而该属性指向该 ActionScript 文件。下面是这一方法的代码。

现在 让我们后退一小步 然后推测一下当 MXML 编译器解析 FormButtons.mxml   文件时会发生什么情况。你已经知道所有代码将会转换成 ActionScript 代码。但对于我添加的现有 ActionScript 代码(两个变量)会发生什么情况呢? MXML 编译器将会把每个 MXML 文件编译至一个 ActionScript  类。在这种情形下,我将获得一个名称为 FormButtons (因为这是该文件的名称并且它可以用于该类的名称)的类,该类扩展了 HBox   组件(因为我选择了   HBox   作为该组件的根节点)。该类中的所有 ActionScript 代码将会变成该类的成员:变量(例如本范例中的变量)将会变成实例变量,并且函数将会变成实例方法。

 

CSS 式样

到目前为止,你也许想知道你是否能够改变视觉 Flex 组件的外观。 Flex 组件具有类似 HTML CSS 的技术?答案是肯定的, Flex  支持  CSS 。在 Flex 4 中,对 CSS 的支持已经扩展至允许不仅可以基于类的名称而且可以基于 ID 进行式样定义,以支持伪选择符( pseudo-selector )(例如,对于一个按钮来说,你应该具有下选择符( down selector )、上选择符( over selector )等等)以及其他更多功能。

与在 HTML 中一样,式样可以在行中(在 MXML 代码内部)定义或在一个独立的文件中定义。让我们先回到自定义组件 FormButtons 然后设置若干式样。如果你选择在一个独立的文件中定义试样,则必须使用一个 Style   标签并且将路径设置为   source   属性中的式样文件。

我创建了一个名称为 Button1   CSS 类,该  CSS 类定义了标签颜色以及字体大小。然后,我使用第一个按钮的 styleName   属性将式样设置为第一个按钮。至此,该应用程序如下图所示:

CSS 式样在运行时能够改变(在 Flex 应用程序载入浏览器之后),并且该应用程序的外观也会立即随着改变。

Flex 4 中, Adobe 添加了名称为 MXML 用于图形的新语言,该语言添加了原语( primitive )、效果( effect )、面具(  mask   2D  转换功能。你可以使用这些新的标签在 MXML 文件中创建皮肤( skin )类,然后你能够将该类设置为你期望对其进行皮肤粘贴的组件。在下图中,你能够看到一串以 Flex 4 为皮肤的图像。左边给出了该串图像的默认状态,而右边给出了该串图像的打开状态。你可以点击 这里   观看处于运行状态的应用程序。

当你在关于 Flex 应用程序外观的自定义的文档中徘徊时,你也许能够理解术语 皮肤粘贴 的含义。你可以进行图形皮肤粘贴( graphical skinning  )或编程皮肤粘贴( programmatic skinning  )以便改变相应的外观。点击 这里   可以获得关于这方面问题的佳文。    

 

在运行时修改 MXML 代码

有时候你希望在运行时变更 UI 组件。也许你希望根据你从服务器中检索到的数据来实时地建立一个表单。同样,你也能使用 ActionScript 代码实现这一任务。任何视觉 Flex 组件均具有添加一个新子类、移除一个新子类以及获取所有子类等方法。如果你愿意,你可以将这些方法与在 HTML 中使用 JavaScript 改变 DOM 的方式进行比较。然而,它们之间存在差异:利用 JavaScript 你可以注入你从服务器检动态索到的 HTML 代码(通过一个 AJAX  调用)。但在 Flex 中,这是不可能,并且在 Flex 中不存在 eval()   函数。然而,在主应用程序载入之后,有方法可以载入其它 Flex 应用程序或 Flex 模块。

当你了解一个组件的所有不同视图时,你能够使用 MXML  States   来实现相同组件或应用程序的不同状态。状态功能是 Flex 4 对比 Flex 3 的实现方式改善非常显著的地方,这使得这些状态更加易于使用并且添加更多功能。在 Flex 4 ,状态的工作方式如下:

1.  你可以定义若干状态并且指定默认状态

2.  你能够指定在一个特定的组件应该出现在哪些状态中

3.  你可以指定在状态出现的位置每个状态的任何属性的独立值

假设你希望创建一个处理应用程序登录功能的组件。你希望使用该组件显示登录表格,并且在登录成功之后,你希望显示退出按钮以及用户姓名。

下面是使用 Flex 4 创建的登录 / 退出组件:

上面的代码应该是很容易理解的。作为顶部容器,我使用一个具有设置为 HorizontalLayout   布局的 Group 组件(这与用于上面范例 Flex 3 中的 Hbox 具有相同的效果)。我已经在该文件的顶部为该组件定义了可用状态。接下来,我还定义了按钮、文本输入和标签。注意一下指定该组件在什么状态下会出现的 includeIn   属性。另外,文件中还包含一个 excludeFrom   属性。如果你希望在所有状态下定义一个按钮,则无需为这两个属性指定任何状态。最后,你可以看到我为这两个按钮的点击属性指定了一个表达式。例如,表达式 click=”{currentState=’logged’}”   告诉 Flex  当按钮被点击时,应该将该组件的状态改变为名称为 logged 的状态。

尽管我一直在讨论 MXML 语言,但我已经将越来越多的 ActionScript 代码加入了这些范例。这是一个迹象:该到讨论第二种 Flex 语言 ActionScript 3 的时候了。

【国内下载】Flex 3 Builder :http://g.csdn.net/5120749
【国内下载】Adobe Flash Builder 4 :http://g.csdn.net/5105812
【官方下载】Flex 3 Builder :http://g.csdn.net/5121278
【官方下载】Adobe Flash Builder 4 :http://g.csdn.net/5120750


未完待续-----

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值