从零到一:发布你的第一个npm包,让世界见证你的代码魅力!

 

学习目标:

  1. 学会创建和组织项目:了解如何创建一个新项目,并定义其结构和文件布局。
  2. 编写可重用的代码:学习如何编写模块化、可重用和易于维护的代码,以便其他人可以轻松地集成和使用你的npm包。
  3. 处理依赖关系:了解如何处理项目的依赖关系,包括如何引入和更新外部包以及处理版本冲突。
  4. 学会发布和维护npm包:掌握如何发布你的npm包到npm的注册表,以及如何维护和更新你的包。

学习内容:

  1. 了解npm:学习如何使用npm(Node Package Manager),包括安装、更新和卸载包,以及如何处理依赖关系。
  2. 学习Node.js:理解Node.js的基本概念和工作原理,这将为你构建和发布npm包提供基本的环境和工具。
  3. 掌握JavaScript:熟悉JavaScript语法和常用的库和框架,这将帮助你编写高质量的npm包。
  4. 了解模块化开发:学习如何使用模块化开发的概念和技术,以便你的npm包可以被其他人方便地使用和扩展。


学习产出:

  1. 了解npm的基本概念和用法:

    • 安装和更新npm:学习如何安装Node.js以及随之安装的npm包管理器,并了解如何更新npm到最新版本。

安装Node.js和npm包管理器是发布npm包的前提条件。以下是关于安装和更新npm的详细步骤:

  1. 安装Node.js:

    • 访问Node.js官方网站:https://nodejs.org/en/
    • 根据你的操作系统选择合适的安装包下载。
    • 在下载完成后,运行安装包,并按照安装向导的步骤进行安装。
  2. 验证Node.js和npm的安装:

    • 打开终端(命令提示符或终端窗口)。
    • 运行以下命令以验证Node.js和npm的安装:
      node -v
      npm -v
      

    • 如果输出显示了对应的版本号,则表示Node.js和npm已成功安装。
  3. 更新npm到最新版本:

    • 运行以下命令来更新全局的npm包到最新版本:
      npm install -g npm
      

    • 如果你使用的是较旧的npm版本,可能需要在命令前面加上sudo(针对Mac和Linux用户)。
  4. 验证npm的更新:

    • 运行以下命令以验证npm是否已成功更新:
      npm -v
      

    • 如果输出显示了最新的npm版本号,则表示更新成功。

现在,你已经成功安装了Node.js和npm,并更新了npm到最新版本。你可以开始使用npm来管理和发布你的代码了。

    • 创建一个新的npm项目:学习使用npm init命令来初始化一个新的npm项目,并了解生成的package.json文件的作用和结构。

使用npm init命令可以帮助你初始化一个新的npm项目,并生成一个package.json文件。以下是详细的步骤:

  1. 打开终端(命令提示符或终端窗口)。

  2. 确定你的当前工作目录,并进入到你想要创建新项目的文件夹中。

  3. 运行以下命令以初始化新的npm项目:

    npm init
    

    或者你可以使用npm init -y命令来跳过交互式的设置。

  4. 在运行命令后,你将会被要求提供一些关于你的项目的基本信息,例如项目名称、版本号、描述等。

  5. 依次填写每个字段的值,并按下回车键确认。如果你使用了npm init -y命令,所有的字段都会采用默认值。

  6. 完成上述步骤后,npm init命令将会生成并写入一个package.json文件到你的项目文件夹中。

package.json文件是npm项目的核心文件,它用于描述项目的元数据,包括项目名称、版本号、作者、依赖关系等。你可以通过编辑package.json文件来添加或修改项目的配置信息。

通过npm init命令初始化一个新的npm项目并生成package.json文件后,你就可以开始编写你的代码,并使用npm来安装和管理依赖包。

    • 包的依赖关系:了解如何在package.json文件中定义你的包所依赖的其他包的版本和范围。

package.json 文件中,你可以使用 dependencies 字段来定义你的包所依赖的其他包的版本和范围。

具体来说,你可以在 dependencies 字段中添加键值对,其中键是包的名称,值是该包的版本号或版本范围。例如:

