框架技术---Vue的webpack

Vue框架


Vue3基础: 前端工程化,webpack,plugin、loader、Source Map


Vue框架是当前前端最火的框架,这里为了后期配合springBoot框架完成一个完整项目的搭建,之前已经分享过学习Vue的铺垫的知识比如ES6模块化,Promise,EventLoop事件循环[消息队列],宏任务和微任务;并且安装了Vue的工具node装载在HBuilderX中

Vue

对于Vue框架,我们首先就要了解前端工程化和webpack,webpack之前已经下载到了global中

前端工程化

之前没有接触前端的时候,或许很多人都觉得只要会Html + CSS + JavaScript就可以进行开发,利用bootStrap和JQuery就来美化页面和发送Ajax请求,利用art + template模板引擎来进行模板结构的渲染; 但是实际上 : 前端开发要遵守:

  • 模块化 : js的模块化,css的模块化,其他资源的模块化
  • 组件化: 复用现有的UI结构,样式,行为
  • 规范化 : 目录结构划分,编码规范,接口规范,文档规范,Git分支管理
  • 自动化 : 自动化构建,自动部署,自动化测试

前端工程化 : 企业级的前端项目开发中,把前端开发所使用的工具,技术,流程,经验等进行规范化、标准化、最终实现前面的几个标准

前端工程化能够让前端开发自成体系,覆盖前端项目从创建到部署的方方面面; 最大程度提高了前端的开发效率,降低了技术选型和前后端的协调沟通的成本

目前主流的解决方案就是webpack和parcel,这里主要简单介绍webpack

webpack

webpack介绍

webpack就是前端工程化的具体的解决方案

提供优化的前端工程化开发支持,代码压缩、处理浏览器端JavaScript的兼容性和性能优化;让工作重心放在功能的实现上,提高了可维护性【后端的Maven、Spring等都可以减少工作量】,项目大部分都是基于webpack进行打包构建

