2024年Web前端最新彻底解决新手对webpack的恐惧!(2),前端后端社招面试经历

最后

为了帮助大家更好的了解前端,特别整理了《前端工程师面试手册》电子稿文件。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

安装

  • 安装webpack、webpack-cli依赖

# 我更喜欢yarn,当然你也可以使用npm

yarn add webpack@4.44.2 webpack-cli@3.3.12 -D

创建目录


  • 根目录下创建src、src下创建index.js

  • 在index.js中添加一段代码:

console.log(‘hello webpack’)

  • 在package.json文件中的scripts字段中添加"start": "webpack"

“scripts”: {

“test”: “echo “Error: no test specified” && exit 1”,

“start”: “webpack”

}

  • 在命令行中执行yarn start,我们会发现编译成功,但有个警告!在webpack自动在根目录下创建了一个dist文件夹和dist文件夹中的main.js文件

extry: ‘./src/index.js’, output: { filename: ‘main.js’, path: path.resolve(__dirname, ‘./dist’) } }

- 注意:这份默认配置是不是太过简单了。看了这个配置后,我想你也知道为什么当我们创建的不是src或者src下不是index.js时候无法使用零配置功能的原因了

  • 关于警告:ARNING in configuration The ‘mode’ option has not been set, webpack will fallback to ‘production’ for this value. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for each environment. You can also set it to ‘none’ to disable any default behavior. Learn more: webpack.js.org/configurati…[6]; 警告中已经说的很清楚了,我们没有设置mode字段。我们只需在webpack的配置中配置mode字段即可消除该警告

  • 关于dist文件夹和main.js文件 :这是webpack4当初宣传的零配置使用。很显然我们这里什么都没配置,就帮我们成功打包了一个src下的代码。该功能实际上是wabpack默认帮我们配置了一套简单的打包配置,让我们看看webpack默认为我们配置了什么:

const path = require(‘path’)

module.exports = {

webpack的零配置


上面我们看到了,零配置很弱,真正的项目中他完全不可能满足我们的需求我们想要自定义配置webpack的话,需要在根目录上创建一个webpack.config.js的文件,这个文件的内容可以覆盖webpack的零配置

  • 使用默认的配置文件:webpack.config.js

# 使用webpack.config.js配置文件时,输入该命令即可启动webpack打包

webpack

  • 使用其他配置文件:如yzyConfig.js,可以通过--config yzyConfig.js来指定webpack使用哪个配置文件来执行构建

# 通过–config来指定其他配置文件,并按照指定的配置文件的配置内容进行打包

webpack --config yzyConfig.js

webpack配置核心概念


  • chunk:指代码块,一个chunk可能由多个模块组合而成,也用于代码合并与分割(这里的合并分割主要指指纹策略的判断),指纹策略简单来说就是文件名后的hash

  • bundle:资源经过webpack流程解析编译后最终输出的成果文件(一个.js格式的文件,也就是我们的output文件)

  • entry:文件打包的入口,webpack会根据entry递归的去寻找依赖,每个依赖都将被它处理,最后打包到集合文件中

  • output:配置打包输出的位置、文件名等

  • loader:默认情况下,webpack仅支持js和json文件,通过loader,可以让它解析其他类型的文件。理论上只要有相应的loader,webpack可以处理任何类型的文件

  • plugin:loader主要的职责是让webpack认识更多的文件类型,而plugin的职责则是让其可以控制构建流程,从而执行一些特殊的任务。插件的功能非常强大,可以完成各种各样的任务

  • mode:目标环境,不用的目标环境会影响webpack打包时的决策

  • production:码进行压缩等一系列优化操作

  • development:有利于热更新的处理,识别哪个模块变化代

  • none:什么都不做,打包时会有提示警告

配置webpack.config.js

===================

项目搭建目标


咱们目标不是搭建一个完整全面的项目工程,目标是以一些有代表性的功能作为切入点学习webpack,我相信这些你认真看过后一定能做到举一反三

  • 实现加载css

  • 实现css效果展示

  • 实现css前缀自动补充

  • 实现css以文件形式导出

  • 实现自动生成html文件

  • 实现打包清空dist文件夹

  • 实现图片在js文件中引入

  • 实现图片在css文件中引入

  • 实现webpack本地服务

  • 实现多页面打包

实现加载css


我们已经知道.css文件无法正常被webpack打包进bundle(bundle的解释可查看“webpack配置核心概念”部分)文件,所以我们需要一个loader作为加载器将它正确打包进bundle文件文件内容b777a8e2de691135c64f36c817a904dc.png安装css-loader

yarn add css-loader -D

配置css-loader

const path = require(‘path’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: “development”,

module: {

rules: [

{

test: /.css$/,

use: “css-loader”

}

]

}

}

运行webpack命令,检查一下dist/main.js中是否包含了css文件中的内容d0941a607342409b1a5cf8606bf0c1d5.png我们发现css文件的内容被成功打包了,这时如果你在dist文件夹下创建了一个html页面给div元素加上了box类,并引入main.js文件,你会发现完全看不到样式效果。因为此时css中的内容只是被作为一段字符串引入了js中(相当于对css文件的内容进行了JSON.stringify),所以你自然是看不到效果的。想要看到效果要怎么办?当然是将css内容放进style标签啦!不过这步不需要我们做,因为我们有style-loader为我们做这件事情!

实现css效果展示


安装style-loader

yarn add style-loader -D

配置style-loader

const path = require(‘path’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [‘style-loader’, ‘css-loader’]

}

]

}

}