"dependencies": {
  "lodash": "^4.17.21",
  "axios": "~0.21.1"
}

在上面的例子中,我们定义了两个依赖项:lodashaxios。对于每个依赖项,我们提供了包的名称和版本号或版本范围。

版本号可以使用以下格式之一:

  • 精确的版本号:例如 1.2.3 表示精确的版本号。
  • 范围:例如 ^1.2.3 表示可以接受 1.2.3 及其更新的任何版本,但不能接受主版本号的更改。
  • 波浪线:例如 ~1.2.3 表示可以接受 1.2.3 及其更新的任何补丁版本,但不能接受次版本号的更改。

当你运行 npm install 命令来安装依赖项时,npm 会根据 package.json 文件中的依赖关系自动下载和安装所需的包及其依赖项。npm 还会为你管理这些包的版本,确保它们保持最新。

如果你需要安装一个已经存在于 package.json 文件中的依赖包,可以简单地运行 npm install 命令。

总结起来,通过在 package.json 文件的 dependencies 字段中定义包的依赖关系,你可以确保你的包在安装时具有必要的依赖,并且这些依赖的版本符合你的要求。这有助于确保你的包能够在各个环境中以一致的方式运行。

    • 安装和使用包:使用npm install命令来安装包,并学习如何在你的项目中引入和使用这些包。

使用 npm install 命令可以安装所需的包。在命令行中进入你的项目目录,然后运行 npm install <package-name>,其中 <package-name> 是你想要安装的包的名称。

例如,要安装 lodash 包,可以运行以下命令:

npm install lodash

在安装完成后,该包及其依赖项将被下载并安装到你的项目的 node_modules 文件夹中。你可以在项目根目录下找到这个文件夹。

一旦安装了包,你可以在你的代码中引入和使用它。例如,如果你想在代码中使用 lodash,你可以在你的 JavaScript 文件中添加以下代码:

const _ = require('lodash');

// 现在你可以使用 lodash 提供的函数和工具了

在上面的代码中,我们通过 require 方法引入了 lodash 包,并将其赋值给 _ 变量。这样,我们就可以通过 _ 变量来访问和使用 lodash 提供的函数和工具。

需要注意的是,在你的项目中引入包时,你不需要指定完整的包路径,只需要包的名称即可。

此外,如果你在 package.json 文件中已经定义了依赖项,你也可以直接运行 npm install 命令来安装所有的依赖项,而不需要逐个安装。

总结一下,通过 npm install 命令安装所需的包,并通过 require 方法在你的代码中引入和使用这些包,你可以扩展和改进你的项目。

  1. 学习Node.js的基础知识:

    • 了解Node.js的工作原理:掌握Node.js的事件驱动和非阻塞I/O的特性,理解它为什么适合用于开发服务器端应用和构建命令行工具。

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。它具有事件驱动和非阻塞 I/O 的特性,这使得它非常适合用于开发服务器端应用和构建命令行工具。

Node.js 的事件驱动模型是基于事件循环的。事件循环不断地监听和处理事件,而不是等待和阻塞执行。

在 Node.js 中,所有的 I/O 操作都是非阻塞的,这意味着当执行一个 I/O 操作时,Node.js 不会等待 I/O 操作完成后再继续执行下一个操作,而是会立即执行下一个操作。当 I/O 操作完成后,Node.js 会触发相应的回调函数来处理结果。这种非阻塞的方式可以使得 Node.js 在同一时间内处理大量的并发请求,提高服务器的吞吐量和性能。

另外,Node.js 采用了单线程的事件驱动模型,意味着它只有一个主线程来处理所有的请求和操作。这使得开发人员可以更容易地编写并发代码,而不需要担心同步和线程安全的问题。此外,Node.js 还提供了异步编程模型,使得开发人员可以更轻松地处理回调函数和处理复杂的异步操作。

由于以上特点,Node.js 在开发服务器端应用和构建命令行工具方面有很大的优势。在服务器端应用中,Node.js 可以处理大量并发请求,并且可以通过事件驱动和非阻塞的方式高效地处理 I/O 操作。这使得它非常适合构建实时应用、聊天应用、数据流应用等需要高并发和实时性的应用。

