前端项目代码规范:打造高效开发基石

目录

一、前端代码规范的重要性

二、制定代码规范的前期准备

2.1 了解团队开发习惯

2.2 参考业界成熟规范

三、代码规范细则

3.1 命名规范

3.1.1 项目命名

3.1.2 文件命名

3.1.3 变量、函数、类命名

3.2 代码格式规范

3.2.1 缩进与空格

3.2.2 分号、括号使用

3.2.3 代码排序

3.3 注释规范

3.3.1 功能性注释

3.3.2 文档注释

3.3.3 单行注释

3.4 编程风格规范(以 JavaScript 为例)

3.4.1 变量声明

3.4.2 函数式编程

3.4.3 最小函数准则

3.4.4 解构赋值

四、规范落地与维护

4.1 引入代码检查工具

4.2 团队培训与沟通

4.3 定期回顾与更新

五、总结与展望


一、前端代码规范的重要性

在前端项目开发的广袤天地里,代码就如同构建大厦的砖石,而代码规范则是确保这座大厦稳固、美观且易于维护的蓝图。随着前端技术的迅猛发展,项目规模日益庞大,代码规范的重要性愈发凸显。

想象一下,一个没有统一代码规范的前端项目,就像是一座杂乱无章的城市。开发人员各自为政,代码风格五花八门,变量命名随心所欲,代码结构混乱不堪。这样的项目,在后续的维护过程中,就如同在迷宫中寻找出口,每一次代码的修改都可能引发一系列意想不到的问题。比如,当需要修改某个功能时,开发人员可能需要花费大量的时间去理解代码的逻辑,因为不同的代码风格和命名方式让人摸不着头脑。这不仅增加了开发成本,还可能导致项目进度的延误。

从团队协作的角度来看,缺乏代码规范更是一场灾难。在一个团队中,不同的开发人员有着不同的编程习惯和思维方式。如果没有统一的代码规范,那么在代码合并时,就会出现各种冲突和问题。这不仅会影响团队的协作效率,还可能破坏团队的和谐氛围。例如,有的开发人员喜欢使用驼峰命名法,而有的则喜欢使用下划线命名法,当他们的代码合并到一起时,就会出现命名不一致的问题,这会给后续的开发和维护带来很大的困扰。

而规范的前端代码,则为我们带来了诸多好处。它就像是一把万能钥匙,能够轻松打开代码可读性和可维护性的大门。规范的代码具有良好的结构和清晰的逻辑,如同一条清澈的溪流,让人一眼就能看到水底的石头。开发人员在阅读代码时,能够迅速理解代码的意图,从而减少理解成本。当项目需要进行扩展或修改时,规范的代码也能让开发人员更加容易地找到需要修改的部分,降低出错的概率。

在团队协作方面,代码规范更是发挥着不可或缺的作用。它就像是团队成员之间的共同语言,能够消除沟通障碍,提高协作效率。当所有的开发人员都遵循统一的代码规范时,代码的合并就变得更加顺畅,团队成员之间的交流也更加高效。大家可以将更多的精力放在业务逻辑的实现上,而不是浪费在解决代码风格不一致的问题上。

代码规范还能在一定程度上保证代码的质量,减少潜在的错误和漏洞。通过规范的代码编写,我们可以避免一些常见的编程错误,如变量未定义、语法错误等。这有助于提高项目的稳定性和可靠性,为用户提供更好的体验。

二、制定代码规范的前期准备

2.1 了解团队开发习惯

在着手制定前端项目代码规范之前,深入了解团队成员的开发习惯就像是为大厦奠定坚实的基石。每个开发人员都有自己独特的代码风格,这背后蕴含着他们的编程经验、学习背景以及个人偏好。比如,在变量命名上,有的成员可能钟情于驼峰命名法,像userName,这种命名方式将单词连接在一起,除了第一个单词外,每个单词的首字母大写,使得变量名既紧凑又具有一定的可读性;而有的成员则更倾向于下划线命名法,如user_name,用下划线来分隔单词,更加直观清晰。在代码结构的组织上,差异同样明显。有些开发人员习惯将相关的功能模块封装成独立的函数或类,然后通过函数调用或类的实例化来实现业务逻辑,这样的结构使得代码层次分明,易于维护;而另一些人则可能更倾向于采用面向过程的编程方式,按照业务流程的顺序依次编写代码,这种方式在处理简单业务时,代码简洁直接,但随着业务复杂度的增加,可能会导致代码的可读性和可维护性下降。