这里需要注意的是,对同一种类型文件使用多个 loader的时候,use属性接收一个数组,并且从右向左执行。所以style-loader要写在css-loader前面运行webpack命令,看一下结果114825a9c6dfeab04c266e4935f556e4.png成功!但是我们知道,css3在浏览器中会存在兼容性问题,我们可以通过给属性加上前缀来解决该问题。前端丰富的生态当然不会让你自己傻傻的做这件事情,我们可以通过autoprefixer这个插件帮我们完成

实现css前缀自动补充


已经知道autoprefixer是postcss工具的插件,所以我们需要安装postcss和postcss-loader安装postcss、postcss-loader、autoprefixer,这里postcss-loader需要指定4.x的版本,因为4.x的版本和webpack4会存在报错问题

yarn add autoprefixer postcss-loader@4.2.0 postcss -D

配置postcss-loader和插件autoprefixer

const path = require(‘path’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

‘style-loader’,

‘css-loader’,

{

loader: ‘postcss-loader’,

options: {

postcssOptions: {

plugins: [require(‘autoprefixer’)]

}

}

}

]

}

]

}

}

当loader需要写配置的时候,我们可以把loader写成一个对象,loader属性就是要使用的loader名称,options属性就是这个loader的配置对象。autoprefixer是postcss的插件,所以autoprefixer的使用自然就要写在postcss-loader的配置中了因为postcss有自己的配置文件,所以这里还可以写成这样:

// webpack.config.js

const path = require(‘path’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [‘style-loader’, ‘css-loader’, ‘postcss-loader’]

}

]

}

}

// 根目录下新建postcss.config.js文件

module.exports = {

plugins: [require(‘autoprefixer’)],

}

这里我们需要配置一下browserslist,否则插件不知道按照什么样的规则进行前缀补全

// 在package.json文件中添加

// 这里的意思表示目标浏览器为ie浏览器,并需要兼容到ie8以上

“browserslist”: [“ie > 8”]

运行webpack命令看一下结果6171a80d34a97552e2a2ee08f4a504db.png成功!

实现css以文件形式导出


随着项目的增大,我们不想把那么多的样式都放在style标签中,我们想用link标签引入,这时我们就需要使用mini-css-extract-plugin[7]安装mini-css-extract-plugin

yarn add mini-css-extract-plugin -D

配置mini-css-extract-plugin插件和它的loader,这时我们不需要style-loader了,我们要style-loader替换成MiniCssExtractPlugin.loader

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”

})

]

}

  • MiniCssExtractPlugin可以配置输出文件名

  • [name]为占位符,引入的时候是什么名字,导出的时候就是什么名字

  • css/表示导出到css文件夹下

运行webpack命令看一下结果b7c99b953e9f02818f10059f7e85edbe.png成功!

实现自动生成html文件


我们发现dist下的html是我们自己手动创建的,这显然不够优雅。html-webpack-plugin[8]帮你解决!安装html-webpack-plugin,这里也要制定一下4.x的版本

yarn add html-webpack-plugin@4.5.2 -D

配置html-webpack-plugin

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

})

]

}

运行webpack命令看一下结果35da69386150d39e17b6352bc04538c3.png成功!很显然HtmlWebpackPlugin根据我们的模版为我们生成了新的html页面,并自动引入了dist包下的依赖。查看更多HtmlWebpackPlugin配置[9]

实现打包清空dist文件夹


我们会发现每次打包dist文件夹的内容会被覆盖,但是如果下次打包出来的文件名不同,那旧的打包文件还会存在,这是我们不想要的。clean-webpack-plugin[10]来帮我们解决这个问题安装clean-webpack-plugin

yarn add clean-webpack-plugin -D

配置clean-webpack-plugin

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

这时,你也在dist文件夹下随意建一个其他文件,运行webpack命令看一下结果,你会发现你随意建的文件不在了。验证了这一点,就说明你成功了