在构建命令行工具方面,Node.js 提供了丰富的内置模块和函数,可以很方便地处理文件操作、执行 Shell 命令、处理命令行参数等功能。它还可以通过 npm 包管理器方便地引入和使用第三方模块,使得开发命令行工具更加灵活和高效。

总结一下,Node.js 的事件驱动和非阻塞 I/O 特性使得它成为开发服务器端应用和构建命令行工具的理想选择。它能够高效地处理大量并发请求,同时提供了丰富的内置模块和函数以及强大的生态系统,为开发人员提供了便利和灵活的开发环境。

    • 学习基本的Node.js模块:了解Node.js内置的核心模块,如fshttppath,它们提供了处理文件系统、网络和路径等常见任务的功能。

在 Node.js 中,有许多内置的核心模块可以用来处理文件系统、网络和路径等常见任务。以下是一些常用的核心模块:

  1. fs 模块:fs 模块提供了用于处理文件系统的功能,如读写文件、创建和删除目录、以及修改文件权限等。它包含了同步和异步的方法,可以根据需要选择使用。
const fs = require('fs');

// 异步读取文件
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// 同步读取文件
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);

  1. http 模块:http 模块提供了创建 HTTP 服务器和客户端的功能。你可以使用它来创建一个简单的 Web 服务器,处理 HTTP 请求并发送响应。
const http = require('http');

// 创建一个 HTTP 服务器
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!');
});

// 监听服务器端口
server.listen(3000, 'localhost', () => {
  console.log('Server running at http://localhost:3000/');
});

  1. path 模块:path 模块提供了处理文件路径的功能,可以帮助你跨平台地处理和操作文件路径。
const path = require('path');

const filePath = '/path/to/file.txt';

// 获取文件名
console.log(path.basename(filePath)); // file.txt

// 获取文件所在目录
console.log(path.dirname(filePath)); // /path/to

// 拼接路径
console.log(path.join('/path', 'to', 'file.txt')); // /path/to/file.txt

// 解析路径
console.log(path.parse(filePath)); // { root: '/', dir: '/path/to', base: 'file.txt', ext: '.txt', name: 'file' }

除了上述模块之外,Node.js 还提供了许多其他有用的核心模块,如 os 模块用于获取操作系统信息,util 模块用于提供实用工具函数,events 模块用于处理事件等。你可以根据需要查阅 Node.js 的官方文档来了解更多的核心模块和功能。

以上是一些常用的 Node.js 内置核心模块的简单介绍。通过学习和使用这些模块,你可以更高效地处理文件系统、网络和路径等任务,并构建出更强大和灵活的 Node.js 应用程序。

    • 使用第三方模块:学习如何使用第三方的npm包,了解如何查找、安装和使用这些模块,以及如何在你的代码中引入和调用它们。