常用工具也是团队开发习惯的重要组成部分。版本控制系统是团队协作开发中不可或缺的工具,不同的团队可能会选择不同的版本控制系统,如 Git、SVN 等。Git 以其分布式的特性,使得每个开发者都拥有完整的代码仓库,方便进行分支管理和代码合并,能够极大地提高团队协作的效率;而 SVN 则是集中式的版本控制系统,所有的代码都存储在中央服务器上,虽然在某些方面不如 Git 灵活,但在一些对权限管理要求较高的团队中,仍然被广泛使用。构建工具也是如此,Webpack、Gulp、Grunt 等构建工具各有千秋。Webpack 以其强大的模块打包功能而备受青睐,它可以将各种类型的文件,如 JavaScript、CSS、图片等,打包成一个或多个文件,优化项目的加载性能;Gulp 则侧重于自动化任务流,通过定义一系列的任务,如文件压缩、代码检查等,可以大大提高开发效率;Grunt 与 Gulp 类似,也是一个基于任务的命令行构建工具,它通过配置文件来定义任务和执行流程,适合那些需要高度定制化构建过程的项目。

偏好的编程模式同样影响着代码规范的制定。在前端开发中,常见的编程模式有面向对象编程、函数式编程和响应式编程等。面向对象编程强调将数据和行为封装在对象中,通过对象之间的交互来实现业务逻辑,这种编程模式适合大型项目的开发,能够提高代码的可维护性和可扩展性;函数式编程则注重函数的纯粹性和不可变性,通过函数的组合和高阶函数的使用,使得代码更加简洁和易于测试;响应式编程则专注于处理异步数据流,通过观察者模式和事件驱动的方式,使得代码能够及时响应数据的变化,适合开发需要实时交互的应用程序。了解团队成员对这些编程模式的偏好,有助于在代码规范中确定一种或多种主流的编程模式,从而提高代码的一致性和可维护性。

2.2 参考业界成熟规范

在制定前端项目代码规范的过程中,参考业界成熟规范是一条事半功倍的捷径。这些成熟规范就像是行业内的标杆,经过了众多开发者的实践检验,具有很高的权威性和参考价值。Airbnb JavaScript Style Guide 就是其中的佼佼者,它对 JavaScript 代码的书写规范、变量命名、函数定义、对象和数组的使用等方面都给出了详细且合理的建议。在变量声明方面,它提倡使用const和let来代替var,以避免变量提升和作用域混乱的问题,提高代码的可读性和可维护性;在函数定义时,它建议使用箭头函数来简化函数的写法,同时明确了箭头函数的使用场景和注意事项。

Google HTML/CSS Style Guide 则是 HTML 和 CSS 代码规范的重要参考。在 HTML 部分,它规定了文档类型的使用、标签的嵌套规则、属性的命名和使用方式等,强调使用语义化的 HTML 标签,如<header>、<nav>、<main>、<footer>等,来提高页面的可访问性和代码的可读性;在 CSS 部分,它对样式表的结构、选择器的使用、属性的书写顺序等方面都给出了明确的指导,建议使用简洁明了的选择器,避免过度使用嵌套选择器,以提高 CSS 的性能和可维护性。

还有很多其他的业界成熟规范,如 JavaScript Standard Style、ESLint 的官方规范等。这些规范虽然在具体细节上可能存在差异,但它们的核心目标都是一致的,即提高代码的质量、可读性和可维护性。参考这些规范,我们可以借鉴其中的优秀实践,避免重复造轮子,同时也能够使我们的代码更好地接轨行业标准,便于团队成员之间的交流和协作,以及项目的后续维护和扩展。

三、代码规范细则

3.1 命名规范

3.1.1 项目命名