项目创建实例 : 列表隔行变色

  • 新建项目,npm init -y 可以初始化包管理文件package.json - 这里直接在HBuilderX中新建一个空的项目webpack,然后运行命令npm init -y 使用ES6,所以要加上type : module
{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
  • 新建src源代码目录

  • 新建src-> index.html首页和src-> index.js脚本文件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
        <script src="./index.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<ul>
			<li>这是第1个li</li>
			<li>这是第2个li</li>
			<li>这是第3个li</li>
			<li>这是第4个li</li>
			<li>这是第5个li</li>
		</ul>
	</body>
</html>

-----------------使用npm命令引入jquery-------------------操作上面的dom
  • 初始化首页基本的结构

  • 运行npm install jquery -S,安装JQuery

PS D:\HBuilderX\Web项目\webpack> npm i jquery  -S

added 1 package in 2s

导入包之后,项目中用一个node_modules来存放下载导入的包,这样就可以使用默认导入在其他js文件中使用该目录下面的包【这样js脚本间就不需要像最初那样使用script标签来链入】

  • 通过ES6模块化的方式导入JQuery,实现列表隔行变色
//导入JQuery
import $ from 'jquery'
//实现隔行变色
$(function(){ //自动为页面加载完毕之后执行 -- 相当于load事件
	//选择器选择标签进行修改属性,odd代表基数,enen都属--过滤
	$('li:odd').css('backgroundColor','red')
	$('li:even').css('backgroundColor','green')
})

运行到浏览器会报错 : Uncaught SyntaxError: Cannot use import statement outside a module ;这是因为浏览器不兼容 ;而webpack就可以解决这些兼容性问题 — 自动将有兼容性问题的代码转化为没有兼容性的代码,然后运行到浏览器

给项目安装webpack使用命令安装两个包即可,只是开发时使用,所以是-D

npm i webpack@5.5.1 webpack-cli@4.2.0 -D


PS D:\HBuilderX\Web项目\webpack> npm i webpack@5.5.1 webpack-cli@4.2.0 -D
added 136 packages in 6s

项目中配置webpack

  1. 在项目的根目录中,创建名为webpack.config.js的webpack的配置文件
//这里就简单声明配置对象
module.exports ={
	mode: 'development'  //mode值有development和production,开发阶段就用dev
}
  1. 在package.json的script【可运行脚本】中新增dev脚本 ; 使用npm run XX 来运行脚本 ; npm run dev ; 这里的dev就是随意的,但是值就是webpack ;运行dev脚本就会启动webpack,然后读取webpack.config.js来读取配置项,对项目进行打包等处理
 "scripts": {
   //"test": "echo Error: no test specified && exit 1" , //这里的只是测试的,没有具体用处
	"dev" : "webpack"
  },

运行npm run dev之后,会生成dist目录,下面的main.js就是webpack解决之前index.js的兼容性后生成的新的js文件,重新引入

上面的test最好删掉,因为有的时候可能报错

//这里之前出现小问题
[webpack-cli] Error [ERR_REQUIRE_ESM]: require() of ES Module D:\HBuilderX\Web项目\webpack\webpack.config.js from D:\HBuilderX\Web项目\webpack\node_modules\webpack-cli\lib\groups\resolveConfig.js not supported.

这里是因为之前加入了type : module ; 这里要使用require(),这是CommonJS,所以要删掉

可以截取一小段main.js看一下

/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => module['default'] :
/******/ 				() => module;
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();

这里已经对所有的js文件进行了处理,并且使用了require,直接将这个文件链入index.html就可以解决兼容性问题

<script src="../dist/main.js" type="text/javascript" charset="utf-8"></script>

当修改js文件之后,如果没有热更新,就需要重新运行npm run dev命令,来执行webpack

module的可选值【webpack.config.js中】

webpack.config.js是webpack的配置文件,webpack在真正开始打包构建之后,会先读取这个配置文件,从而基于给定的配置,对项目进行打包; webpack是基于node.js开发的工具,所以配置文件,支持使用node.js的语法来进行个性化配置【CommonJS】

  • development

表示的是开发环境,不会对打包生成的文件进行代码压缩和性能优化, 所以打包的速度快, 适合在开发阶段使用

  • production

生产环境, 会对打包生成的文件进行代码压缩和性能优化, 所以打包速度要慢一点, 适合项目开发完成之后使用

webpack中默认的打包入口文件时src -> index.js

默认的输出文件路径为dist-> main.js

想要修改默认值,需要在webpack.config.js配置文件中进行配置,这里使用的node的语法CommonJS来引入path包: entry指代的时打包入口,output为打包的出口,path和filename分别指定出口的路径和名称

const path = require('path') //CommonJS引入path包

module.exports ={
	mode: 'development',//mode值有development和production,开发阶段就用dev
	entry: path.join(__dirname,'./src/index.js'), 
	output: {
		path: path.join(__dirname,'./dist'),
		filename: 'boundle.js'
	}
}

使用的path.join进行路径的拼接 【 因为这里是相对路径】

前端相对路径/ ./ …/ …/…/

  • 不加/就是资源路径,之前讲过,这里和 ./是相同的, ./和资源路径都表示相对路径是当前文件所在的目录路径
  • / 是相对路径,如果是web项目,就是项目的路径之前的路径,就是端口号级,一般就是项目的上一级目录
  • …/ 表示的是返回上一级目录,就是前文件所在目录的上一级目录为相对路径
  • …/…/就是再上一级,依次类推

这里将之前的dist删除之后重新执行命令,发现修改成功

webpack中的plugin

上面每次修改代码之后,都要重新运行npm run dev来执行webpack,可以使用plugin来进行热更新,通过安装和配置第三方的插件,可以拓展webpack的能力

  • webpack-dev-server

    • 类似于node.js中的命令nodemon,热更新; 每当修改了源代码,webpack会自动对项目进行打包和构建

    • 【-D代表将其记录到开发结点下】,运行命令npm i webpack-dev-server@3.11.0 -D, 下载之后就需要配置到项目中

    • 配置 : 修改package.json-> scripts中的dev命令,之前是webpack,直接执行并不会进行热更新

      "dev": "webpack serve"
      
      
      //修改之后运行npm run dev就可以通过浏览器访问实时的更新,和nodemon类似,如果报错,使用npm i webpack-cli -D 更新之后再使用即可
      
      
      
      ---------------------result-----------------------
      PS D:\HBuilderX\Web项目\webpack> npm run dev
      
      > webpack@1.0.0 dev
      > webpack serve
      
      (node:552) [DEP0111] DeprecationWarning: Access to process.binding('http_parser') is deprecated.
      (Use `node --trace-deprecation ...` to show where the warning was created)
      × 「wds」:  Error: listen EACCES: permission denied 127.0.0.1:8080 ---- netstat杀死即可
          at Server.setupListenHandle [as _listen2] (node:net:1313:21)
          at listenInCluster (node:net:1378:12)
          at GetAddrInfoReqWrap.doListen [as callback] (node:net:1516:7)
          at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:73:8) {
        code: 'EACCES',
        errno: -4092,
        syscall: 'listen',
        address: '127.0.0.1',
        port: 8080
      }
      

    需要注意的是: webpack-server会启动一批个实时打包的http服务器,所以查看打包效果在http://localhost:8080; 这里和之前的nodemon挂载服务器是一样的效果; 这里可能存在端口号被占用的情况,这里可以先关掉

    打开这个网址之后,出现的是项目的目录结构,包括dist等,所以点击src就可以运行index.html; 但是当直接进行修改之后,浏览器中并没有马上改变,这是由于配置插件后打包的文件是到缓存中

    打包文件的去向

    1. 在不配置webpack-dev-server的情况下,webpack打包生成的文件直接放到物理磁盘上【严格遵守在webpack.config.js中的配置,output结点的指定路径】
    2. 配置之后,打包生成的文件存放到内存中 【不再放到磁盘中,提高实时打包输出的性能,因为内存的速度更快】webpack-dev-server生成到内存中的文件,默认放到项目的根目录中,并且是虚拟的,不可见的, 可以8080/bundle.js查看到一个文件
    <!--所以这里就要修改index.html中的引用的路径,不再是dist下面,而是在项目的根目录下面,使用/的相对路径,所以/ -》前台路径,可以代表上面的网址 -->
    <script src="/boundle.js" type="text/javascript" charset="utf-8"></script>
    
    这样保存就会自动更新页面nodemon
    
  • html-webpack-plugin

    webpack中的HTML插件,类似于一个模板引擎插件; 可以通过此插件自定制index.html的内容

    安装 : 使用命令npm i html-webpack-plugin -D 这样就可以直接安装到最新的版本

    配置 : 打开webpack.config.js

    //1.使用commonJS语法导入html-webpack-plugin包
    const HtmlPlugin = require('html-webpack-plugin')
    
    //2.创建html插件的实例对象
    const htmlPlugin = new HtmlPlugin({
    	template: './src/index.html',//指定源文件的存放路径
    	filename: './idex.html'  //指定生成文件的存放路径
    })
    
    //在module.exports中,加入结点plugins
    plugins: [htmlPlugin]  //通过plugin结点,让HtmlPlugin生效
    

    实例 :通过html-webpack-plugin插件,将src下面的index.html首页复制一份到根目录中,通过template和filename就可以 将index.html复制一份到根目录下【浏览器内存】 HTML插件复制到根目录的idex.html页面,放入的是内存; 并且页面的底部自动注入了打包的bundle.js文件, < script defer src=“boundle.js”>< /script>所以就不需要再手动注入了

    开启实时打包之后,加入html插件,可以删除dist目录,因为不再依赖其下面的bundle.js文件了,而是临时的根目录中的虚拟文件

    <!-- <script src="../dist/boundle.js" type="text/javascript" charset="utf-8"></script> -->
    

    【通过按两次CTRL + C就可以结束nodemon命令,cls命令可以清屏】

  • devserver结点

    在webpack.config.js配置文件中,可以通过devServer结点对webpack-dev-server插件进行更多的配置,open指定是否自动打开,host和port指定端口号; 配置结点和之前的module,output,entry,plugins平级

    devServer:{
    		open: true,  //代表是否自动打开
    		host: '127.0.0.1',  //这里是字符串形式
    		port:8090  //这样就不会出现占用
    	}
    