实现图片在js文件中引入


实现这个功能我们使用url-loader,当然你也可以使用file-loader。url-loader是file-loader的升级版,它内部也依赖了file-loader。file-loader和url-loader在webpack5后都被废弃了,使用asset modules代替安装url-loader和file-loader

yarn add url-loader file-loader -D

你可以会疑问为什么要装file-loader,因为url-loader依赖file-loader。若不装,当url-loader将图片转换为base64导入bundle时不会存在问题,但直接输出图片到dist文件夹下就会报错,告诉你缺少file-loader配置url-loader

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3

}

}

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

  • [ext]表示导入时是什么格式,导出时就是什么格式

  • limit表示图片大小的阈值,超过阈值的图片会被原封不动的放置到打包文件夹下(file-loader做的这件事情,在js中引入时会帮你生成一个地址,即打包后对应的访问地址),没有超过会处理成base64放在bundle文件中

在入口文件中引入图片

// index.js

import ‘./index.css’

import mk85 from ‘./assets/images/mk85.jpeg’

console.log(mk85) // mk85.jpeg

const img = document.createElement(‘img’)

img.src = mk85

const BoxDiv = document.getElementsByClassName(‘box’)

BoxDiv[0].appendChild(img)

运行webpack命令看一下结果0bef75b0ce85a0a63e1ff92ab1efc82f.png

实现图片在css文件中引入


在css中引入图片我们依旧使用url-loader,但需要对配置稍微进行修改css代码

.box {

width: 100px;

height: 100px;

/* background-color: yellowgreen; */

background-image: url(‘./assets/images/mk85.jpeg’);

display: flex;

}

直接引用并打包,打包成功!打开html页面,发现看不到图片,因为地址不对。打包后mk85图片在dist文件夹下,而index.css的引用路径依旧是mk85.jpeg,可index.css是在css文件夹下的,所以自然是无法引用到。那如何才能引用到呢?最简单的方法就是加上/但这里有坑(其实也不是坑,这是一个关于/images./imagesimage三者有什么不同的知识点)。补充:create-react-app也是通过/ 实现引用统一的d79d1c21b8acd9afba27e3dae93c2e8a.png修改url-loader配置

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

  • outputPath表示输出的到哪里(file-loader提供的)

  • name: images/[name].[ext]这样写和用outputPath设置效果一样吗?在配合publicPath字段时不一样。所以当你不需要配置publicPath字段时,可以通过name设置输出路径(file-loader提供的)

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

// 等价于

options: {

name: ‘images/[name].[ext]’,

limit: 1024 * 3,

publicPath: “/”,

}

  • publicPath表示资源引用的路径

运行webpack命令看一下结果001b5fd873caab0428bcf930ec3d07c2.png成功了!是我们想要的结果,不过问题又来了,当你打开html页面时发现并不能看到图片正常显示,这里就牵扯到关于/images./imagesimage三者有什么不同的知识点简单来说,如果我起了服务,我的实际路径就是“localhost:8080/images/mk85.jpeg”,如果没有起服务那就是“/images/mk85.jpeg”所以让我们开启一个服务吧!

实现webpack本地服务


安装webpack-dev-server

yarn add webpack-dev-server -D

配置url-loader

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

module.exports = {

entry: ‘./src/index.js’,

output: {

filename: ‘main.js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

MiniCssExtractPlugin.loader,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

loader: ‘url-loader’,

options: {

name: ‘[name].[ext]’,

limit: 1024 * 3,

outputPath: “images/”,

publicPath: “/images”,

}

}

}

]

},

devServer: {

open: true,

port: 8080,

},

plugins: [

new MiniCssExtractPlugin({

filename: “css/[name].css”,

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’

}),

new CleanWebpackPlugin()

]

}

  • 只需要加上devServer配置即可

  • open表示打开浏览器

  • port表示服务的端口号

注意:这时就不是使用webpack命令来启动项目了,需使用webpack-dev-server来启动

实现多页面打包


顾名思义,多页面自然是有多个html页面,每个html页面都有自己的js文件,那么,有多少个入口就要有多少个出口我们首先要设置一下目录形式,以适应多页面打包的形式(以下形式不是唯一的,但有助于大家的理解)23664c4e1929d111ff46972ac8e88ae2.png

  • 这里不需要src/index.js

  • 新建一个webpack.multiple.config.js

  • 新建src/pages/login/js/index.js

  • 新建src/pages/main/js/index.js

安装glob,用于处理文件

yarn add glob -D

配置webpack.multiple.config.js