项目命名如同为新生儿取名,需精心考量。应遵循简洁明了的原则,让看到项目名的人能迅速对项目内容有个大致的了解。采用小写字母加下划线的方式是一种常见且实用的做法,比如my_project_name。这样的命名方式清晰直观,便于在文件系统和命令行中操作。项目名要准确反映项目的核心内容,避免使用过于抽象或模糊的词汇。如果是一个电商项目,可以命名为ecommerce_project,而不是像xyz_project这种让人一头雾水的名字。还需遵循团队已有的命名约定,如果团队一直采用特定的命名风格,新的项目也应保持一致,以维持整体的统一性。要坚决避免使用特殊字符,如空格、连字符(除了下划线)、星号等,这些特殊字符可能会在不同的环境中引发兼容性问题,导致项目在部署或运行时出现异常。

3.1.2 文件命名

不同类型的文件有着各自独特的命名规则。JavaScript 文件(.js)、CSS 文件(.css)和 HTML 文件(.html)通常都采用小写字母加下划线的方式命名,像account_model.js、styles.css、index.html等。这样的命名方式与项目命名风格保持一致,易于管理和识别。文件名要能够准确体现文件的内容和用途。比如,一个用于用户登录功能的 JavaScript 文件,可以命名为user_login.js,这样开发人员在看到文件名时,就能立刻明白该文件的作用,提高开发效率。

目录结构的合理设置对于项目的可维护性至关重要。按照功能或模块来划分目录是一种高效的方式,它能将相关的文件组织在一起,使得项目结构清晰明了。常见的目录设置包括src(源代码目录)、dist(构建产物目录)、node_modules(依赖包目录)等。在src目录下,还可以进一步细分,如components(组件目录)、pages(页面目录)、utils(工具函数目录)等。这样的目录结构就像一个分类清晰的图书馆,开发人员可以快速找到所需的文件,降低出错的概率。

3.1.3 变量、函数、类命名

在 JavaScript 中,变量和函数的命名通常采用驼峰命名法,即第一个单词的首字母小写,后面每个单词的首字母大写,例如myVariableName和myFunctionName。这种命名方式能够清晰地分隔单词,使变量和函数名具有良好的可读性。常量则使用全大写字母和下划线的组合,如MY_CONSTANT,这样的命名方式能够突出常量的特殊性,提醒开发人员其值不可随意更改。类名采用帕斯卡尔命名法,也就是每个单词的首字母都大写,例如MyClass,这种命名方式能够清晰地区分类和其他标识符,符合面向对象编程的风格。无论是变量、函数还是类,命名都要有明确的描述性,能够准确体现其用途。比如,一个用于获取用户信息的函数,可以命名为getUserInfo,而不是简单地命名为func,这样可以减少代码的理解成本,提高代码的可维护性。

3.2 代码格式规范

3.2.1 缩进与空格

缩进就像是文章中的段落缩进,能够使代码的层次结构更加清晰。在前端项目中,统一使用 4 个空格进行缩进是一种广泛接受的做法。这样的缩进方式既能保证代码的整齐美观,又不会因为缩进过多或过少而影响可读性。在操作符前后各加一个空格,例如x = y + z,这样可以使表达式更加清晰易读,避免因操作符与变量紧密相连而导致的阅读困难。在逗号后面加一个空格,例如function foo(a, b, c) {},这有助于区分函数的参数,提高代码的清晰度。合理的缩进与空格使用,就像给代码穿上了一件整洁的外衣,让人赏心悦目。

3.2.2 分号、括号使用

在 JavaScript 中,语句末尾使用分号是一个良好的习惯。分号能够明确地标识一条语句的结束,避免因语句粘连而导致的语法错误。虽然 JavaScript 在某些情况下可以自动插入分号,但为了避免潜在的问题,最好还是手动添加分号。在函数声明和表达式后,即使代码只有一行,也应该使用花括号。例如:

 

if (condition) {

doSomething();

}

这样的写法能够清晰地界定代码块的范围,避免在后续修改代码时出现逻辑错误。花括号就像是代码的边界线,明确了代码的作用域,使代码的结构更加严谨。

3.2.3 代码排序