在 Node.js 中,你可以使用第三方的 npm 包来扩展你的应用程序的功能。以下是一些使用第三方模块的基本步骤:

  1. 查找模块:在 npm 的官方网站(https://www.npmjs.com/)上可以查找和浏览各种可用的模块。你可以通过搜索关键字或浏览不同的类别来找到你需要的模块。

  2. 安装模块:在你的项目根目录下通过命令行运行 npm install <模块名> 来安装模块。这将会下载并安装该模块及其所有依赖项到你的 node_modules 文件夹中。

npm install express

  1. 引入模块:在你的代码中使用 require 函数来引入已安装的模块。如果模块是通过 npm 安装的,则可以使用模块的名称直接引入。
const express = require('express');

  1. 使用模块:一旦你引入了模块,你就可以使用模块提供的功能和方法。具体的使用方式可以参考模块的官方文档。
const express = require('express');

const app = express();

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

需要注意的是,如果你的项目依赖了第三方模块,你需要在分享或部署项目时一并将 node_modules 文件夹传输或打包。

在使用第三方模块时,建议查看模块的官方文档以了解模块的使用方法和选项。此外,有时候模块可能会有不同的版本可供选择,你可以通过在 package.json 文件中指定模块的版本来管理你的依赖关系。

通过使用第三方模块,你可以快速、高效地扩展和增强你的应用程序的功能。同时,你也可以通过贡献自己的模块来分享你的代码和解决方案给其他开发者使用。

  1. JavaScript编程基础:

    • 语法和基本概念:复习JavaScript的语法、变量、数据类型、函数、条件语句和循环等基本概念。

好的,以下是一些JavaScript编程基础的案例和注释,包括语法、变量、数据类型、函数、条件语句和循环等基本概念。

// 声明变量
var name = "John";
var age = 25;
var isStudent = true;

// 打印变量
console.log(name); // 输出: John

// 数据类型
var num = 10; // 数字类型
var str = "Hello"; // 字符串类型
var bool = true; // 布尔类型
var arr = [1, 2, 3]; // 数组类型
var obj = { name: "John", age: 25 }; // 对象类型
var func = function() { // 函数类型
  console.log("Hello");
};

// 函数
function sayHello() {
  console.log("Hello");
}

sayHello(); // 输出: Hello

function greet(name) {
  console.log("Hello, " + name);
}

greet("John"); // 输出: Hello, John

// 条件语句
var age = 18;

if (age >= 18) {
  console.log("成年人");
} else {
  console.log("未成年人");
}

// 循环
for (var i = 1; i <= 5; i++) {
  console.log(i);
}

var arr = [1, 2, 3, 4, 5];

arr.forEach(function(item) {
  console.log(item);
});

在上面的案例中,我们通过注释进行解释和说明。可以在控制台中打印出结果来验证每个示例的输出。

这些是JavaScript编程中的一些基本概念和语法。通过练习和实践,你将能够更好地理解和掌握这些概念,并将它们应用到实际的项目中。

    • 异步编程:掌握JavaScript的异步编程模式,包括回调函数、Promise和async/await等,这对于Node.js的开发非常重要。

异步编程在Node.js中非常重要,因为它允许代码在执行耗时操作时不会阻塞其他代码的执行。下面将介绍JavaScript中常用的异步编程模式。

  1. 回调函数(Callback): 回调函数是一种常见的异步编程模式,它允许在异步操作完成后执行特定的代码。在Node.js中,回调函数通常作为参数传递给异步函数,并在操作完成后被调用。
function fetchData(callback) {
  setTimeout(function() {
    var data = "Hello, world!";
    callback(data);
  }, 2000);
}

fetchData(function(data) {
  console.log(data); // 输出: Hello, world!
});

在上面的示例中,fetchData函数模拟了一个异步操作,2秒后调用回调函数并传递数据。

  1. Promise: Promise是一种更高级的异步编程模式,它提供了一种处理异步操作的方式,可以链式地组织、处理和传递异步操作的结果。
function fetchData() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      var data = "Hello, world!";
      resolve(data);
    }, 2000);
  });
}

fetchData()
  .then(function(data) {
    console.log(data); // 输出: Hello, world!
  })
  .catch(function(error) {
    console.error(error);
  });

在上面的示例中,fetchData函数返回一个Promise对象。当数据准备好时,调用resolve函数传递数据。通过.then方法可以处理和使用这个数据,通过.catch方法可以捕捉可能发生的错误。

  1. async/await: async/await是ES2017引入的一种更简洁的异步编程模式,它基于Promise,并通过使用asyncawait关键字来实现更直观、易读的代码。
function fetchData() {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      var data = "Hello, world!";
      resolve(data);
    }, 2000);
  });
}

async function getData() {
  try {
    var data = await fetchData();
    console.log(data); // 输出: Hello, world!
  } catch (error) {
    console.error(error);
  }
}

getData();

在上面的示例中,getData函数使用了async关键字,使其成为一个异步函数。在函数内部,使用await关键字来等待Promise的解析结果,然后再继续执行。

这些异步编程模式都在Node.js开发中得到了广泛的应用。掌握这些模式将使你能够更好地处理异步操作,并编写出更具可读性和可维护性的代码。

    • ES6+特性:了解ES6及以上版本的新特性,如箭头函数、模板字符串、解构赋值等,以便你可以使用现代化的语言特性来编写代码。