这里的设置和之前的ES6实例中的nodemon配置服务器相同; 这里需要重新配置服务器

webpack中的loader

在实际的开发中,webpack默认只能打包处理.js后缀名的模块,其他的非.js结尾的模块如.css不能处理,这个时候,就要使用loader加载器来进行打包

loader加载器的作用 : 协助webpack打包处理指定的文件模块

  • css-loader : 可以打包处理.css相关的文件
  • less-loader : 可以打包处理.less相关的文件
  • babel-loader : 可以打包处理webpack无法处理的高级JS语法

loader的调用过程:

在这里插入图片描述

先判断待处理的模块,如果为js,判断是否有高级的JS语法,没有就直接打包处理,否则就判断是否安装配置相关的loader

在webpack中,一切皆模块; 所以js中可以导入任何的模块比如css等

打包css文件

这里可以继续操作上面的index.html,为其加上样式,在src目录下再创建css文件夹,

其中的index.html 【去掉列表前面的*】

ul:{     ----> 这是错误的写法,选择器后面应该直接跟{},加上: 在firefox中会警告
	list-style: none;
}

--------------直接就是选择器加上{样式}---------------
ul{
	list-style: none;
}

要让这个css文件生效,按照之前,就会link链入,现在按照模块化思维,直接导入到index.js中即可