在 CSS 中,代码的排序应遵循一定的逻辑顺序。通常先定义布局相关的属性,如display、position、float等,这些属性决定了元素在页面中的位置和布局方式;然后再定义视觉样式相关的属性,如color、background、font-size等,这些属性负责元素的外观展示。按照这样的顺序排列代码,就像按照从框架到装饰的顺序来装修房子,能够使代码更加有条理,方便开发人员查找和维护。例如:

 

.element {

display: block;

position: relative;

float: left;

color: #333;

background-color: #f5f5f5;

font-size: 16px;

}

这种逻辑顺序的代码排列,能够提高代码的可读性和可维护性,让开发人员在修改样式时能够快速定位到所需的属性。

3.3 注释规范

3.3.1 功能性注释

功能性注释就像是代码中的导游,为开发人员指引方向。在复杂的代码段或关键逻辑处,添加注释是非常必要的。这些注释能够详细说明代码的功能和实现思路,帮助其他开发人员(甚至是一段时间后的自己)快速理解代码的意图。比如,在一段实现数据排序的复杂代码中,可以添加注释解释排序算法的原理和关键步骤:

 

// 使用快速排序算法对数组进行排序

// 快速排序的基本思想是通过一趟排序将待排记录分割成独立的两部分,

// 其中一部分记录的关键字均比另一部分的关键字小,

// 然后再分别对这两部分记录继续进行排序,以达到整个序列有序。

function quickSort(arr) {

if (arr.length <= 1) {

return arr;

}

let pivot = arr[Math.floor(arr.length / 2)];

let left = [];

let right = [];

let equal = [];

for (let num of arr) {

if (num < pivot) {

left.push(num);

} else if (num > pivot) {

right.push(num);

} else {

equal.push(num);

}

}

return [...quickSort(left), ...equal, ...quickSort(right)];

}

这样的注释能够让开发人员在阅读代码时,不仅看到代码的实现,还能理解其背后的逻辑,提高代码的可维护性。

3.3.2 文档注释

文档注释是文件的名片,它能够为项目的管理和维护提供重要信息。在文件的顶部,应该添加文档注释,介绍文件的目的、内容、作者、版本等信息。以一个 JavaScript 文件为例:

 

/**

* @fileoverview 该文件用于实现用户登录和注册功能

* @author John Doe <johndoe@example.com>

* @version 1.0.0

*/

这样的文档注释能够让开发人员在打开文件时,迅速了解文件的基本信息,方便项目的管理和维护。它就像是一本书的前言,为读者提供了阅读前的必要背景知识。

3.3.3 单行注释

单行注释是代码中的小助手,它主要用于临时禁用代码或对简单的行内代码进行解释。当需要暂时屏蔽某一行代码时,可以使用单行注释:

 

// var temp = calculateValue(); // 暂时禁用这行代码,用于调试

在对某一行代码进行简单解释时,单行注释也能发挥作用:

 

let sum = num1 + num2; // 计算两个数的和

使用单行注释时,要注意简洁明了,避免冗长的解释,以免影响代码的可读性。它就像是代码中的便签,简洁地记录一些重要的提示信息。

3.4 编程风格规范(以 JavaScript 为例)

3.4.1 变量声明

在 JavaScript 中,提倡使用const和let来声明变量,尽量避免使用var。var存在变量提升的问题,即变量可以在声明之前使用,这可能会导致一些难以排查的错误。例如:

 

console.log(num); // 输出undefined,而不是报错

var num = 10;

var还允许在同一作用域内重复定义变量,这也容易引发逻辑错误。而const声明的变量是常量,一旦赋值就不能再更改,这有助于防止意外的变量修改,提高代码的稳定性。let声明的变量具有块级作用域,避免了var的函数作用域带来的一些问题。例如:

 

{

let message = 'Hello';

console.log(message); // 输出Hello

}

console.log(message); // 报错,message未定义

使用const和let能够使代码的行为更加可预测,减少潜在的错误。

3.4.2 函数式编程

函数式编程是一种强大的编程范式,它强调函数的纯粹性和不可变性,通过函数的组合和高阶函数的使用,使代码更加简洁和易于测试。在 JavaScript 中,filter、map等方法是函数式编程的典型应用。例如,有一个数组[1, 2, 3, 4, 5],要获取其中的偶数并将其平方,可以使用传统的循环方式:

 