ES6(ES2015)及以上版本引入了许多新的语言特性和改进,使得JavaScript更现代化、更强大。以下是一些常用的ES6+特性:

  1. 箭头函数(Arrow Functions): 箭头函数是一种更简洁的函数定义方式,它使用箭头(=>)来代替function关键字。它具有更短的语法和更简洁的作用域绑定。
// 普通函数
function add(a, b) {
  return a + b;
}

// 箭头函数
const add = (a, b) => a + b;

箭头函数还具有词法绑定的特性,绑定了上下文的this值,避免了function关键字所导致的绑定问题。

  1. 模板字符串(Template Strings): 模板字符串允许在字符串中使用表达式和占位符,通过${}语法将表达式嵌入到字符串中。
const name = "Alice";
const message = `Hello, ${name}!`;

console.log(message); // 输出: Hello, Alice!

在模板字符串中,${}内的表达式会被求值,并将结果嵌入到字符串中。

  1. 解构赋值(Destructuring Assignment): 解构赋值允许从数组或对象中提取值,并将其赋给变量。这种方式可以更简洁地获取和操作数据。
// 数组解构赋值
const numbers = [1, 2, 3];
const [a, b, c] = numbers;

console.log(a, b, c); // 输出: 1 2 3

// 对象解构赋值
const person = { name: "Alice", age: 25 };
const { name, age } = person;

console.log(name, age); // 输出: Alice 25

解构赋值可以同时从数组或对象中提取多个值,并将它们赋给对应的变量。

除了上述特性外,ES6+还引入了类(class)、模块(module)、Promise、默认参数、展开运算符(spread operator)等许多新特性和改进。这些特性使得JavaScript更加灵活和强大,可以更高效地编写代码。

  1. 模块化开发和发布npm包:

    • CommonJS和ES模块:学习使用CommonJS和ES模块的语法和规范,以便你可以将代码以模块的形式组织起来,并在不同的文件中进行导入和导出。

模块化开发是指将复杂的代码拆分成独立的模块,每个模块具有自己的功能,并可以被其他模块引用和复用。在JavaScript中,有两种常用的模块化规范:CommonJS和ES模块。

  1. CommonJS模块化规范: CommonJS是Node.js采用的模块化规范,它定义了一套用于模块导入和导出的语法和API。使用CommonJS,你可以通过require函数导入模块,并通过module.exportsexports对象导出模块。
// 导入模块
const moduleA = require('./moduleA');

// 导出模块
module.exports = {
  foo: 'bar',
};

在导入模块时,可以使用相对路径或绝对路径指定模块的位置。

  1. ES模块化规范: ES模块是由ECMAScript(JavaScript的标准化组织)定义的模块化规范,它在ES6中引入,并逐渐被现代浏览器和Node.js所支持。使用ES模块,可以通过importexport语句导入和导出模块。
// 导入模块
import moduleA from './moduleA';

// 导出模块
export const foo = 'bar';

与CommonJS不同,ES模块的导入和导出语句使用关键字importexport,并且支持具名导入和导出,以及默认导出。

注意:ES模块的导入和导出语句只能在顶层作用域中使用,不能在函数中使用。

在开发过程中,你可以根据项目的需求选择使用CommonJS或ES模块化规范。如果你使用的是Node.js环境,通常使用CommonJS。如果你的项目基于现代浏览器,可以使用ES模块。

发布npm包是将你的代码打包成一个可复用的npm包,供其他人使用。以下是发布npm包的基本步骤:

  1. 创建一个项目目录,并在目录中初始化一个package.json文件。该文件用于描述项目信息和依赖关系。
$ mkdir my-package
$ cd my-package
$ npm init

  1. 编写你的代码,并将其组织为一个或多个模块。

  2. package.json文件中的main字段中指定你的主模块文件(打包后的入口文件)。