import  './css/index.css' //只是执行,不使用,所以直接加路径
  • 安装加载器style-loader,css-loader,直接运行命令 : npm i style-loader css-loader -D
  • 配置 : 在webpack.config.js中的modlue -> rules数组中,添加loader规则,test和use分别指定后缀名和其加载器; style-loader在css-loader之前
const path = require('path') //CommonJS引入path包

//1.使用commonJS语法导入html-webpack-plugin包
const HtmlPlugin = require('html-webpack-plugin')

//2.创建html插件的实例对象
const htmlPlugin = new HtmlPlugin({
	template: './src/index.html',//指定源文件的存放路径
	filename: './index.html'  //指定生成文件的存放路径
})

module.exports ={
	mode: 'development',//mode值有development和production,开发阶段就用dev
	entry: path.join(__dirname,'./src/index.js'), 
	output: {
		path: path.join(__dirname,'./dist'),
		filename: 'boundle.js'
	},
	plugins: [htmlPlugin],  //通过plugin结点,让HtmlPlugin生效
	devServer:{
		open: true,  //代表是否自动打开
		host: '127.0.0.1',
		port:8090  //这样就不会出现占用
	},
	module:{ //所有第三方文件模块的匹配规则标识
		rules:[ //文件后缀名的匹配规则
			{test:/\.css/,use:['style.loader','css.loader']} //test为正则,文件正则;use为使用的加载器
		]
	}
}

重启服务器,运行即可打包

Can’t resolve ‘style.loader’ 问题

这里是因为我们安装了高版本的webpack,所以配置的语法已经不是之前的,在webpack4.xx以后,配置loader必须要用对象的方式指明loader,即 use:[{loader:xxx},……]

module:{ //所有第三方文件模块的匹配规则标识
		rules:[ //文件后缀名的匹配规则
			{ test: /\.css/, use: [{ loader: 'style-loader' }, { loader: 'css-loader' }] } //test为正则,文件正则;use为使用的加载器
		]
	}

这里就是要注意,loader前面必须加上loader:

打包处理less文件

less文件可以操作margin和padding等位置,所以这里就美化一下之前的列表,在css下面新建一个index.less文件

html,body,ul{
	margin: 0;
	padding: 0;
	li{
		line-height: 35px;
		padding-left: 10px;
		font-size: 12px;
	}
}

之后在index.js中导入这个模块 import ‘./css/index.less’,要想打包处理,还是需要安装配置两个loader

安装 : npm i less-loader less -D

配置 : { test: /.less$/,use: [{ loader: ‘style-loader’ }, { loader: ‘css-loader’ },{loader:‘less-loader’}]}//不用less,less是less-loader的内置依赖项,而是要用style和css