let numbers = [1, 2, 3, 4, 5];

let result = [];

for (let i = 0; i < numbers.length; i++) {

if (numbers[i] % 2 === 0) {

result.push(numbers[i] * numbers[i]);

}

}

console.log(result);

使用函数式编程的方式则更加简洁明了:

 

let numbers = [1, 2, 3, 4, 5];

let result = numbers.filter(num => num % 2 === 0).map(num => num * num);

console.log(result);

函数式编程的代码语义更加清晰,避免了繁琐的循环和条件判断,提高了代码的可读性和可维护性。

3.4.3 最小函数准则

一个函数应该只做一件事,这是提高函数复用性和拓展性的关键。如果一个函数承担了过多的职责,那么它的逻辑会变得复杂,难以理解和维护。当需要对其中一个功能进行修改时,可能会影响到其他功能,增加出错的风险。比如,有一个函数既要获取用户信息,又要对用户信息进行格式化,还要将用户信息保存到数据库中,这样的函数就违反了最小函数准则。应该将这些功能拆分成多个独立的函数,每个函数只负责一个明确的任务:

 

// 获取用户信息

function getUserInfo() {

// 具体实现

}

// 格式化用户信息

function formatUserInfo(info) {

// 具体实现

}

// 保存用户信息到数据库

function saveUserInfo(info) {

// 具体实现

}

这样,每个函数的功能单一,易于测试和复用,当需要修改某个功能时,也不会对其他部分造成影响。

3.4.4 解构赋值

解构赋值是一种强大的语法,它能够简化从对象和数组中取值的操作,提高代码的可读性和效率。从对象中取值时,传统的方式是通过对象的属性名来获取:

 

let user = { name: 'John', age: 30, email: 'johndoe@example.com' };

let name = user.name;

let age = user.age;

使用解构赋值可以更加简洁地实现:

 

let user = { name: 'John', age: 30, email: 'johndoe@example.com' };

let { name, age } = user;

从数组中取值时,解构赋值同样方便:

 

let numbers = [1, 2, 3];

let [a, b, c] = numbers;

解构赋值能够减少冗余代码,使代码更加简洁直观,提高开发效率。

四、规范落地与维护

4.1 引入代码检查工具

在前端项目中,引入像 ESLint 这样的代码检查工具,就如同为项目配备了一位严谨的质检员,能够实时监督代码的质量。ESLint 是一款流行的 JavaScript 代码检查工具,它基于一系列规则来检查代码,确保代码遵循特定的编程风格和最佳实践。通过配置 ESLint,我们可以让它自动检查代码,在开发过程中及时发现并纠正不符合规范的代码,从而提高代码的质量和可维护性。

安装 ESLint 非常简单,只需在项目根目录下的命令行中运行npm install eslint --save-dev,即可将其安装到项目中。安装完成后,我们需要创建一个配置文件.eslintrc,来定义项目中遵循的规则集。这个配置文件可以根据项目的实际需求进行定制,以确保代码的规范性和一致性。例如,我们可以在配置文件中设置以下规则:

 

{

"env": {

"browser": true,

"es6": true

},

"extends": "eslint:recommended",

"rules": {

// 变量命名规范,使用驼峰命名法

"camelcase": ["error", {"properties": "never"}],

// 使用单引号

"quotes": ["error", "single"],

// 每个语句结束使用分号

"semi": ["error", "always"]

}

}

在上述配置中,env定义了代码运行的环境,这里设置为浏览器环境并支持 ES6 语法;extends表示继承 ESLint 推荐的规则;rules中则具体定义了我们项目所需要遵循的规则,如变量命名要使用驼峰命名法,字符串使用单引号,语句结束要加分号等。

配置好 ESLint 后,我们可以在项目的脚本中添加检查命令,比如在package.json的scripts字段中添加"lint": "eslint ."。这样,在开发过程中,只需运行npm run lint,ESLint 就会对项目中的所有 JavaScript 文件进行检查,并在命令行中显示检查结果。如果发现不符合规范的代码,它会详细指出错误的类型、所在的文件名和行号,以及问题的描述,同时还会给出建议的解决方案,帮助我们快速定位和解决问题。