module.exports = {

entry: {

login: ‘./src/pages/login/js/index.js’,

main: ‘./src/pages/main/js/index.js’

},

output: {

filename: ‘[name].js’,

path: path.resolve(__dirname, ‘./dist’)

},

plugins: [

new HtmlWebpackPlugin({

template: ‘./src/index.html’,

filename: ‘login.html’,

chunks: [‘login’] // chunks的名字对应entry中的名字

}),

new HtmlWebpackPlugin({

template: ‘./src/index.html’,

filename: ‘main.html’,

chunks: [‘main’]

})

]

}

这样就完成了!你可以使用webpack --config ./`webpack.multiple.config.js 命令运行一下。结果会如你所愿的但是,这时你肯定会想难道我每写一个页面就重新配置一次吗?这也太麻烦了,也不优雅!那我们现在解决一下这个问题吧,直接上代码

// 我们写一个方法自动做我们上面配置的事情

const glob = require(“glob”)

const setMpa = () => {

const entry = {}

const htmlwebpackplugins = []

// 通过glob库拿到我们的入口文件数组

const entryFiles = glob.sync(path.resolve(__dirname, “./src/pages///index.js”))

// console.log(entryFiles)

// 打印结果

// [

//  ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js’,

//  ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/main/js/index.js’

// ]

entryFiles.forEach((item) => {

const entryFile = item

const match = entryFile.match(/src/pages/(.*)/js/index.js$/)

// console.log(match)

// 打印结果

// [

//   ‘src/pages/login/js/index.js’,

//   ‘login’,

//   index: 43,

//   input: ‘/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js’,

//   groups: undefined

// ]

const pageName = match[1]

entry[pageName] = entryFile

htmlwebpackplugins.push(

new HtmlWebpackPlugin({

template: ./src/index.html,

filename: ${pageName}.html,

chunks: [pageName]

})

)

})

return {

entry,

htmlwebpackplugins,

}

}

有了这个方法以后,我们把它加到配置文件里

const path = require(‘path’)

const MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)

const HtmlWebpackPlugin = require(‘html-webpack-plugin’)

const { CleanWebpackPlugin } = require(‘clean-webpack-plugin’)

const glob = require(“glob”)

const setMpa = () => {

const entry = {}

const htmlwebpackplugins = []

const entryFiles = glob.sync(path.resolve(__dirname, “./src/pages///index.js”))

entryFiles.forEach((item) => {

const entryFile = item

const match = entryFile.match(/src/pages/(.*)/js/index.js$/)

const pageName = match[1]

entry[pageName] = entryFile

htmlwebpackplugins.push(

new HtmlWebpackPlugin({

template: ./src/index.html,

filename: ${pageName}.html,

chunks: [pageName]

})

)

})

return {

entry,

htmlwebpackplugins,

}

}

const { entry, htmlwebpackplugins } = setMpa()

module.exports = {

entry,

output: {

filename: ‘[name].js’,

path: path.resolve(__dirname, ‘./dist’)

},

mode: ‘development’,

module: {

rules: [

{

test: /.css$/,

use: [

‘style-loader’,

‘css-loader’,

‘postcss-loader’

]

},

{

test: /.(png|jpe?g|gif)$/,

use: {

下面是我在学习HTML和CSS的时候整理的一些笔记,有兴趣的可以看下:

HTML、CSS部分截图

进阶阶段

进阶阶段,开始攻 JS,对于刚接触 JS 的初学者,确实比学习 HTML 和 CSS 有难度,但是只要肯下功夫,这部分对于你来说,也不是什么大问题。

JS 内容涉及到的知识点较多,看到网上有很多人建议你从头到尾抱着那本《JavaScript高级程序设计》学,我是不建议的,毕竟刚接触 JS 谁能看得下去,当时我也不能,也没那样做。

我这部分的学习技巧是,增加次数,减少单次看的内容。就是说,第一遍学习 JS 走马观花的看,看个大概,去找视频以及网站学习,不建议直接看书。因为看书看不下去的时候很打击你学下去的信心。

然后通过一些网站的小例子,开始动手敲代码,一定要去实践、实践、实践,这一遍是为了更好的去熟悉 JS 的语法。别只顾着来回的看知识点,眼高手低可不是个好习惯,我在这吃过亏,你懂的。

1、JavaScript 和 ES6

在这个过程你会发现,有很多 JS 知识点你并不能更好的理解为什么这么设计,以及这样设计的好处是什么,这就逼着让你去学习这单个知识点的来龙去脉,去哪学?第一,书籍,我知道你不喜欢看,我最近通过刷大厂面试题整理了一份前端核心知识笔记,比较书籍更精简,一句废话都没有,这份笔记也让我通过跳槽从8k涨成20k。

JavaScript部分截图

2、前端框架

前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

以 Vue 为例,我整理了如下的面试题。

Vue部分截图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值