{
  "name": "my-package",
  "version": "1.0.0",
  "main": "dist/index.js"
  ...
}

  1. 构建和打包你的代码。可以使用一些工具如Webpack、Rollup等来打包你的代码,并将其输出到指定的目录中。

  2. 将你的代码发布到npm仓库中。执行以下命令来登录npm账号,并发布你的包。

$ npm login
$ npm publish

发布成功后,其他开发者就可以通过npm install命令来安装并使用你的包了。

这只是发布npm包的简单步骤,具体的发布过程可能会有一些额外的配置和步骤,可以参考官方文档或其他资源来了解更多细节。

    • 构建工具:了解使用构建工具(如Webpack或Rollup)来打包和构建你的代码,以便你的npm包可以在不同的环境中使用。

构建工具是用于将源代码打包、转换和优化的工具,常用的构建工具有Webpack和Rollup。

  1. Webpack: Webpack是一个非常流行的模块打包工具,它可以将多个模块打包成一个或多个bundle文件。Webpack支持多种模块化规范,可以处理各种类型的文件(例如JavaScript、CSS、图片等),并提供丰富的插件和加载器来进行代码转换和优化。

基本使用示例:

$ npm install webpack webpack-cli --save-dev

在项目的根目录下创建一个webpack.config.js文件,配置Webpack的构建选项。

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

在命令行中执行以下命令,使用Webpack构建代码。

$ npx webpack

  1. Rollup: Rollup是一个用于打包JavaScript模块的构建工具,它主要用于构建库和组件。相比于Webpack,Rollup更适用于打包纯粹的JavaScript模块,可以生成更小、更高效的输出。

基本使用示例:

$ npm install rollup --save-dev

在项目的根目录下创建一个rollup.config.js文件,配置Rollup的构建选项。

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'umd',
  },
};

在命令行中执行以下命令,使用Rollup构建代码。

$ npx rollup -c

除了Webpack和Rollup,还有其他的构建工具如Parcel、Gulp等,它们各有特点,可以根据项目的需求选择合适的构建工具。

通过使用构建工具,你可以将你的代码打包成适合在不同环境下使用的形式,例如在浏览器中直接引入、作为一个npm包发布、或作为一个库供其他开发者使用。构建工具还可以进行代码转换、压缩、代码分割等优化操作,帮助你更好地管理和维护你的代码。

    • 文档和测试:学习如何编写清晰、准确和易于理解的文档,并使用适当的测试框架(如Mocha或Jest)来测试你的代码的正确性。

编写文档和进行测试是非常重要的开发实践,可以提高代码质量、可维护性和可理解性。

  1. 编写文档: 编写清晰、准确和易于理解的文档可以帮助他人更好地理解和使用你的代码。以下是一些编写文档的建议:
  • 提供代码示例:通过提供代码示例来展示如何正确使用你的代码,可以帮助其他开发者更快地上手。
  • 描述API和功能:清晰地描述你的代码的API和功能,包括参数、返回值、使用方法等。可以使用注释或编写独立的文档文件。
  • 提供示意图和流程图:使用示意图和流程图来展示你的代码的工作原理和执行流程,有助于理解和调试代码。
  1. 进行测试: 测试可以帮助你验证代码的正确性,并确保代码在后续修改中不会引入新的错误。以下是一些测试的建议:
  • 选择适当的测试框架:常见的JavaScript测试框架有Mocha、Jest、Jasmine等。选择适合你项目的测试框架,并学习其使用方式。
  • 编写单元测试:编写针对代码中的单个函数、类或模块的测试用例。确保测试用例覆盖代码的各种情况和边界条件。
  • 编写集成测试:编写测试用例来验证多个组件或模块之间的协作和交互。确保你的代码在不同组件之间正常工作。
  • 运行自动化测试:将测试集成到你的构建流程中,确保每次代码提交或构建时都会运行测试,并及时发现潜在的问题。
  • 考虑边界条件和异常情况:测试时要考虑各种边界条件和异常情况,以确保代码在不同情况下都能正确处理。

通过编写文档和进行测试,你可以提高代码的质量和可靠性,并为其他开发者提供更好的使用和理解代码的资源。记住,好的文档和测试是编写高质量代码的重要一环。

  • 38
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿猫的故乡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值