除了在命令行中手动运行检查,我们还可以将 ESLint 集成到开发工具中,如 Visual Studio Code。在 VS Code 中安装 ESLint 插件后,它会在我们编写代码时实时进行检查,一旦发现不符合规范的代码,会立即在编辑器中给出提示,就像一位贴心的助手,时刻提醒我们保持代码的规范性。这样,我们在开发过程中就能及时发现并纠正问题,避免问题积累到后期难以排查和解决。

4.2 团队培训与沟通

制定好代码规范后,对团队成员进行培训是确保规范有效执行的关键一步。这就好比一场军事训练,只有让每个士兵都熟悉并掌握作战规则,才能在战场上协同作战,取得胜利。培训的方式可以多种多样,线上课程是一种便捷的方式,团队成员可以根据自己的时间安排,随时学习代码规范的内容,通过视频讲解、案例分析等形式,深入理解规范的要求和背后的原理。线下培训则可以营造更加互动的学习氛围,大家可以面对面交流,共同探讨在实际开发中可能遇到的问题和解决方案。例如,可以组织一次代码规范培训研讨会,让团队成员分享自己在开发中对规范的理解和实践经验,通过交流和讨论,加深对规范的认识。

除了培训,在日常开发中,团队成员之间的沟通也至关重要。鼓励成员在开发中及时沟通交流,就像一支足球队的队员在比赛中不断传球、交流战术一样。当遇到对代码规范理解不一致的情况时,及时沟通可以避免误解,确保大家对规范的理解和执行保持一致。例如,在代码审查过程中,如果发现某个成员的代码不符合规范,审查者可以及时与该成员沟通,指出问题所在,并共同探讨如何修改。这样不仅可以帮助成员更好地理解规范,还能促进团队成员之间的相互学习和成长。建立一个专门的沟通渠道,如钉钉群、企业微信讨论组等,方便团队成员随时交流关于代码规范的问题,也是非常有必要的。在这个沟通渠道中,大家可以分享一些关于代码规范的最佳实践、遇到的问题及解决方案,形成一个良好的学习和交流氛围,不断提高团队整体的代码质量意识。

4.3 定期回顾与更新

代码规范不是一成不变的,它需要随着项目的发展和技术的更新而不断调整和完善。定期回顾规范的执行情况,就像定期对车辆进行保养一样,能够确保规范始终适应项目的需求。我们可以每隔一段时间,如一个月或一个季度,对项目中的代码进行一次全面的检查,统计违反代码规范的情况,分析哪些规则经常被违反,哪些规则在实际应用中存在不合理的地方。例如,通过统计发现某个复杂的命名规则在实际开发中经常被成员忽略,导致代码风格不一致,这时就需要重新评估这个规则的合理性,是否需要简化或调整。

根据项目的发展和技术的更新,及时调整规范也是必不可少的。随着前端技术的不断发展,新的编程模式、工具和框架不断涌现,代码规范也需要与时俱进。比如,当项目开始使用新的 JavaScript 特性,如 ES6 的箭头函数、解构赋值等,代码规范中就需要明确这些新特性的使用规则,以确保代码的一致性和可读性。如果项目引入了新的构建工具或开发框架,也需要相应地调整代码规范,以适应新工具和框架的要求。定期回顾和更新代码规范,能够让规范始终保持活力,为项目的顺利开发提供有力的保障。

五、总结与展望

前端项目代码规范的制定是一项系统而细致的工作,它涵盖了命名、格式、注释以及编程风格等多个方面。规范的代码不仅能提升代码的可读性和可维护性,还能极大地促进团队协作,减少开发过程中的沟通成本和潜在错误。在制定代码规范时,我们要充分考虑团队的开发习惯,借鉴业界成熟的规范,使规范既符合团队实际情况,又能与行业标准接轨。通过引入代码检查工具、加强团队培训与沟通以及定期回顾更新规范等措施,确保规范能够有效落地并持续发挥作用。

希望读者们能够重视前端项目代码规范的制定与实践,将其融入到日常的开发工作中。让我们一起用规范的代码打造更加高效、稳定、易维护的前端项目,在前端开发的道路上不断前行,创造出更加优质的用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大雨淅淅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值