貼上官網(wǎng)
vue-cli3 創(chuàng)建的時(shí)候并不會(huì)自動(dòng)創(chuàng)建vue.config.js瓷马,因?yàn)檫@個(gè)是個(gè)可選項(xiàng)洲赵,所以一般都是需要修改webpack的時(shí)候才會(huì)自己創(chuàng)建一個(gè)vue.config.js
再然后因?yàn)関ue-cli3內(nèi)部高度集成了webpack吧黄,一般來(lái)說使用者不需要再去知道weboack做了什么逛犹,所以沒有暴露webpack的配置文件,我們可以手動(dòng)去創(chuàng)建vue.config.js 去修改默認(rèn)的webpack供屉。注意往产,只能叫vue.config.js。
-
在根目錄中創(chuàng)建 vue.config.js
vue.config.js配置
貼上我在項(xiàng)目中撒犀,用到的比較全的配置
"use strict";
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
// 部署應(yīng)用時(shí)的基本 URL
publicPath:
process.env.NODE_ENV === "production"
? `/${process.env.VUE_APP_BASE_URL}`
: "/",
// build時(shí)構(gòu)建文件的目錄 構(gòu)建時(shí)傳入 --no-clean 可關(guān)閉該行為
outputDir: "dist",
// build時(shí)放置生成的靜態(tài)資源 (js福压、css、img或舞、fonts) 的 (相對(duì)于 outputDir 的) 目錄
assetsDir: "",
// 指定生成的 index.html 的輸出路徑 (相對(duì)于 outputDir)荆姆。也可以是一個(gè)絕對(duì)路徑。
indexPath: "index.html",
// 默認(rèn)在生成的靜態(tài)資源文件名中包含hash以控制緩存
filenameHashing: true,
// 是否在開發(fā)環(huán)境下通過 eslint-loader 在每次保存時(shí) lint 代碼 (在生產(chǎn)構(gòu)建時(shí)禁用 eslint-loader)
lintOnSave: process.env.NODE_ENV !== "production",
// 是否使用包含運(yùn)行時(shí)編譯器的 Vue 構(gòu)建版本
runtimeCompiler: false,
// Babel 顯式轉(zhuǎn)譯列表
transpileDependencies: [],
// 設(shè)置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 標(biāo)簽的 crossorigin 屬性(注:僅影響構(gòu)建時(shí)注入的標(biāo)簽)
crossorigin: "",
// 在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 標(biāo)簽上啟用 Subresource Integrity (SRI)
integrity: false,
// 如果這個(gè)值是一個(gè)對(duì)象映凳,則會(huì)通過 webpack-merge 合并到最終的配置中
// 如果你需要基于環(huán)境有條件地配置行為胆筒,或者想要直接修改配置,那就換成一個(gè)函數(shù) (該函數(shù)會(huì)在環(huán)境變量被設(shè)置之后懶執(zhí)行)诈豌。該方法的第一個(gè)參數(shù)會(huì)收到已經(jīng)解析好的配置腐泻。在函數(shù)內(nèi),你可以直接修改配置队询,或者返回一個(gè)將會(huì)被合并的對(duì)象
configureWebpack: { devtool: "source-map" },
// 對(duì)內(nèi)部的 webpack 配置(比如修改派桩、增加Loader選項(xiàng))(鏈?zhǔn)讲僮?
productionSourceMap: process.env.NODE_ENV === "development", // 是否在構(gòu)建生產(chǎn)包時(shí)生成sourcdeMap
// productionSourceMap: true, // 是否在構(gòu)建生產(chǎn)包時(shí)生成sourcdeMap
chainWebpack: config => {
config.entry("main").add("@babel/polyfill");
config.plugin("html").tap(args => {
args[0].title = "測(cè)試";
return args;
});
config.resolve.alias.set("@", resolve("src"));
const svgRule = config.module.rule("svg");
// 清除已有的所有l(wèi)oader
svgRule.uses.clear();
svgRule
.test(/\.svg$/)
.include.add(path.resolve(__dirname, "./src/assets/icons"))
.end()
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: "icon-[name]"
});
},
// css的處理
// 所有 webpack-dev-server 的選項(xiàng)都支持
devServer: {
host: "0.0.0.0", //局域網(wǎng)和本地訪問
port: "8089",
hot: true,
/* 自動(dòng)打開瀏覽器 */
open: false,
overlay: {
warning: false,
error: true
},
/* 跨域代理 */
proxy: {
[process.env.VUE_APP_BASE_API]: {
/* 目標(biāo)代理服務(wù)器地址 */
// target: process.env.VUE_APP_BASE_URI,
target: "http://xxx/xx",
/* 允許跨域 */
changeOrigin: true,
ws: true,
pathRewrite: {
// "^/dev-api": ""
["^" + process.env.VUE_APP_BASE_API]: ""
}
}
}
},
// 是否為 Babel 或 TypeScript 使用 thread-loader
parallel: require("os").cpus().length > 1,
// 向 PWA 插件傳遞選項(xiàng)
pwa: {},
// 可以用來(lái)傳遞任何第三方插件選項(xiàng)
pluginOptions: {},
css: {
loaderOptions: {
postcss: {
plugins: [
require("postcss-pxtorem")({
rootValue: 37.5, // 換算的基數(shù),數(shù)值具體看你的設(shè)計(jì)稿 另外提醒下vant-UI的官方根字體大小是37.5
selectorBlackList: [], // 忽略轉(zhuǎn)換正則匹配項(xiàng)
unitPrecision: 3,
propList: ["*"], // 需要做轉(zhuǎn)化處理的屬性,如`hight`蚌斩、`width`铆惑、`margin`等,`*`表示全部
minPixelValue: 3 // 小于或等于`3px`不轉(zhuǎn)換為視窗單位
})
]
},
less: {
modifyVars: {
hack: `true; @import "${resolve("./src/assets/styles/reset.less")}";`
}
}
}
}
};
配置選項(xiàng)解析
publicPath(從 Vue CLI 3.3 起已棄用baseUrl送膳,請(qǐng)使用publicPath)
參考:https://my.oschina.net/u/4446873/blog/4882847
Type: string
Default: '/'
部署應(yīng)用包時(shí)的基本 URL员魏, 用法和 webpack 本身的 output.publicPath 一致。
這個(gè)值也可以被設(shè)置為空字符串 ('') 或是相對(duì)路徑 ('./')叠聋,這樣所有的資源都會(huì)被鏈接為相對(duì)路徑撕阎,這樣打出來(lái)的包可以被部署在任意路徑。
默認(rèn)情況下碌补,Vue CLI 會(huì)假設(shè)你的應(yīng)用是被部署在一個(gè)域名的根路徑上虏束,例如https://www.xxx.com/。如果應(yīng)用被部署在一個(gè)子路徑上厦章,你就需要用這個(gè)選項(xiàng)指定這個(gè)子路徑镇匀。例如,如果你的應(yīng)用被部署在https://www.xxx.com/my-app/袜啃,則設(shè)置 publicPath 為 /my-app/汗侵。
這個(gè)值在開發(fā)環(huán)境下同樣生效。如果你想把開發(fā)服務(wù)器架設(shè)在根路徑
,你可以使用一個(gè)條件式的值:
module.exports={
//基本路徑
publicPath:process.env.NODE\_ENV=== 'production' ? '/haining-Admin/' : '/'
}
通常開發(fā)環(huán)境晰韵,本地運(yùn)行都會(huì)直接部署在根路徑上发乔,publicPath設(shè)置為'/',訪問地址是你的IP地址雪猪。如下是設(shè)置成'/app'的效果:
從上面可以得知栏尚,靜態(tài)資源文件都是在app下的,所以在dist下新增添一個(gè)app目錄浪蹂,把dist下文件放到app下抵栈,相當(dāng)于一個(gè)文件的路徑告材,可以發(fā)現(xiàn)項(xiàng)目會(huì)正常啟動(dòng)坤次。一般nginx都會(huì)配置一個(gè)靜態(tài)資源目錄,打包后的文件都會(huì)放到這個(gè)靜態(tài)資源目錄里面斥赋,nginx去做映射缰猴,所以publicPath這個(gè)屬性基本不用改。'/'就行疤剑。
結(jié)論:publicPath配置成'/aaa/bbb/ccc'滑绒, 則需在相應(yīng)的服務(wù)器路徑中新建aaa>bbb>ccc的文件夾,然后將打包后的文件放進(jìn)去隘膘,就ok啦疑故。
項(xiàng)目中,我會(huì)在.env.production文件中設(shè)置一個(gè)變量VUE_APP_BASE_URL 弯菊,項(xiàng)目打包后告訴相關(guān)人員 nginx 路由前綴是什么即可
# nginx 路由前綴
VUE_APP_BASE_URL = 'ancientCms'
這里補(bǔ)充一下: base和publicpath
如果在history路由模式下纵势,一般改配置的話,兩個(gè)都要一起改管钳。publicpath針對(duì)的是項(xiàng)目部署的路徑問題钦铁, base針對(duì)的是頁(yè)面路由url的路徑問題,缺一不可才漆。
outputDir
Type: string
Default: 'dist'
輸出文件目錄牛曹,當(dāng)運(yùn)行 vue-cli-service build 時(shí)生成的生產(chǎn)環(huán)境構(gòu)建文件的目錄醇滥。注意目標(biāo)目錄在構(gòu)建之前會(huì)被清除 (構(gòu)建時(shí)傳入 --no-clean 可關(guān)閉該行為)。
module.exports={
//build時(shí)構(gòu)建文件的目錄
outputDir: "dist",
}
assetsDir
Type: string
Default: ''
build時(shí)放置生成的靜態(tài)資源 (js焰手、css、img怀喉、fonts) 的 (相對(duì)于 outputDir 的) 目錄。
注:從生成的資源覆寫 filename 或 chunkFilename 時(shí),assetsDir 會(huì)被忽略见间。
module.exports={
//build時(shí)放置靜態(tài)資源的目錄
assetsDir: "static",
}
indexPath
Type: string
Default: 'index.html'
指定生成的 index.html 的輸出路徑 (相對(duì)于 outputDir)。也可以是一個(gè)絕對(duì)路徑工猜。
module.exports={
//html 的輸出路徑
indexPath: "index.html",
}
filenameHashing
Type: boolean
Default: true
默認(rèn)情況下米诉,生成的靜態(tài)資源在它們的文件名中包含了 hash 以便更好的控制緩存篷帅。然而魏身,這也要求 index 的 HTML 是被 Vue CLI 自動(dòng)生成的。如果你無(wú)法使用 Vue CLI 生成的 index HTML税朴,你可以通過將這個(gè)選項(xiàng)設(shè)為 false 來(lái)關(guān)閉文件名哈希
module.exports={
//默認(rèn)在生成的靜態(tài)資源文件名中包含hash以控制緩存
filenameHashing: true,
}
直觀效果:當(dāng)運(yùn)行npm run build時(shí)家制,
打包后的文件后面都會(huì)帶一個(gè)8位的hash值,那啥是個(gè)hash值觅廓?
在打包出來(lái)的文件名上加上文件內(nèi)容的hash是目前最常見的有效使用瀏覽器長(zhǎng)緩存的方法杈绸,js文件如果有內(nèi)容更新贤笆,hash就會(huì)更新,瀏覽器請(qǐng)求路徑變化所以更新緩存篡殷,如果js內(nèi)容不變埋涧,hash不變,直接用緩存棘催。(這段話是從別的文章里面參考的)。
將filenameHashing這個(gè)值設(shè)置為false試試邑跪,就不會(huì)帶那個(gè)后綴hash值。
pages
Type: Object
Default: undefined
在 multi-page(多頁(yè))模式下構(gòu)建應(yīng)用砸琅。每個(gè)“page”應(yīng)該有一個(gè)對(duì)應(yīng)的 JavaScript 入口文件症脂。
module.exports={
pages:{
index:{
//page的入口文件
entry:'src/index/main.js',
//模板文件
template:'public/index.html',
// 在 dist/index.html 的輸出
filename:'index.html',
//當(dāng)使用頁(yè)面titlt選項(xiàng)時(shí),
// template 中的 title 標(biāo)簽需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title:'Index Page',
// 在這個(gè)頁(yè)面中包含的塊淫僻,默認(rèn)情況下會(huì)包含
// 提取出來(lái)的通用 chunk 和 vendor chunk雳灵。
chunks:['chunk-vendors','chunk-common','index']
},
subpage:'src/subpage/main.js'
},
}
lintOnSave
Type:
boolean
|'warning'
|'default'
|'error'
Default:'default'
是否在開發(fā)環(huán)境下通過 eslint-loader 在每次保存時(shí) lint 代碼。這個(gè)值會(huì)在@vue/cli-plugin-eslint
被安裝之后生效橙凳。
設(shè)置為true
或'warning'
時(shí)笑撞,eslint-loader
會(huì)將 lint 錯(cuò)誤輸出為編譯警告茴肥。默認(rèn)情況下荡灾,警告僅僅會(huì)被輸出到命令行批幌,且不會(huì)使得編譯失敗。
module.exports = {
//是否在開發(fā)環(huán)境下通過 eslint-loader 在每次保存時(shí) lint 代碼 (在生產(chǎn)構(gòu)建時(shí)禁用 eslint-loader)
lintOnSave: process.env.NODE_ENV !== 'production'
}
runtimeCompiler
Type: boolean
Default: false
是否使用包含運(yùn)行時(shí)編譯器的 Vue 構(gòu)建版本皆警。設(shè)置為 true 后你就可以在 Vue 組件中使用 template 選項(xiàng)了信姓,但是這會(huì)讓你的應(yīng)用額外增加 10kb 左右绸罗。
module.exports = {
// 是否使用包含運(yùn)行時(shí)編譯器的 Vue 構(gòu)建版本
runtimeCompiler: false,
}
transpileDependencies
Type: Array<string | RegExp>
Default: []
默認(rèn)情況下 babel-loader 會(huì)忽略所有 node_modules 中的文件珊蟀。如果你想要通過 Babel 顯式轉(zhuǎn)譯一個(gè)依賴,可以在這個(gè)選項(xiàng)中列出來(lái)腻窒。
module.exports = {
// Babel 顯式轉(zhuǎn)譯列表
transpileDependencies: [],
}
productionSourceMap
Type: boolean
Default: true
如果你不需要生產(chǎn)環(huán)境的 source map,可以將其設(shè)置為 false 以加速生產(chǎn)環(huán)境構(gòu)建趟薄。
module.exports = {
// 是否在構(gòu)建生產(chǎn)包時(shí)生成sourcdeMap
productionSourceMap: process.env.NODE_ENV === "development",
}
crossorigin(不理解)
Type: string
Default: undefined
設(shè)置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 標(biāo)簽的 crossorigin 屬性杭煎。
需要注意的是該選項(xiàng)僅影響由 html-webpack-plugin 在構(gòu)建時(shí)注入的標(biāo)簽 - 直接寫在模版 (public/index.html) 中的標(biāo)簽不受影響卒落。
module.exports = {
// 設(shè)置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 標(biāo)簽的 crossorigin 屬性(注:僅影響構(gòu)建時(shí)注入的標(biāo)簽)
crossorigin: "",
}
integrity
Type: boolean
Default: false
在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 標(biāo)簽上啟用 Subresource Integrity (SRI)儡毕。如果你構(gòu)建后的文件是部署在 CDN 上的,啟用該選項(xiàng)可以提供額外的安全性雷恃。
module.exports = {
// 在生成的 HTML 中的 <link rel="stylesheet"> 和 <script> 標(biāo)簽上啟用 Subresource Integrity (SRI)
integrity: false,
}
- Webpack相關(guān)配置
configureWebpack
Type: Object | Function
除了上述使用 chainWebpack 來(lái)改變 webpack 內(nèi)部配置外倒槐,我們還可以使用 configureWebpack 來(lái)進(jìn)行修改附井,兩者的不同點(diǎn)在于 chainWebpack 是鏈?zhǔn)叫薷挠酪悖?configureWebpack 更傾向于整體替換和修改。
configureWebpack: { devtool: "source-map" },
chainWebpack
Type: Object | Function
chainWebpack 配置項(xiàng)允許我們更細(xì)粒度的控制 webpack 的內(nèi)部配置着逐,其集成的是 webpack-chain這一插件漫雕,該插件可以讓我們能夠使用鏈?zhǔn)讲僮鱽?lái)修改配置
chainWebpack: config => {
config.resolve.alias
.set('common', resolve('src/common'))
.set('components', resolve('src/components'))
.set('http', resolve('src/http'))
.set('base', resolve('src/base'))
.set('views', resolve('src/views'))
.set('store', resolve('src/store'))
.set('filters', resolve('src/filters'))
.set('directives', resolve('src/directives'))
.set('router', resolve('src/router'));
config.plugin('preload').tap(() => [
{
rel: 'preload',
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
include: 'initial',
},
]);
config.plugins.delete('prefetch');
config.plugin('provide').use(webpack.ProvidePlugin, [{
'window.Quill': 'quill'
}])
},
Css相關(guān)配置
css: {
loaderOptions: {
postcss: {
plugins: [
require("postcss-pxtorem")({
rootValue: 37.5, // 換算的基數(shù),數(shù)值具體看你的設(shè)計(jì)稿 另外提醒下vant-UI的官方根字體大小是37.5
selectorBlackList: [], // 忽略轉(zhuǎn)換正則匹配項(xiàng)
unitPrecision: 3,
propList: ["*"], // 需要做轉(zhuǎn)化處理的屬性浸间,如`hight`魁蒜、`width`吩翻、`margin`等狭瞎,`*`表示全部
minPixelValue: 3 // 小于或等于`3px`不轉(zhuǎn)換為視窗單位
})
]
},
less: {
modifyVars: {
hack: `true; @import "${resolve("./src/assets/styles/reset.less")}";`
}
}
}
}
devServer
如果你的前端應(yīng)用和后端 API 服務(wù)器沒有運(yùn)行在同一個(gè)主機(jī)上搏予,你需要在開發(fā)環(huán)境下將 API 請(qǐng)求代理到 API 服務(wù)器雪侥。這個(gè)問題可以通過 vue.config.js 中的 devServer.proxy 選項(xiàng)來(lái)配置。
補(bǔ)充知識(shí)
所謂的跨域就是不同源锌妻,不滿足協(xié)議旬牲、域名原茅、端口都相同的約定
http://www.test.com/dir/login.html 同源
https://www.test.com/index.html 不同源 協(xié)議不同(https)
http://www.test.com:90/index.html 不同源 端口不同(90)
http://www.demo.com/index.html 不同源 域名不同(demo)
當(dāng)協(xié)議员咽、域名贮预、端口中任意一個(gè)不相同時(shí),就是不同源滑频。若不同源之間相互請(qǐng)求資源峡迷,就算作跨域
補(bǔ)充知識(shí)
反向代理(Reverse Proxy)方式是指以代理服務(wù)器來(lái)接受網(wǎng)絡(luò)上的連接請(qǐng)求你虹,然后將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器傅物,并將服務(wù)器上得到的結(jié)果返回給請(qǐng)求連接的客戶端,此時(shí)代理服務(wù)器對(duì)外就表現(xiàn)為一個(gè)反向代理服務(wù)器蒿褂。客戶端無(wú)需做任何配置娄帖。
修改config/index.js /vue.config.js文件(改完之后千萬(wàn)記得要重新 npm run dev)
module.exports = {
devServer: {
host: "0.0.0.0", //同一局域網(wǎng)下可以用前端的本地地址訪問
port: "7978",
hot: true,
/* 自動(dòng)打開瀏覽器 */
open: false,
overlay: {
warning: false,
error: true
},
/* 跨域代理 */
proxy: {
[process.env.VUE_APP_BASE_API]: {
/* 目標(biāo)代理服務(wù)器地址 */
// target: process.env.VUE_APP_BASE_URI, //
target: "http://xxx/xx", //
/* 允許跨域 */
changeOrigin: true,
ws: true,
pathRewrite: {
// "^/dev-api": ""
["^" + process.env.VUE_APP_BASE_API]: ""
}
}
}
},
}
derServer下的參數(shù)配置
host 將他的值修改為 0.0.0.0近速,代表可以訪問本機(jī)所有的IP地址堪旧,讓vue項(xiàng)目可通過localhost和IP同時(shí)訪問崎场。
Type: string
Default: localhost
作用:用于指定devDerve使用的host。
port 設(shè)置端口號(hào)
Type: number
作用: 指定要監(jiān)聽請(qǐng)求的端口號(hào)
open 是否在第一次編譯時(shí)是自動(dòng)打開瀏覽器
Type: boolean | string
Default: false
作用:用于設(shè)置 server 啟動(dòng)后是否自動(dòng)打開瀏覽器干厚。
hot 開啟為true蛮瞄,啟動(dòng)熱重載谆扎,自動(dòng)刷新頁(yè)面
Type: boolean | string
Default: true
作用:用于設(shè)置代碼保存時(shí)是否進(jìn)行熱更新(局部刷新堂湖,不刷新整個(gè)頁(yè)面)。
hot和hotOnly的區(qū)別
- hot: true
單純?cè)O(shè)置為true的時(shí)候伺糠,如果編譯報(bào)錯(cuò)训桶,會(huì)拋出錯(cuò)誤酣倾,你重新改成正確的,這個(gè)時(shí)候又會(huì)觸發(fā)重新編譯午绳,整個(gè)瀏覽器會(huì)重新刷新箱叁! - hotOnly: true
這個(gè)也設(shè)置的話,如果編譯報(bào)錯(cuò)算色,你再改成正確的螟够,重新編譯妓笙,瀏覽器不會(huì)刷新!
區(qū)別在于萧福,刷新鲫忍,有些復(fù)現(xiàn)步驟比較復(fù)雜的話果录,刷掉了瀏覽器篷就,要一步步重新點(diǎn)。
hot 和 hotOnly 的區(qū)別是在某些模塊不支持熱更新的情況下智润,前者會(huì)自動(dòng)刷新頁(yè)面永品,后者不會(huì)刷新頁(yè)面鼎姐,而是在控制臺(tái)輸出熱更新失敗
https
Type: boolean | object
Default: false
作用:用于設(shè)置是否啟用https
inline
Type: boolean | string
Default: true
作用:用于設(shè)置代碼保存時(shí)是否自動(dòng)刷新頁(yè)面更振。
overlay
overlay: { // 錯(cuò)誤肯腕、警告在頁(yè)面彈出
warning: false,
error: true
},
proxy下的參數(shù)配置
/* 跨域代理 */
proxy: {
'/api/': {
/* 目標(biāo)代理服務(wù)器地址 */
target: "http://localhost:8080", //
/* 允許跨域 */
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api/': ""
}
}
}
targe 代理的服務(wù)器实撒,也就是api要訪問的服務(wù)器涉瘾。
changeOrigin 允許跨域立叛, 為false時(shí)贡茅,請(qǐng)求頭中host仍然是瀏覽器發(fā)送過來(lái)的host;如果設(shè)置成true:發(fā)送請(qǐng)求頭中host會(huì)設(shè)置成target的值
ws 是否代理websocket
pathRewrite 重寫 url 的 path 部分
問:pathRewrite里面的'^/api/'是什么意思顶考?
答:用代理,首先你得有一個(gè)標(biāo)識(shí)艘策,告訴他渊季,帶有/api/的連接要用代理梭域,不然可能html,css富玷,js這些靜態(tài)資源都跑去代理赎懦。所以我們只要接口用代理幻工,靜態(tài)文件用本地囊颅。
'/api/':{},就是告訴node盲憎,我接口只要是'/api/'開頭的才用代理胳挎,所以你的接口就要這么寫:'/api/xx/xx'慕爬,最后代理的路徑就是:http://xxx.xx.com/api/xx/xx
可是不對(duì)啊,正確的接口路徑里面沒有/api啊磅甩,所以就需要pathRewrite更胖,用 '^/api/':'',把/api給去掉饵逐,這樣既能有正確的表示倍权,又能在請(qǐng)求接口的時(shí)候去掉api捞烟。
此文記錄下來(lái)题画,方便自己遺忘的時(shí)候能夠快速查閱苍息,如有錯(cuò)誤請(qǐng)指出。
參考鏈接:
http://www.reibang.com/p/b358a91bdf2d
https://www.jb51.net/article/174200.htm
https://blog.csdn.net/liu_yunzhao/article/details/90520028
這篇文章講的也很詳細(xì)https://blog.csdn.net/guozhangqiang/article/details/87197870