打包处理样式表中与url相关的文件 url-loader file-loader

现在在index上面新建一个id为box的div,目的是将src/img/local.png作为该box的背景图片

正常来说,在index.less下面,会对这个div进行样式的编辑

#box{
	width: 380px;
	height: 114px;
	background-color: yellow;
	background: url(../img/local.png);
}

保存之后,也还是报错了: You may need an appropriate loader to handle this file type, 这是因为不能处理图片文件.jpg,.png结尾的文件

安装: npm i url-loader file-loader -D 安装两个loader

配置 : { test: /\.jpg|png|gif$/,use:[{loader: 'url-loader'}]} //暂时就只配置url-loader,图片各种后缀使用|

之后重新运行即可:但是div的背景是截取的图片的一部分…

url-loader参数limit

网页中,小的图片可以直接转化为base64直接加载,大型图片再发请求,这样可以提高网页访问的性能,而选择大小就需要url-loader的参数limit ,小于等于的就会转为base64,limit是用来指定图片的大小,单位为byte

{ test: /\.jpg|png|gif$/,use:[{loader: 'url-loader?limit=207946'}]

设置之后可以重新查看图片 : url(data:image/png;base64 —> 被转为了base64

loader配置其他方式

loader配置可以采用对象的方式进行配置:

use:{
    loader:'url-loader' , //loader属性指向调用的loader
    options:{
        limit:2229  //通过options指定参数项
    }
}
打包处理js文件高级语法

webpack只能打包处理一部分高级的js语法,对于webpack无法处理的js高级语法,只能使用babel-loader来协助打包;最新版本的webpack可以处理

class Person{
	//使用static为Person类声明一个静态属性
	//webpack无法处理这个static的高级语法,需要使用babel-loader
	static info = 'person info';
}

babel-loader含有三个主要的包babel-loader,@babel/core,@babel/plugin-proposal-class-properties

安装 : npm i babel-loader @babel/core @babel/plugin-proposal-class-properties -D

配置 : 需要注意,除了test和use,还有一个exclude : 排除项 :‘node_modules’;babel-loader只需要处理用户编写的js文件,不需要处理node_modules下面的下载的其他的包文件,这样速度快

{
				test: /\.js$/,
				exclude:/node_modules/ ,  //这里同样是正则
				use:{//要声明插件,用来转化高级语法,后面的@开头的都是插件
					loader: 'babel-loader',
					options:{
						plugins:['@babel/plugin-proposal-class-properties']
					}
				}
			}

上面的都是rules数组的一项

打包发布

项目完成之后,使用webpack对项目进行打包发布 :

  • 开发环境下,打包生成的文件存放再内存中,无法获取到最终生成的文件
  • 开发环境下,mode为development,不会对代码进行压缩和性能优化,所以需要打包发布
配置webpack的打包发布

之前再package.json下面的scripts结点下配置的是dev命令,代表的就是development,当项目完成之后,重新配置命令build

'build': 'webpack --mode production'  //没有serve,所以没有使用server插件,直接放到了物理的磁盘上,同时会修改webpack.config.js的mode为production,就会压缩

这里会覆盖config中的mode的值

这样使用命令npm run build

生成文件位置统一

直接生成文件杂乱,要将js文件统一生成到js目录中,需要再output中进行配置

//生成的位置filename,只要加上js级即可
output: {
		path: path.join(__dirname,'./dist'),
		filename: 'js/boundle.js'
	}

对于图片文件,生成到img目录下,需要对url-loader进行配置,除了原来的limit参数,新增一个outputPath参数指定路径

{ test: /\.jpg|png|gif$/,use:{
				loader: 'url-loader',
				options:{
					limit:227946,
					outputPath:'image'
				}
				}}
自动清理dist目录

为了每次打包发布自动清理dist目录,安装配置插件clean-webpack-plugin npm i XX -D

安装配置这个插件和之前配置html插件是相同的

const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const cleanPlugin = new CleanWebpackPlugin()

//1.使用commonJS语法导入html-webpack-plugin包
const HtmlPlugin = require('html-webpack-plugin')

//2.创建html插件的实例对象
const htmlPlugin = new HtmlPlugin({
	template: './src/index.html',//指定源文件的存放路径
	filename: './index.html'  //指定生成文件的存放路径
})

module.exports ={
	mode: 'development',//mode值有development和production,开发阶段就用dev
	entry: path.join(__dirname,'./src/index.js'), 
	output: {
		path: path.join(__dirname,'./dist'),
		filename: 'js/boundle.js'
	},
	plugins: [htmlPlugin,cleanPlugin],  //通过plugin结点,让HtmlPlugin生效

在高级的打包发布中,包括打包生成报告,分析具体的优化法案,Tree-Shaking,为第三方库提供CDN加载,配置组件的按需加载,开启路由懒加载,自定制首页的内容

Source Map

生产环境中遇到的问题: 前端项目投入生产环境后,都需要对js文件进行压缩混淆,从而减小体积,提高加载效率,但是产生问题 : 压缩后的代码不好debug

Source Map是一个信息文件,里面存储这位置信息, 存储代码压缩前后的位置的对应关系,有了Source Map,出错的时候,出错工具直接显示的源代码,而不是转换后的代码,方便后期的调试

在开发环境下,webpack默认开启了Source Map功能,出错的时候,控制台显示的错误行的位置,定位具体的源代码,但是默认的有一定的问题,默认的是生产后的代码的位置,行数不一致

在webpack-config.js文件中加入配置,就是和model平级

module.exports ={
	mode: 'development',//mode值有development和production,开发阶段就用dev
	devtool: 'eval-source-map',   -----------------------------------------增加的配置
	entry: path.join(__dirname,'./src/index.js'), 
	output: {
		path: path.join(__dirname,'./dist'),
		filename: 'js/boundle.js'
	},
	plugins: [htmlPlugin,cleanPlugin],  //通过plugin结点,让HtmlPlugin生效
	devServer:{
		open: true,  //代表是否自动打开
		host: '127.0.0.1',
		port:8090  //这样就不会出现占用
	},
	module:{ //所有第三方文件模块的匹配规则标识
		rules

配置之后,行数就是前后一致的

生产环境下的Source Map

在生产环境下,省略devtool选项,最终生成的文件不包含Source Map,这就可以防止原始代码通过Source Map泄露,这样定位的错位都是转化的混淆的代码,对调试不好可以设置为: 只显示行数,不暴露代码

devtool: 'nosources-source-map'

这样既方便调试,也不会泄露代码

但是devtool : ‘source-map’ 就是可以定位到源码,和之前的开发环境的eval-source-map的效果相同,十分不安全,一般就用nosources或者直接关闭🎄

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
electron-vue是一个基于Electron框架和Vue.js框架的开发工具,可以帮助开发者使用Vue进行Electron应用的开发。而webpack是一个模块打包工具,用于将各种资源(JavaScript、CSS、HTML等)打包成一个或多个文件。 当我们在electron-vue项目中使用serialport库时,需要进行一些配置和打包工作。首先,在项目的package.json文件中添加serialport库的依赖,可以使用命令npm install serialport进行安装。 接下来,在项目的webpack配置文件中,需要对serialport库进行配置。首先,添加externals属性,指定serialport库在打包时不被打包,而是在运行时通过require引入外部依赖。例如: externals: { 'serialport': 'require("serialport")' } 然后,在配置文件中找到module.exports中的target属性,将其设置为electron-renderer,以便在渲染进程中使用serialport库。 最后,通过运行npm run build命令,进行项目的打包操作。webpack将会根据配置文件将所有的资源打包成一个或多个文件,并输出到指定的目录中。 需要注意的是,在打包完成后,项目的依赖关系需要正确地配置,以确保serialport库能够正常工作。可以通过使用electron-rebuild等工具来重新编译serialport库,以适配Electron环境。 总结起来,通过electron-vue和webpack的配合,我们可以将serialport库打包到Electron应用中,从而实现在Vue界面中使用串口通信的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值