[{"data":1,"prerenderedAt":4711},["ShallowReactive",2],{"page-\u002Fvue\u002Fvue学习笔记":3},{"id":4,"title":5,"body":6,"description":4704,"extension":4705,"meta":4706,"navigation":121,"path":4707,"seo":4708,"stem":4709,"__hash__":4710},"content\u002FVue\u002FVue学习笔记.md","Vue学习笔记",{"type":7,"value":8,"toc":4660},"minimark",[9,13,22,27,32,35,52,55,77,80,100,104,107,204,207,251,254,303,307,311,450,454,460,464,467,594,597,606,610,613,659,663,666,703,707,710,751,755,759,762,766,769,778,781,801,804,813,816,913,916,940,944,951,954,989,992,1007,1011,1015,1192,1196,1199,1288,1291,1300,1304,1311,1320,1324,1327,1376,1380,1384,1387,1439,1442,1457,1461,1464,1627,1631,1820,1824,1827,2087,2089,2103,2106,2115,2118,2150,2154,2158,2304,2308,2443,2447,2893,2897,3009,3013,3357,3361,3777,3781,4381,4385,4419,4423,4572,4576,4599,4603,4656],[10,11,5],"h1",{"id":12},"vue学习笔记",[14,15,16,17],"p",{},"@",[18,19,21],"a",{"href":20},"%E7%9B%AE%E5%BD%95","TOC",[23,24,26],"h2",{"id":25},"一环境搭建","一、环境搭建",[28,29,31],"h3",{"id":30},"_1-nodejsnpmcnpm","1. Node.js、Npm、Cnpm",[14,33,34],{},"Npm依赖于Node.js，直接下载安装，并配置环境变量\n由于个人比较习惯使用 shift+右键 唤起powershell来执行命令，默认powershell不允许执行脚本文件，需要解除此安全策略",[36,37,42],"pre",{"className":38,"code":39,"language":40,"meta":41,"style":41},"language-powershell shiki shiki-themes github-light github-dark"," set-ExecutionPolicy RemoteSigned\n","powershell","",[43,44,45],"code",{"__ignoreMap":41},[46,47,50],"span",{"class":48,"line":49},"line",1,[46,51,39],{},[14,53,54],{},"Npm默认安装位置在C盘，修改默认路径与查看Npm配置",[36,56,58],{"className":38,"code":57,"language":40,"meta":41,"style":41},"npm config set prefix \"E:\u002FNpm\"   # 配置全局安装目录\nnpm config set cache \"E:\u002FNpm\u002Fnpm_cache\"   # 配置缓存目录\nnpm config ls   # 查看配置\n",[43,59,60,65,71],{"__ignoreMap":41},[46,61,62],{"class":48,"line":49},[46,63,64],{},"npm config set prefix \"E:\u002FNpm\"   # 配置全局安装目录\n",[46,66,68],{"class":48,"line":67},2,[46,69,70],{},"npm config set cache \"E:\u002FNpm\u002Fnpm_cache\"   # 配置缓存目录\n",[46,72,74],{"class":48,"line":73},3,[46,75,76],{},"npm config ls   # 查看配置\n",[14,78,79],{},"由于一些已知原因国外网络较慢，于是选择使用淘宝的cnpm进行构建",[36,81,83],{"className":38,"code":82,"language":40,"meta":41,"style":41},"npm install cnpm -g\ncnpm install vue\ncnpm install --global vue-cli\n",[43,84,85,90,95],{"__ignoreMap":41},[46,86,87],{"class":48,"line":49},[46,88,89],{},"npm install cnpm -g\n",[46,91,92],{"class":48,"line":67},[46,93,94],{},"cnpm install vue\n",[46,96,97],{"class":48,"line":73},[46,98,99],{},"cnpm install --global vue-cli\n",[28,101,103],{"id":102},"_2-vue-cli","2. Vue-cli",[14,105,106],{},"直接构建一个基于webpack的项目，需要进行一些配置",[36,108,110],{"className":38,"code":109,"language":40,"meta":41,"style":41},"> vue init webpack project-name\n\n? Project name project-name\n? Project description A Vue.js project\n? Author Czy \u003C651525974@qq.com>\n? Vue build standalone\n? Install vue-router? Yes\n? Use ESLint to lint your code? No\n? Set up unit tests No\n? Setup e2e tests with Nightwatch? No\n? Should we run `npm install` for you after the project has been created? (recommended) no\n\n   vue-cli · Generated \"project-name\".\n\n# Project initialization finished!\n# ========================\n",[43,111,112,117,123,128,134,140,146,152,158,164,170,176,181,187,192,198],{"__ignoreMap":41},[46,113,114],{"class":48,"line":49},[46,115,116],{},"> vue init webpack project-name\n",[46,118,119],{"class":48,"line":67},[46,120,122],{"emptyLinePlaceholder":121},true,"\n",[46,124,125],{"class":48,"line":73},[46,126,127],{},"? Project name project-name\n",[46,129,131],{"class":48,"line":130},4,[46,132,133],{},"? Project description A Vue.js project\n",[46,135,137],{"class":48,"line":136},5,[46,138,139],{},"? Author Czy \u003C651525974@qq.com>\n",[46,141,143],{"class":48,"line":142},6,[46,144,145],{},"? Vue build standalone\n",[46,147,149],{"class":48,"line":148},7,[46,150,151],{},"? Install vue-router? Yes\n",[46,153,155],{"class":48,"line":154},8,[46,156,157],{},"? Use ESLint to lint your code? No\n",[46,159,161],{"class":48,"line":160},9,[46,162,163],{},"? Set up unit tests No\n",[46,165,167],{"class":48,"line":166},10,[46,168,169],{},"? Setup e2e tests with Nightwatch? No\n",[46,171,173],{"class":48,"line":172},11,[46,174,175],{},"? Should we run `npm install` for you after the project has been created? (recommended) no\n",[46,177,179],{"class":48,"line":178},12,[46,180,122],{"emptyLinePlaceholder":121},[46,182,184],{"class":48,"line":183},13,[46,185,186],{},"   vue-cli · Generated \"project-name\".\n",[46,188,190],{"class":48,"line":189},14,[46,191,122],{"emptyLinePlaceholder":121},[46,193,195],{"class":48,"line":194},15,[46,196,197],{},"# Project initialization finished!\n",[46,199,201],{"class":48,"line":200},16,[46,202,203],{},"# ========================\n",[14,205,206],{},"我选择了手动安装依赖，但是由于依赖生成的 node_modules 动辄百兆，并且若是出现问题，需要重新构建，由于文件过多，删除时相当慢，而且个人更倾向于像 Maven 一样共用依赖，于是使用 mklink 做目录链接\n首先复制 package.json 到某目录，在此执行安装 cnpm i，会自动生成 node_modules ,此后在项目文件夹执行mklink即可，也可以先建好目录链接再执行 cnpm i (i即install缩写)",[36,208,210],{"className":38,"code":209,"language":40,"meta":41,"style":41},"Directory: D:\\Project\\Library\\Modules\nMode                LastWriteTime         Length Name\n----                -------------         ------ ----\nd-----         20\u002F01\u002F09     09:21                node_modules\n-a----         20\u002F01\u002F04     14:09             62 mklink.md\n-a----         20\u002F01\u002F04     14:07           2707 package.json\n\nPS D:\\Project\\Library\\Modules> npm i\n",[43,211,212,217,222,227,232,237,242,246],{"__ignoreMap":41},[46,213,214],{"class":48,"line":49},[46,215,216],{},"Directory: D:\\Project\\Library\\Modules\n",[46,218,219],{"class":48,"line":67},[46,220,221],{},"Mode                LastWriteTime         Length Name\n",[46,223,224],{"class":48,"line":73},[46,225,226],{},"----                -------------         ------ ----\n",[46,228,229],{"class":48,"line":130},[46,230,231],{},"d-----         20\u002F01\u002F09     09:21                node_modules\n",[46,233,234],{"class":48,"line":136},[46,235,236],{},"-a----         20\u002F01\u002F04     14:09             62 mklink.md\n",[46,238,239],{"class":48,"line":142},[46,240,241],{},"-a----         20\u002F01\u002F04     14:07           2707 package.json\n",[46,243,244],{"class":48,"line":148},[46,245,122],{"emptyLinePlaceholder":121},[46,247,248],{"class":48,"line":154},[46,249,250],{},"PS D:\\Project\\Library\\Modules> npm i\n",[14,252,253],{},"在 powershell 中不能执行 mklink ，需要使用CMD进行mklink，然后运行 npm run dev 即可正常启动项目",[36,255,257],{"className":38,"code":256,"language":40,"meta":41,"style":41},"C:\\Users\\Czy\\Desktop\\project-name>mklink \u002FJ node_modules D:\\Project\\Library\\Modules\\node_modules\nJunction created for node_modules \u003C\u003C===>> D:\\Project\\Library\\Modules\\node_modules\n\nC:\\Users\\Czy\\Desktop\\project-name>npm run dev\n> project-name@1.0.0 dev C:\\Users\\Czy\\Desktop\\project-name\n> webpack-dev-server --inline --progress --config build\u002Fwebpack.dev.conf.js\n 10 13 13 13 13% building modules 33\u002F37 modules 4 active ...ct-name\\src\\components\\HelloWorld.vue{ parser: \"babylon\" } is deprecated; we now treat it as {  14 14 95% emitting\n DONE  Compiled successfully in 14788ms                                                                       1:09:13 PM\n I  Your application is running here: http:\u002F\u002Flocalhost:8080\n",[43,258,259,264,269,273,278,283,288,293,298],{"__ignoreMap":41},[46,260,261],{"class":48,"line":49},[46,262,263],{},"C:\\Users\\Czy\\Desktop\\project-name>mklink \u002FJ node_modules D:\\Project\\Library\\Modules\\node_modules\n",[46,265,266],{"class":48,"line":67},[46,267,268],{},"Junction created for node_modules \u003C\u003C===>> D:\\Project\\Library\\Modules\\node_modules\n",[46,270,271],{"class":48,"line":73},[46,272,122],{"emptyLinePlaceholder":121},[46,274,275],{"class":48,"line":130},[46,276,277],{},"C:\\Users\\Czy\\Desktop\\project-name>npm run dev\n",[46,279,280],{"class":48,"line":136},[46,281,282],{},"> project-name@1.0.0 dev C:\\Users\\Czy\\Desktop\\project-name\n",[46,284,285],{"class":48,"line":142},[46,286,287],{},"> webpack-dev-server --inline --progress --config build\u002Fwebpack.dev.conf.js\n",[46,289,290],{"class":48,"line":148},[46,291,292],{}," 10 13 13 13 13% building modules 33\u002F37 modules 4 active ...ct-name\\src\\components\\HelloWorld.vue{ parser: \"babylon\" } is deprecated; we now treat it as {  14 14 95% emitting\n",[46,294,295],{"class":48,"line":154},[46,296,297],{}," DONE  Compiled successfully in 14788ms                                                                       1:09:13 PM\n",[46,299,300],{"class":48,"line":160},[46,301,302],{}," I  Your application is running here: http:\u002F\u002Flocalhost:8080\n",[23,304,306],{"id":305},"二vue实例","二、Vue实例",[28,308,310],{"id":309},"_1-目录结构","1. 目录结构",[36,312,314],{"className":38,"code":313,"language":40,"meta":41,"style":41},"vue-cli\n   ├── build\u002F                # Webpack 配置目录\n   ├── dist\u002F                 # build 生成的生产环境下的项目\n   ├── config\u002F               # Vue基本配置文件，可以设置监听端口，打包输出等\n   ├── node_modules\u002F         # 依赖包，即 cnpm i生成的目录\n   ├── src\u002F                  # 源码目录（构建应用专注于此目录）\n   │   ├── assets\u002F           # 放置需要经由 Webpack 处理的静态文件，通常为样式类文件，如CSS，SASS以及一些外部的JS\n   │   ├── components\u002F       # 组件目录\n   │   ├── filters\u002F          # 过滤器\n   │   ├── store\u002F    　　　　 # 状态管理\n   │   ├── routes\u002F           # 路由，此处配置项目路由\n   │   ├── utils\u002F            # 工具类\n   │   ├── views\u002F            # 路由页面组件\n   │   ├── App.vue           # 根组件\n   │   └── main.js           # 入口文件\n   ├── index.html            # 主页，打开页面后会被Vue注入\n   ├── static\u002F               # 放置无需经由 Webpack 处理的静态文件，通常放置图片类资源\n   ├── .babelrc              # Babel 转码配置\n   ├── .editorconfig         # 代码格式\n   ├── .eslintignore         # ESLint 忽略\n   ├── .eslintrc             # ESLint 配置\n   ├── .gitignore            # Git 忽略\n   ├── package.json          # 本项目的配置信息，启动方式\n   ├── package-lock.json     # 记录当前状态下实际安装的各个npm package的具体来源和版本号\n   └── README.md             # 项目说明\n",[43,315,316,321,326,331,336,341,346,351,356,361,366,371,376,381,386,391,396,402,408,414,420,426,432,438,444],{"__ignoreMap":41},[46,317,318],{"class":48,"line":49},[46,319,320],{},"vue-cli\n",[46,322,323],{"class":48,"line":67},[46,324,325],{},"   ├── build\u002F                # Webpack 配置目录\n",[46,327,328],{"class":48,"line":73},[46,329,330],{},"   ├── dist\u002F                 # build 生成的生产环境下的项目\n",[46,332,333],{"class":48,"line":130},[46,334,335],{},"   ├── config\u002F               # Vue基本配置文件，可以设置监听端口，打包输出等\n",[46,337,338],{"class":48,"line":136},[46,339,340],{},"   ├── node_modules\u002F         # 依赖包，即 cnpm i生成的目录\n",[46,342,343],{"class":48,"line":142},[46,344,345],{},"   ├── src\u002F                  # 源码目录（构建应用专注于此目录）\n",[46,347,348],{"class":48,"line":148},[46,349,350],{},"   │   ├── assets\u002F           # 放置需要经由 Webpack 处理的静态文件，通常为样式类文件，如CSS，SASS以及一些外部的JS\n",[46,352,353],{"class":48,"line":154},[46,354,355],{},"   │   ├── components\u002F       # 组件目录\n",[46,357,358],{"class":48,"line":160},[46,359,360],{},"   │   ├── filters\u002F          # 过滤器\n",[46,362,363],{"class":48,"line":166},[46,364,365],{},"   │   ├── store\u002F    　　　　 # 状态管理\n",[46,367,368],{"class":48,"line":172},[46,369,370],{},"   │   ├── routes\u002F           # 路由，此处配置项目路由\n",[46,372,373],{"class":48,"line":178},[46,374,375],{},"   │   ├── utils\u002F            # 工具类\n",[46,377,378],{"class":48,"line":183},[46,379,380],{},"   │   ├── views\u002F            # 路由页面组件\n",[46,382,383],{"class":48,"line":189},[46,384,385],{},"   │   ├── App.vue           # 根组件\n",[46,387,388],{"class":48,"line":194},[46,389,390],{},"   │   └── main.js           # 入口文件\n",[46,392,393],{"class":48,"line":200},[46,394,395],{},"   ├── index.html            # 主页，打开页面后会被Vue注入\n",[46,397,399],{"class":48,"line":398},17,[46,400,401],{},"   ├── static\u002F               # 放置无需经由 Webpack 处理的静态文件，通常放置图片类资源\n",[46,403,405],{"class":48,"line":404},18,[46,406,407],{},"   ├── .babelrc              # Babel 转码配置\n",[46,409,411],{"class":48,"line":410},19,[46,412,413],{},"   ├── .editorconfig         # 代码格式\n",[46,415,417],{"class":48,"line":416},20,[46,418,419],{},"   ├── .eslintignore         # ESLint 忽略\n",[46,421,423],{"class":48,"line":422},21,[46,424,425],{},"   ├── .eslintrc             # ESLint 配置\n",[46,427,429],{"class":48,"line":428},22,[46,430,431],{},"   ├── .gitignore            # Git 忽略\n",[46,433,435],{"class":48,"line":434},23,[46,436,437],{},"   ├── package.json          # 本项目的配置信息，启动方式\n",[46,439,441],{"class":48,"line":440},24,[46,442,443],{},"   ├── package-lock.json     # 记录当前状态下实际安装的各个npm package的具体来源和版本号\n",[46,445,447],{"class":48,"line":446},25,[46,448,449],{},"   └── README.md             # 项目说明\n",[28,451,453],{"id":452},"_2-生命周期","2. 生命周期",[455,456],"img",{"src":457,"width":458,"referrerPolicy":459},"https:\u002F\u002Fv2.cn.vuejs.org\u002Fimages\u002Flifecycle.png","600px","no-referrer",[28,461,463],{"id":462},"_3过滤器","3.过滤器",[14,465,466],{},"过滤器可将数据进行过滤，例如可以在打印表格中将1显示为OK",[36,468,472],{"className":469,"code":470,"language":471,"meta":41,"style":41},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F模板中使用\n{{status | statusFilter}} \u002F\u002F使用{{ 数据 | 过滤器定义}} 支持链式 {{ 数据 | 过滤器定义1 |  过滤器定义2}}\n\n\u002F\u002F可以在style中引用\n:style=\"status | colorFilter\"\n\n\u002F\u002F定义过滤器\nexport default { \n    filters:{\n      statusFilter: function(val){\n        switch (val){\n          case true : return \"OK\";\n          case false : return \"Block\";\n        }\n        return \"待获取\";\n      },\n      colorFilter: function(val){\n        switch (val){\n          case true : return {'color':'green'};\n          case false : return {'color':'red'};\n        }\n        return {'color':'black'};\n      },\n    }\n}\n","javascript",[43,473,474,479,484,488,493,498,502,507,512,517,522,527,532,537,542,547,552,557,561,566,571,575,580,584,589],{"__ignoreMap":41},[46,475,476],{"class":48,"line":49},[46,477,478],{},"\u002F\u002F模板中使用\n",[46,480,481],{"class":48,"line":67},[46,482,483],{},"{{status | statusFilter}} \u002F\u002F使用{{ 数据 | 过滤器定义}} 支持链式 {{ 数据 | 过滤器定义1 |  过滤器定义2}}\n",[46,485,486],{"class":48,"line":73},[46,487,122],{"emptyLinePlaceholder":121},[46,489,490],{"class":48,"line":130},[46,491,492],{},"\u002F\u002F可以在style中引用\n",[46,494,495],{"class":48,"line":136},[46,496,497],{},":style=\"status | colorFilter\"\n",[46,499,500],{"class":48,"line":142},[46,501,122],{"emptyLinePlaceholder":121},[46,503,504],{"class":48,"line":148},[46,505,506],{},"\u002F\u002F定义过滤器\n",[46,508,509],{"class":48,"line":154},[46,510,511],{},"export default { \n",[46,513,514],{"class":48,"line":160},[46,515,516],{},"    filters:{\n",[46,518,519],{"class":48,"line":166},[46,520,521],{},"      statusFilter: function(val){\n",[46,523,524],{"class":48,"line":172},[46,525,526],{},"        switch (val){\n",[46,528,529],{"class":48,"line":178},[46,530,531],{},"          case true : return \"OK\";\n",[46,533,534],{"class":48,"line":183},[46,535,536],{},"          case false : return \"Block\";\n",[46,538,539],{"class":48,"line":189},[46,540,541],{},"        }\n",[46,543,544],{"class":48,"line":194},[46,545,546],{},"        return \"待获取\";\n",[46,548,549],{"class":48,"line":200},[46,550,551],{},"      },\n",[46,553,554],{"class":48,"line":398},[46,555,556],{},"      colorFilter: function(val){\n",[46,558,559],{"class":48,"line":404},[46,560,526],{},[46,562,563],{"class":48,"line":410},[46,564,565],{},"          case true : return {'color':'green'};\n",[46,567,568],{"class":48,"line":416},[46,569,570],{},"          case false : return {'color':'red'};\n",[46,572,573],{"class":48,"line":422},[46,574,541],{},[46,576,577],{"class":48,"line":428},[46,578,579],{},"        return {'color':'black'};\n",[46,581,582],{"class":48,"line":434},[46,583,551],{},[46,585,586],{"class":48,"line":440},[46,587,588],{},"    }\n",[46,590,591],{"class":48,"line":446},[46,592,593],{},"}\n",[14,595,596],{},"全局过滤器定义，注意当全局过滤器与局部过滤器同名时会加载局部过滤器",[36,598,600],{"className":469,"code":599,"language":471,"meta":41,"style":41},"Vue.filter('dataFormat', (input, pattern = '') => {});\n",[43,601,602],{"__ignoreMap":41},[46,603,604],{"class":48,"line":49},[46,605,599],{},[28,607,609],{"id":608},"_4计算属性","4.计算属性",[14,611,612],{},"模板内的表达式非常便利，但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。计算属性的结果会被缓存，除非依赖的响应式属性变化才会重新计算，computed擅长处理的场景：一个数据受多个数据影响",[36,614,616],{"className":469,"code":615,"language":471,"meta":41,"style":41},"模板: {{message}} 计算属性: {{reversedMessage }}\n\nexport default { \n     computed: { \n        reversedMessage: function () {\n          return this.message.split('').reverse().join('')\n        }\n      }\n}\n",[43,617,618,623,627,631,636,641,646,650,655],{"__ignoreMap":41},[46,619,620],{"class":48,"line":49},[46,621,622],{},"模板: {{message}} 计算属性: {{reversedMessage }}\n",[46,624,625],{"class":48,"line":67},[46,626,122],{"emptyLinePlaceholder":121},[46,628,629],{"class":48,"line":73},[46,630,511],{},[46,632,633],{"class":48,"line":130},[46,634,635],{},"     computed: { \n",[46,637,638],{"class":48,"line":136},[46,639,640],{},"        reversedMessage: function () {\n",[46,642,643],{"class":48,"line":142},[46,644,645],{},"          return this.message.split('').reverse().join('')\n",[46,647,648],{"class":48,"line":148},[46,649,541],{},[46,651,652],{"class":48,"line":154},[46,653,654],{},"      }\n",[46,656,657],{"class":48,"line":160},[46,658,593],{},[28,660,662],{"id":661},"_5监听器","5.监听器",[14,664,665],{},"监听数据的改变，一旦数据改变则触发监听器，watch擅长处理的场景：一个数据影响多个数据",[36,667,669],{"className":469,"code":668,"language":471,"meta":41,"style":41},"export default { \n    watch:{\n      radio: function(newV,oldV){\n        console.log(`监听radio的值改变: ${oldV} -> ${newV}`);\n      }\n    },\n}\n",[43,670,671,675,680,685,690,694,699],{"__ignoreMap":41},[46,672,673],{"class":48,"line":49},[46,674,511],{},[46,676,677],{"class":48,"line":67},[46,678,679],{},"    watch:{\n",[46,681,682],{"class":48,"line":73},[46,683,684],{},"      radio: function(newV,oldV){\n",[46,686,687],{"class":48,"line":130},[46,688,689],{},"        console.log(`监听radio的值改变: ${oldV} -> ${newV}`);\n",[46,691,692],{"class":48,"line":136},[46,693,654],{},[46,695,696],{"class":48,"line":142},[46,697,698],{},"    },\n",[46,700,701],{"class":48,"line":148},[46,702,593],{},[28,704,706],{"id":705},"_6方法","6.方法",[14,708,709],{},"响应@click触发事件",[36,711,713],{"className":469,"code":712,"language":471,"meta":41,"style":41},"\u003Cdiv  @click='search'>点击\u003C\u002Fdiv >\n\nexport default { \n    methods: {\n      clickHandle: function(e) {\n        console.log(\"我被触发了\",e);\n      }\n}\n",[43,714,715,720,724,728,733,738,743,747],{"__ignoreMap":41},[46,716,717],{"class":48,"line":49},[46,718,719],{},"\u003Cdiv  @click='search'>点击\u003C\u002Fdiv >\n",[46,721,722],{"class":48,"line":67},[46,723,122],{"emptyLinePlaceholder":121},[46,725,726],{"class":48,"line":73},[46,727,511],{},[46,729,730],{"class":48,"line":130},[46,731,732],{},"    methods: {\n",[46,734,735],{"class":48,"line":136},[46,736,737],{},"      clickHandle: function(e) {\n",[46,739,740],{"class":48,"line":142},[46,741,742],{},"        console.log(\"我被触发了\",e);\n",[46,744,745],{"class":48,"line":148},[46,746,654],{},[46,748,749],{"class":48,"line":154},[46,750,593],{},[23,752,754],{"id":753},"三组件","三、组件",[28,756,758],{"id":757},"_1-组件介绍","1. 组件介绍",[14,760,761],{},"Vue-cli默认是构建单页应用，使用Url的锚来确定组件引用，组件是可复用的 Vue 实例, 如果网页中的某一个部分需要在多个场景中使用，那么我们可以将其抽出为一个组件进行复用。组件大大提高了代码的复用率。",[28,763,765],{"id":764},"_2-使用element-ui组件库","2. 使用Element UI组件库",[14,767,768],{},"安装组件库",[36,770,772],{"className":38,"code":771,"language":40,"meta":41,"style":41},"npm i element-ui -S\n",[43,773,774],{"__ignoreMap":41},[46,775,776],{"class":48,"line":49},[46,777,771],{},[14,779,780],{},"在main.js中引入组件库",[36,782,784],{"className":469,"code":783,"language":471,"meta":41,"style":41},"import ElementUI from 'element-ui';\nimport 'element-ui\u002Flib\u002Ftheme-chalk\u002Findex.css';\nVue.use(ElementUI);\n",[43,785,786,791,796],{"__ignoreMap":41},[46,787,788],{"class":48,"line":49},[46,789,790],{},"import ElementUI from 'element-ui';\n",[46,792,793],{"class":48,"line":67},[46,794,795],{},"import 'element-ui\u002Flib\u002Ftheme-chalk\u002Findex.css';\n",[46,797,798],{"class":48,"line":73},[46,799,800],{},"Vue.use(ElementUI);\n",[14,802,803],{},"上述是全局引入，但是由于上边说了Vue是单页应用，也就是说明打包起来的项目其实就是一页，所有需要的资源将全部被打包，所以我个人更倾向于引入部分组件，当然也可以在单页cdn引入全部的组件，这样就不会打包Element UI的组件进去了，现在使用本地资源按需引入，则需要借助 babel-plugin-component ，安装依赖，运行如果提示某文件夹缺少文件则添加文件，如果提示缺少es2015则也要安装，另外更改文件.babelrc",[36,805,807],{"className":38,"code":806,"language":40,"meta":41,"style":41},"cnpm i babel-plugin-component -D\n",[43,808,809],{"__ignoreMap":41},[46,810,811],{"class":48,"line":49},[46,812,806],{},[14,814,815],{},".babelrc",[36,817,819],{"className":469,"code":818,"language":471,"meta":41,"style":41},"{\n  \"presets\": [\n    [\"env\", {\n      \"modules\": false,\n      \"targets\": {\n        \"browsers\": [\"> 1%\", \"last 2 versions\", \"not ie \u003C= 8\"]\n      }\n    }],\n    \"stage-2\",\n    [\"es2015\", { \"modules\": false }]\n  ],\n  \"plugins\": [\"transform-vue-jsx\", \"transform-runtime\",[\n      \"component\",\n      {\n        \"libraryName\": \"element-ui\",\n        \"styleLibraryName\": \"theme-chalk\"\n      }\n    ]]\n}\n",[43,820,821,826,831,836,841,846,851,855,860,865,870,875,880,885,890,895,900,904,909],{"__ignoreMap":41},[46,822,823],{"class":48,"line":49},[46,824,825],{},"{\n",[46,827,828],{"class":48,"line":67},[46,829,830],{},"  \"presets\": [\n",[46,832,833],{"class":48,"line":73},[46,834,835],{},"    [\"env\", {\n",[46,837,838],{"class":48,"line":130},[46,839,840],{},"      \"modules\": false,\n",[46,842,843],{"class":48,"line":136},[46,844,845],{},"      \"targets\": {\n",[46,847,848],{"class":48,"line":142},[46,849,850],{},"        \"browsers\": [\"> 1%\", \"last 2 versions\", \"not ie \u003C= 8\"]\n",[46,852,853],{"class":48,"line":148},[46,854,654],{},[46,856,857],{"class":48,"line":154},[46,858,859],{},"    }],\n",[46,861,862],{"class":48,"line":160},[46,863,864],{},"    \"stage-2\",\n",[46,866,867],{"class":48,"line":166},[46,868,869],{},"    [\"es2015\", { \"modules\": false }]\n",[46,871,872],{"class":48,"line":172},[46,873,874],{},"  ],\n",[46,876,877],{"class":48,"line":178},[46,878,879],{},"  \"plugins\": [\"transform-vue-jsx\", \"transform-runtime\",[\n",[46,881,882],{"class":48,"line":183},[46,883,884],{},"      \"component\",\n",[46,886,887],{"class":48,"line":189},[46,888,889],{},"      {\n",[46,891,892],{"class":48,"line":194},[46,893,894],{},"        \"libraryName\": \"element-ui\",\n",[46,896,897],{"class":48,"line":200},[46,898,899],{},"        \"styleLibraryName\": \"theme-chalk\"\n",[46,901,902],{"class":48,"line":398},[46,903,654],{},[46,905,906],{"class":48,"line":404},[46,907,908],{},"    ]]\n",[46,910,911],{"class":48,"line":410},[46,912,593],{},[14,914,915],{},"main.js",[36,917,919],{"className":469,"code":918,"language":471,"meta":41,"style":41},"import { Menu,MenuItem } from 'element-ui';\nimport 'element-ui\u002Flib\u002Ftheme-chalk\u002Findex.css';\nVue.use(Menu)\nVue.use(MenuItem)\n",[43,920,921,926,930,935],{"__ignoreMap":41},[46,922,923],{"class":48,"line":49},[46,924,925],{},"import { Menu,MenuItem } from 'element-ui';\n",[46,927,928],{"class":48,"line":67},[46,929,795],{},[46,931,932],{"class":48,"line":73},[46,933,934],{},"Vue.use(Menu)\n",[46,936,937],{"class":48,"line":130},[46,938,939],{},"Vue.use(MenuItem)\n",[28,941,943],{"id":942},"_3-创建自定义组件","3. 创建自定义组件",[14,945,946,947],{},"像这些组件库一样在组件内类似",[948,949,950],"layout",{},"作为元素使用，需要一个.vue文件作为创建的自定义组件，以及index.js暴露接口",[14,952,953],{},"index.js",[36,955,957],{"className":469,"code":956,"language":471,"meta":41,"style":41},"import layout from '.\u002Flayout';\n\u002F* istanbul ignore next *\u002F\nlayout.install = function(Vue) {\n  Vue.component(layout.name, layout);\n};\nexport default layout;\n",[43,958,959,964,969,974,979,984],{"__ignoreMap":41},[46,960,961],{"class":48,"line":49},[46,962,963],{},"import layout from '.\u002Flayout';\n",[46,965,966],{"class":48,"line":67},[46,967,968],{},"\u002F* istanbul ignore next *\u002F\n",[46,970,971],{"class":48,"line":73},[46,972,973],{},"layout.install = function(Vue) {\n",[46,975,976],{"class":48,"line":130},[46,977,978],{},"  Vue.component(layout.name, layout);\n",[46,980,981],{"class":48,"line":136},[46,982,983],{},"};\n",[46,985,986],{"class":48,"line":142},[46,987,988],{},"export default layout;\n",[14,990,991],{},"再在main.js引入并挂载即可",[36,993,995],{"className":469,"code":994,"language":471,"meta":41,"style":41},"import layout from '@\u002Fcomponents\u002Fcommon\u002Flayout';\nVue.use(layout)\n",[43,996,997,1002],{"__ignoreMap":41},[46,998,999],{"class":48,"line":49},[46,1000,1001],{},"import layout from '@\u002Fcomponents\u002Fcommon\u002Flayout';\n",[46,1003,1004],{"class":48,"line":67},[46,1005,1006],{},"Vue.use(layout)\n",[23,1008,1010],{"id":1009},"四router路由","四、Router路由",[28,1012,1014],{"id":1013},"_1-router配置","1. Router配置",[36,1016,1018],{"className":469,"code":1017,"language":471,"meta":41,"style":41},"\u002F\u002F以此配置介绍\n\nimport Vue from 'vue'\nimport Router from 'vue-router'\n\u002F\u002F引入页面组件\nimport Index from \"@\u002Fcomponents\u002Flogin\u002FIndex.vue\"\nimport ManagerIndex from \"@\u002Fcomponents\u002Fmanager\u002FIndex.vue\"\n\u002F\u002F挂载Router\nVue.use(Router)\n\nexport default new Router({\n  routes: [\n    {\n      path: '\u002F',                        \u002F\u002F 页面路径 \u002F#\u002F\n      name: \"Index\",                    \u002F\u002F 页面命名，当跳转页面需要传参时就需要使用name\n      component: Index,                 \u002F\u002F 加载组件\n    },\n    {\n      path: '\u002FManagerIndex',\n      name: \"ManagerIndex\",\n      component: ManagerIndex,\n      meta:{                             \u002F\u002F 一些配置信息\n        auth: true                       \u002F\u002F 此处配置此页面需要鉴权，需配合router.beforeEach()使用\n      },\n      children: [                        \u002F\u002F 此组件的子组件\n        {\n          path: 'OverView',              \u002F\u002F 页面路径\u002F#\u002FManagerIndex\u002FOverView\n          name: \"OverView\",\n          component: OverView\n        }\n        ]\n    }\n  ]\n})\n",[43,1019,1020,1025,1029,1034,1039,1044,1049,1054,1059,1064,1068,1073,1078,1083,1088,1093,1098,1102,1106,1111,1116,1121,1126,1131,1135,1140,1146,1152,1158,1164,1169,1175,1180,1186],{"__ignoreMap":41},[46,1021,1022],{"class":48,"line":49},[46,1023,1024],{},"\u002F\u002F以此配置介绍\n",[46,1026,1027],{"class":48,"line":67},[46,1028,122],{"emptyLinePlaceholder":121},[46,1030,1031],{"class":48,"line":73},[46,1032,1033],{},"import Vue from 'vue'\n",[46,1035,1036],{"class":48,"line":130},[46,1037,1038],{},"import Router from 'vue-router'\n",[46,1040,1041],{"class":48,"line":136},[46,1042,1043],{},"\u002F\u002F引入页面组件\n",[46,1045,1046],{"class":48,"line":142},[46,1047,1048],{},"import Index from \"@\u002Fcomponents\u002Flogin\u002FIndex.vue\"\n",[46,1050,1051],{"class":48,"line":148},[46,1052,1053],{},"import ManagerIndex from \"@\u002Fcomponents\u002Fmanager\u002FIndex.vue\"\n",[46,1055,1056],{"class":48,"line":154},[46,1057,1058],{},"\u002F\u002F挂载Router\n",[46,1060,1061],{"class":48,"line":160},[46,1062,1063],{},"Vue.use(Router)\n",[46,1065,1066],{"class":48,"line":166},[46,1067,122],{"emptyLinePlaceholder":121},[46,1069,1070],{"class":48,"line":172},[46,1071,1072],{},"export default new Router({\n",[46,1074,1075],{"class":48,"line":178},[46,1076,1077],{},"  routes: [\n",[46,1079,1080],{"class":48,"line":183},[46,1081,1082],{},"    {\n",[46,1084,1085],{"class":48,"line":189},[46,1086,1087],{},"      path: '\u002F',                        \u002F\u002F 页面路径 \u002F#\u002F\n",[46,1089,1090],{"class":48,"line":194},[46,1091,1092],{},"      name: \"Index\",                    \u002F\u002F 页面命名，当跳转页面需要传参时就需要使用name\n",[46,1094,1095],{"class":48,"line":200},[46,1096,1097],{},"      component: Index,                 \u002F\u002F 加载组件\n",[46,1099,1100],{"class":48,"line":398},[46,1101,698],{},[46,1103,1104],{"class":48,"line":404},[46,1105,1082],{},[46,1107,1108],{"class":48,"line":410},[46,1109,1110],{},"      path: '\u002FManagerIndex',\n",[46,1112,1113],{"class":48,"line":416},[46,1114,1115],{},"      name: \"ManagerIndex\",\n",[46,1117,1118],{"class":48,"line":422},[46,1119,1120],{},"      component: ManagerIndex,\n",[46,1122,1123],{"class":48,"line":428},[46,1124,1125],{},"      meta:{                             \u002F\u002F 一些配置信息\n",[46,1127,1128],{"class":48,"line":434},[46,1129,1130],{},"        auth: true                       \u002F\u002F 此处配置此页面需要鉴权，需配合router.beforeEach()使用\n",[46,1132,1133],{"class":48,"line":440},[46,1134,551],{},[46,1136,1137],{"class":48,"line":446},[46,1138,1139],{},"      children: [                        \u002F\u002F 此组件的子组件\n",[46,1141,1143],{"class":48,"line":1142},26,[46,1144,1145],{},"        {\n",[46,1147,1149],{"class":48,"line":1148},27,[46,1150,1151],{},"          path: 'OverView',              \u002F\u002F 页面路径\u002F#\u002FManagerIndex\u002FOverView\n",[46,1153,1155],{"class":48,"line":1154},28,[46,1156,1157],{},"          name: \"OverView\",\n",[46,1159,1161],{"class":48,"line":1160},29,[46,1162,1163],{},"          component: OverView\n",[46,1165,1167],{"class":48,"line":1166},30,[46,1168,541],{},[46,1170,1172],{"class":48,"line":1171},31,[46,1173,1174],{},"        ]\n",[46,1176,1178],{"class":48,"line":1177},32,[46,1179,588],{},[46,1181,1183],{"class":48,"line":1182},33,[46,1184,1185],{},"  ]\n",[46,1187,1189],{"class":48,"line":1188},34,[46,1190,1191],{},"})\n",[28,1193,1195],{"id":1194},"_2-router-link-router-view","2. router-link router-view",[14,1197,1198],{},"router-link有一个to属性，即为跳转锚点用，router-view则是根据锚点来加载Router定义的组件的容器",[36,1200,1204],{"className":1201,"code":1202,"language":1203,"meta":41,"style":41},"language-yaml shiki shiki-themes github-light github-dark","\u003Crouter-link :to=\"\u002F\">直接转到\u003C\u002Frouter-link>\n\u003Crouter-link :to=\"{ path: '\u002Fpath', query: { id: 123 }}\">query参数\u003C\u002Frouter-link>\n\u003Crouter-link :to=\"{ name: 'routername', params: { id: 123 }}\">param参数，使用name，在path中标明占位符:id\u003C\u002Frouter-link>\n\u003Crouter-view>\u003C\u002Frouter-view>\n","yaml",[43,1205,1206,1212,1249,1283],{"__ignoreMap":41},[46,1207,1208],{"class":48,"line":49},[46,1209,1211],{"class":1210},"sZZnC","\u003Crouter-link :to=\"\u002F\">直接转到\u003C\u002Frouter-link>\n",[46,1213,1214,1218,1222,1225,1228,1231,1234,1237,1239,1243,1246],{"class":48,"line":67},[46,1215,1217],{"class":1216},"s9eBZ","\u003Crouter-link :to=\"{ path",[46,1219,1221],{"class":1220},"sVt8B",": ",[46,1223,1224],{"class":1210},"'\u002Fpath'",[46,1226,1227],{"class":1220},", ",[46,1229,1230],{"class":1216},"query",[46,1232,1233],{"class":1220},": { ",[46,1235,1236],{"class":1216},"id",[46,1238,1221],{"class":1220},[46,1240,1242],{"class":1241},"sj4cs","123",[46,1244,1245],{"class":1220}," }}",[46,1247,1248],{"class":1210},"\">query参数\u003C\u002Frouter-link>\n",[46,1250,1251,1254,1257,1260,1262,1265,1267,1270,1272,1274,1276,1278,1280],{"class":48,"line":73},[46,1252,1253],{"class":1210},"\u003Crouter-link :to=\"",[46,1255,1256],{"class":1220},"{ ",[46,1258,1259],{"class":1216},"name",[46,1261,1221],{"class":1220},[46,1263,1264],{"class":1210},"'routername'",[46,1266,1227],{"class":1220},[46,1268,1269],{"class":1216},"params",[46,1271,1233],{"class":1220},[46,1273,1236],{"class":1216},[46,1275,1221],{"class":1220},[46,1277,1242],{"class":1241},[46,1279,1245],{"class":1220},[46,1281,1282],{"class":1210},"\">param参数，使用name，在path中标明占位符:id\u003C\u002Frouter-link>\n",[46,1284,1285],{"class":48,"line":130},[46,1286,1287],{"class":1210},"\u003Crouter-view>\u003C\u002Frouter-view>\n",[14,1289,1290],{},"router-link为声明式跳转，Router提供了编程式跳转",[36,1292,1294],{"className":469,"code":1293,"language":471,"meta":41,"style":41},"this.$router.push({ name: 'OverView'})\n",[43,1295,1296],{"__ignoreMap":41},[46,1297,1298],{"class":48,"line":49},[46,1299,1293],{},[28,1301,1303],{"id":1302},"_3-keep-alive","3. keep-alive",[14,1305,1306,1307,1310],{},"当 router-link 进行跳转时，组件会动态的进行创建销毁，如果想保持组件状态，可使用",[43,1308,1309],{},"\u003Ckeep-alive\u002F>","，注意这样则不会触发组件生命周期了",[36,1312,1314],{"className":1201,"code":1313,"language":1203,"meta":41,"style":41},"\u003Ckeep-alive>\u003Crouter-view>\u003C\u002Frouter-view>\u003C\u002Fkeep-alive>\n",[43,1315,1316],{"__ignoreMap":41},[46,1317,1318],{"class":48,"line":49},[46,1319,1313],{"class":1210},[28,1321,1323],{"id":1322},"_4-导航守卫","4.  导航守卫",[14,1325,1326],{},"在注册路由时在meat中声明了一个auth用来鉴权，需要配合 router.beforeEach() 以及 全局变量 使用，在main.js声明此方法，进行导航守卫，注意务必调用next()方法，否则不会执行跳转",[36,1328,1330],{"className":469,"code":1329,"language":471,"meta":41,"style":41},"router.beforeEach((to, from, next) => {\n  if (to.meta.auth && !Vue.prototype.$globalData.user) {\n    next({\n      path: \"\u002F\"\n    })\n  } else {\n    next();\n  }\n})\n",[43,1331,1332,1337,1342,1347,1352,1357,1362,1367,1372],{"__ignoreMap":41},[46,1333,1334],{"class":48,"line":49},[46,1335,1336],{},"router.beforeEach((to, from, next) => {\n",[46,1338,1339],{"class":48,"line":67},[46,1340,1341],{},"  if (to.meta.auth && !Vue.prototype.$globalData.user) {\n",[46,1343,1344],{"class":48,"line":73},[46,1345,1346],{},"    next({\n",[46,1348,1349],{"class":48,"line":130},[46,1350,1351],{},"      path: \"\u002F\"\n",[46,1353,1354],{"class":48,"line":136},[46,1355,1356],{},"    })\n",[46,1358,1359],{"class":48,"line":142},[46,1360,1361],{},"  } else {\n",[46,1363,1364],{"class":48,"line":148},[46,1365,1366],{},"    next();\n",[46,1368,1369],{"class":48,"line":154},[46,1370,1371],{},"  }\n",[46,1373,1374],{"class":48,"line":160},[46,1375,1191],{},[23,1377,1379],{"id":1378},"五方法封装","五、方法封装",[28,1381,1383],{"id":1382},"_1-全局变量","1. 全局变量",[14,1385,1386],{},"在dispose.js中声明并暴露出口",[36,1388,1390],{"className":469,"code":1389,"language":471,"meta":41,"style":41},"const $globalData = {\n  user: 0,\n  url: \"http:\u002F\u002Fdev.touchczy.top\u002F\",\n  header: {\n    'content-type': 'application\u002Fx-www-form-urlencoded'\n  }\n}\nexport default {\n  $globalData: $globalData\n}\n",[43,1391,1392,1397,1402,1407,1412,1417,1421,1425,1430,1435],{"__ignoreMap":41},[46,1393,1394],{"class":48,"line":49},[46,1395,1396],{},"const $globalData = {\n",[46,1398,1399],{"class":48,"line":67},[46,1400,1401],{},"  user: 0,\n",[46,1403,1404],{"class":48,"line":73},[46,1405,1406],{},"  url: \"http:\u002F\u002Fdev.touchczy.top\u002F\",\n",[46,1408,1409],{"class":48,"line":130},[46,1410,1411],{},"  header: {\n",[46,1413,1414],{"class":48,"line":136},[46,1415,1416],{},"    'content-type': 'application\u002Fx-www-form-urlencoded'\n",[46,1418,1419],{"class":48,"line":142},[46,1420,1371],{},[46,1422,1423],{"class":48,"line":148},[46,1424,593],{},[46,1426,1427],{"class":48,"line":154},[46,1428,1429],{},"export default {\n",[46,1431,1432],{"class":48,"line":160},[46,1433,1434],{},"  $globalData: $globalData\n",[46,1436,1437],{"class":48,"line":166},[46,1438,593],{},[14,1440,1441],{},"在main.js中引入并拓展Vue原型",[36,1443,1445],{"className":469,"code":1444,"language":471,"meta":41,"style":41},"import dispose from '@\u002Fvector\u002Fdispose'\nVue.prototype.$globalData = dispose.$globalData;\n",[43,1446,1447,1452],{"__ignoreMap":41},[46,1448,1449],{"class":48,"line":49},[46,1450,1451],{},"import dispose from '@\u002Fvector\u002Fdispose'\n",[46,1453,1454],{"class":48,"line":67},[46,1455,1456],{},"Vue.prototype.$globalData = dispose.$globalData;\n",[28,1458,1460],{"id":1459},"_2-弹窗封装","2. 弹窗封装",[14,1462,1463],{},"在dispose.js中引入组件，封装加载与弹窗，并暴露出口",[36,1465,1467],{"className":469,"code":1466,"language":471,"meta":41,"style":41},"import {\n  Message,\n  Loading\n} from 'element-ui'\n\nfunction startLoading(options) {\n  if (!options.load) return true;\n  var loadingInstance = Loading.service({\n    lock: true,\n    text: 'loading...'\n  })\n  return loadingInstance;\n}\n\nfunction endLoading(options, loadingInstance) {\n  if (!options.load) return true;\n  loadingInstance.close();\n}\n\nfunction toast(msg, type = 'error') {\n  Message({\n    message: msg,\n    type: type,\n    duration: 2000,\n    center: true\n  })\n}\nexport default {\n  $toast: toast\n}\n\nmain.js\nimport dispose from '@\u002Fvector\u002Fdispose'\nVue.prototype.$toast = dispose.$toast;\n",[43,1468,1469,1474,1479,1484,1489,1493,1498,1503,1508,1513,1518,1523,1528,1532,1536,1541,1545,1550,1554,1558,1563,1568,1573,1578,1583,1588,1592,1596,1600,1605,1609,1613,1618,1622],{"__ignoreMap":41},[46,1470,1471],{"class":48,"line":49},[46,1472,1473],{},"import {\n",[46,1475,1476],{"class":48,"line":67},[46,1477,1478],{},"  Message,\n",[46,1480,1481],{"class":48,"line":73},[46,1482,1483],{},"  Loading\n",[46,1485,1486],{"class":48,"line":130},[46,1487,1488],{},"} from 'element-ui'\n",[46,1490,1491],{"class":48,"line":136},[46,1492,122],{"emptyLinePlaceholder":121},[46,1494,1495],{"class":48,"line":142},[46,1496,1497],{},"function startLoading(options) {\n",[46,1499,1500],{"class":48,"line":148},[46,1501,1502],{},"  if (!options.load) return true;\n",[46,1504,1505],{"class":48,"line":154},[46,1506,1507],{},"  var loadingInstance = Loading.service({\n",[46,1509,1510],{"class":48,"line":160},[46,1511,1512],{},"    lock: true,\n",[46,1514,1515],{"class":48,"line":166},[46,1516,1517],{},"    text: 'loading...'\n",[46,1519,1520],{"class":48,"line":172},[46,1521,1522],{},"  })\n",[46,1524,1525],{"class":48,"line":178},[46,1526,1527],{},"  return loadingInstance;\n",[46,1529,1530],{"class":48,"line":183},[46,1531,593],{},[46,1533,1534],{"class":48,"line":189},[46,1535,122],{"emptyLinePlaceholder":121},[46,1537,1538],{"class":48,"line":194},[46,1539,1540],{},"function endLoading(options, loadingInstance) {\n",[46,1542,1543],{"class":48,"line":200},[46,1544,1502],{},[46,1546,1547],{"class":48,"line":398},[46,1548,1549],{},"  loadingInstance.close();\n",[46,1551,1552],{"class":48,"line":404},[46,1553,593],{},[46,1555,1556],{"class":48,"line":410},[46,1557,122],{"emptyLinePlaceholder":121},[46,1559,1560],{"class":48,"line":416},[46,1561,1562],{},"function toast(msg, type = 'error') {\n",[46,1564,1565],{"class":48,"line":422},[46,1566,1567],{},"  Message({\n",[46,1569,1570],{"class":48,"line":428},[46,1571,1572],{},"    message: msg,\n",[46,1574,1575],{"class":48,"line":434},[46,1576,1577],{},"    type: type,\n",[46,1579,1580],{"class":48,"line":440},[46,1581,1582],{},"    duration: 2000,\n",[46,1584,1585],{"class":48,"line":446},[46,1586,1587],{},"    center: true\n",[46,1589,1590],{"class":48,"line":1142},[46,1591,1522],{},[46,1593,1594],{"class":48,"line":1148},[46,1595,593],{},[46,1597,1598],{"class":48,"line":1154},[46,1599,1429],{},[46,1601,1602],{"class":48,"line":1160},[46,1603,1604],{},"  $toast: toast\n",[46,1606,1607],{"class":48,"line":1166},[46,1608,593],{},[46,1610,1611],{"class":48,"line":1171},[46,1612,122],{"emptyLinePlaceholder":121},[46,1614,1615],{"class":48,"line":1177},[46,1616,1617],{},"main.js\n",[46,1619,1620],{"class":48,"line":1182},[46,1621,1451],{},[46,1623,1624],{"class":48,"line":1188},[46,1625,1626],{},"Vue.prototype.$toast = dispose.$toast;\n",[28,1628,1630],{"id":1629},"_3-浅拷贝与深拷贝","3. 浅拷贝与深拷贝",[36,1632,1634],{"className":469,"code":1633,"language":471,"meta":41,"style":41},"function extend() {\n  var aLength = arguments.length;\n  var options = arguments[0];\n  var target = {};\n  var copy;\n  var i = 1;\n  if (typeof options === \"boolean\" && options === true) {\n    \u002F\u002F深拷贝 (仅递归处理对象)\n    for (; i \u003C aLength; i++) {\n      if ((options = arguments[i]) != null) {\n        if (typeof options !== 'object') {\n          return options;\n        }\n        for (var name in options) {\n          copy = options[name];\n          if (target === copy) {\n            continue;\n          }\n          target[name] = this.extend(true, options[name]);\n        }\n      }\n    }\n  } else {\n    \u002F\u002F浅拷贝\n    target = options;\n    if (aLength === i) {\n      target = this;\n      i--;\n    } \u002F\u002F如果是只有一个参数，拓展功能 如果两个以上参数，将后续对象加入到第一个对象\n    for (; i \u003C aLength; i++) {\n      options = arguments[i];\n      for (var name in options) {\n        target[name] = options[name];\n      }\n    }\n  }\n  return target;\n}\n",[43,1635,1636,1641,1646,1651,1656,1661,1666,1671,1676,1681,1686,1691,1696,1700,1705,1710,1715,1720,1725,1730,1734,1738,1742,1746,1751,1756,1761,1766,1771,1776,1780,1785,1790,1795,1799,1804,1809,1815],{"__ignoreMap":41},[46,1637,1638],{"class":48,"line":49},[46,1639,1640],{},"function extend() {\n",[46,1642,1643],{"class":48,"line":67},[46,1644,1645],{},"  var aLength = arguments.length;\n",[46,1647,1648],{"class":48,"line":73},[46,1649,1650],{},"  var options = arguments[0];\n",[46,1652,1653],{"class":48,"line":130},[46,1654,1655],{},"  var target = {};\n",[46,1657,1658],{"class":48,"line":136},[46,1659,1660],{},"  var copy;\n",[46,1662,1663],{"class":48,"line":142},[46,1664,1665],{},"  var i = 1;\n",[46,1667,1668],{"class":48,"line":148},[46,1669,1670],{},"  if (typeof options === \"boolean\" && options === true) {\n",[46,1672,1673],{"class":48,"line":154},[46,1674,1675],{},"    \u002F\u002F深拷贝 (仅递归处理对象)\n",[46,1677,1678],{"class":48,"line":160},[46,1679,1680],{},"    for (; i \u003C aLength; i++) {\n",[46,1682,1683],{"class":48,"line":166},[46,1684,1685],{},"      if ((options = arguments[i]) != null) {\n",[46,1687,1688],{"class":48,"line":172},[46,1689,1690],{},"        if (typeof options !== 'object') {\n",[46,1692,1693],{"class":48,"line":178},[46,1694,1695],{},"          return options;\n",[46,1697,1698],{"class":48,"line":183},[46,1699,541],{},[46,1701,1702],{"class":48,"line":189},[46,1703,1704],{},"        for (var name in options) {\n",[46,1706,1707],{"class":48,"line":194},[46,1708,1709],{},"          copy = options[name];\n",[46,1711,1712],{"class":48,"line":200},[46,1713,1714],{},"          if (target === copy) {\n",[46,1716,1717],{"class":48,"line":398},[46,1718,1719],{},"            continue;\n",[46,1721,1722],{"class":48,"line":404},[46,1723,1724],{},"          }\n",[46,1726,1727],{"class":48,"line":410},[46,1728,1729],{},"          target[name] = this.extend(true, options[name]);\n",[46,1731,1732],{"class":48,"line":416},[46,1733,541],{},[46,1735,1736],{"class":48,"line":422},[46,1737,654],{},[46,1739,1740],{"class":48,"line":428},[46,1741,588],{},[46,1743,1744],{"class":48,"line":434},[46,1745,1361],{},[46,1747,1748],{"class":48,"line":440},[46,1749,1750],{},"    \u002F\u002F浅拷贝\n",[46,1752,1753],{"class":48,"line":446},[46,1754,1755],{},"    target = options;\n",[46,1757,1758],{"class":48,"line":1142},[46,1759,1760],{},"    if (aLength === i) {\n",[46,1762,1763],{"class":48,"line":1148},[46,1764,1765],{},"      target = this;\n",[46,1767,1768],{"class":48,"line":1154},[46,1769,1770],{},"      i--;\n",[46,1772,1773],{"class":48,"line":1160},[46,1774,1775],{},"    } \u002F\u002F如果是只有一个参数，拓展功能 如果两个以上参数，将后续对象加入到第一个对象\n",[46,1777,1778],{"class":48,"line":1166},[46,1779,1680],{},[46,1781,1782],{"class":48,"line":1171},[46,1783,1784],{},"      options = arguments[i];\n",[46,1786,1787],{"class":48,"line":1177},[46,1788,1789],{},"      for (var name in options) {\n",[46,1791,1792],{"class":48,"line":1182},[46,1793,1794],{},"        target[name] = options[name];\n",[46,1796,1797],{"class":48,"line":1188},[46,1798,654],{},[46,1800,1802],{"class":48,"line":1801},35,[46,1803,588],{},[46,1805,1807],{"class":48,"line":1806},36,[46,1808,1371],{},[46,1810,1812],{"class":48,"line":1811},37,[46,1813,1814],{},"  return target;\n",[46,1816,1818],{"class":48,"line":1817},38,[46,1819,593],{},[28,1821,1823],{"id":1822},"_4-axios封装","4. axios封装",[14,1825,1826],{},"由于刚开始学习Vue，对于网络请求还是更倾向于使用 success fail complete 来写\n封装了请求时加载Loading，请求失败弹窗，并且返回promise对象可以继续使用then等\n当发起post请求时使用{ 'content-type': 'application\u002Fx-www-form-urlencoded'}作为请求头，在transformRequest将json形请求转化为表单请求",[36,1828,1830],{"className":469,"code":1829,"language":471,"meta":41,"style":41},"function ajax(requestInfo) {\n  var options = {\n    load: true,\n    url: \"\",\n    method: \"GET\",\n    data: {},\n    param: {},\n    success: () => {},\n    fail: function() { this.completeLoad = () => {toast(\"服务器错误\", 'error');}\n    },\n    complete: () => {},\n    completeLoad: () => {}\n  };\n  extend(options, requestInfo);\n  let loadingInstance = startLoading(options);\n  return axios.request({\n    url: options.url,\n    data: options.data,\n    params: options.param,\n    method: options.method,\n    headers: $globalData.header,\n    transformRequest: [function(data) {\n      let ret = ''\n      for (let it in data) ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'\n      return ret\n    }]\n  }).then(function(res) {\n    try {\n      options.success(res);\n    } catch (e) {\n      options.completeLoad = () => {\n        toast(\"PARSE ERROR\");\n      }\n      console.warn(e);\n    }\n  }).catch(function(res) {\n    options.fail(res);\n  }).then(function(res) {\n    endLoading(options, loadingInstance);\n    try {\n      options.complete(res);\n    } catch (e) {\n      console.warn(e);\n    }\n    options.completeLoad(res);\n  })\n}\n\nexport default {\n  $ajax: ajax\n}\n",[43,1831,1832,1837,1842,1847,1852,1857,1862,1867,1872,1877,1881,1886,1891,1896,1901,1906,1911,1916,1921,1926,1931,1936,1941,1946,1951,1956,1961,1966,1971,1976,1981,1986,1991,1995,2000,2004,2009,2014,2018,2024,2029,2035,2040,2045,2050,2056,2061,2066,2071,2076,2082],{"__ignoreMap":41},[46,1833,1834],{"class":48,"line":49},[46,1835,1836],{},"function ajax(requestInfo) {\n",[46,1838,1839],{"class":48,"line":67},[46,1840,1841],{},"  var options = {\n",[46,1843,1844],{"class":48,"line":73},[46,1845,1846],{},"    load: true,\n",[46,1848,1849],{"class":48,"line":130},[46,1850,1851],{},"    url: \"\",\n",[46,1853,1854],{"class":48,"line":136},[46,1855,1856],{},"    method: \"GET\",\n",[46,1858,1859],{"class":48,"line":142},[46,1860,1861],{},"    data: {},\n",[46,1863,1864],{"class":48,"line":148},[46,1865,1866],{},"    param: {},\n",[46,1868,1869],{"class":48,"line":154},[46,1870,1871],{},"    success: () => {},\n",[46,1873,1874],{"class":48,"line":160},[46,1875,1876],{},"    fail: function() { this.completeLoad = () => {toast(\"服务器错误\", 'error');}\n",[46,1878,1879],{"class":48,"line":166},[46,1880,698],{},[46,1882,1883],{"class":48,"line":172},[46,1884,1885],{},"    complete: () => {},\n",[46,1887,1888],{"class":48,"line":178},[46,1889,1890],{},"    completeLoad: () => {}\n",[46,1892,1893],{"class":48,"line":183},[46,1894,1895],{},"  };\n",[46,1897,1898],{"class":48,"line":189},[46,1899,1900],{},"  extend(options, requestInfo);\n",[46,1902,1903],{"class":48,"line":194},[46,1904,1905],{},"  let loadingInstance = startLoading(options);\n",[46,1907,1908],{"class":48,"line":200},[46,1909,1910],{},"  return axios.request({\n",[46,1912,1913],{"class":48,"line":398},[46,1914,1915],{},"    url: options.url,\n",[46,1917,1918],{"class":48,"line":404},[46,1919,1920],{},"    data: options.data,\n",[46,1922,1923],{"class":48,"line":410},[46,1924,1925],{},"    params: options.param,\n",[46,1927,1928],{"class":48,"line":416},[46,1929,1930],{},"    method: options.method,\n",[46,1932,1933],{"class":48,"line":422},[46,1934,1935],{},"    headers: $globalData.header,\n",[46,1937,1938],{"class":48,"line":428},[46,1939,1940],{},"    transformRequest: [function(data) {\n",[46,1942,1943],{"class":48,"line":434},[46,1944,1945],{},"      let ret = ''\n",[46,1947,1948],{"class":48,"line":440},[46,1949,1950],{},"      for (let it in data) ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'\n",[46,1952,1953],{"class":48,"line":446},[46,1954,1955],{},"      return ret\n",[46,1957,1958],{"class":48,"line":1142},[46,1959,1960],{},"    }]\n",[46,1962,1963],{"class":48,"line":1148},[46,1964,1965],{},"  }).then(function(res) {\n",[46,1967,1968],{"class":48,"line":1154},[46,1969,1970],{},"    try {\n",[46,1972,1973],{"class":48,"line":1160},[46,1974,1975],{},"      options.success(res);\n",[46,1977,1978],{"class":48,"line":1166},[46,1979,1980],{},"    } catch (e) {\n",[46,1982,1983],{"class":48,"line":1171},[46,1984,1985],{},"      options.completeLoad = () => {\n",[46,1987,1988],{"class":48,"line":1177},[46,1989,1990],{},"        toast(\"PARSE ERROR\");\n",[46,1992,1993],{"class":48,"line":1182},[46,1994,654],{},[46,1996,1997],{"class":48,"line":1188},[46,1998,1999],{},"      console.warn(e);\n",[46,2001,2002],{"class":48,"line":1801},[46,2003,588],{},[46,2005,2006],{"class":48,"line":1806},[46,2007,2008],{},"  }).catch(function(res) {\n",[46,2010,2011],{"class":48,"line":1811},[46,2012,2013],{},"    options.fail(res);\n",[46,2015,2016],{"class":48,"line":1817},[46,2017,1965],{},[46,2019,2021],{"class":48,"line":2020},39,[46,2022,2023],{},"    endLoading(options, loadingInstance);\n",[46,2025,2027],{"class":48,"line":2026},40,[46,2028,1970],{},[46,2030,2032],{"class":48,"line":2031},41,[46,2033,2034],{},"      options.complete(res);\n",[46,2036,2038],{"class":48,"line":2037},42,[46,2039,1980],{},[46,2041,2043],{"class":48,"line":2042},43,[46,2044,1999],{},[46,2046,2048],{"class":48,"line":2047},44,[46,2049,588],{},[46,2051,2053],{"class":48,"line":2052},45,[46,2054,2055],{},"    options.completeLoad(res);\n",[46,2057,2059],{"class":48,"line":2058},46,[46,2060,1522],{},[46,2062,2064],{"class":48,"line":2063},47,[46,2065,593],{},[46,2067,2069],{"class":48,"line":2068},48,[46,2070,122],{"emptyLinePlaceholder":121},[46,2072,2074],{"class":48,"line":2073},49,[46,2075,1429],{},[46,2077,2079],{"class":48,"line":2078},50,[46,2080,2081],{},"  $ajax: ajax\n",[46,2083,2085],{"class":48,"line":2084},51,[46,2086,593],{},[14,2088,915],{},[36,2090,2092],{"className":469,"code":2091,"language":471,"meta":41,"style":41},"import dispose from '@\u002Fvector\u002Fdispose'\nVue.prototype.$ajax = dispose.$ajax;\n",[43,2093,2094,2098],{"__ignoreMap":41},[46,2095,2096],{"class":48,"line":49},[46,2097,1451],{},[46,2099,2100],{"class":48,"line":67},[46,2101,2102],{},"Vue.prototype.$ajax = dispose.$ajax;\n",[14,2104,2105],{},"由于测试必须处理跨域请求，并且需要使用cookies时，首先在声明 axios.defaults.withCredentials = true ，此时在后端就不能将Access-Control-Allow-Origin设置为*了\naxios",[36,2107,2109],{"className":469,"code":2108,"language":471,"meta":41,"style":41},"axios.defaults.withCredentials = true\n",[43,2110,2111],{"__ignoreMap":41},[46,2112,2113],{"class":48,"line":49},[46,2114,2108],{},[14,2116,2117],{},"PHP",[36,2119,2123],{"className":2120,"code":2121,"language":2122,"meta":41,"style":41},"language-php shiki shiki-themes github-light github-dark","header('Content-Type: text\u002Fhtml;charset=utf-8');\nheader('Access-Control-Allow-Origin:http:\u002F\u002Flocalhost:8080'); \u002F\u002F 允许网址请求\nheader('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); \u002F\u002F 允许请求的类型\nheader('Access-Control-Allow-Credentials: true'); \u002F\u002F 设置是否允许发送 cookies\nheader('Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin'); \u002F\u002F 设置允许自定义请求头的字段 \n","php",[43,2124,2125,2130,2135,2140,2145],{"__ignoreMap":41},[46,2126,2127],{"class":48,"line":49},[46,2128,2129],{},"header('Content-Type: text\u002Fhtml;charset=utf-8');\n",[46,2131,2132],{"class":48,"line":67},[46,2133,2134],{},"header('Access-Control-Allow-Origin:http:\u002F\u002Flocalhost:8080'); \u002F\u002F 允许网址请求\n",[46,2136,2137],{"class":48,"line":73},[46,2138,2139],{},"header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); \u002F\u002F 允许请求的类型\n",[46,2141,2142],{"class":48,"line":130},[46,2143,2144],{},"header('Access-Control-Allow-Credentials: true'); \u002F\u002F 设置是否允许发送 cookies\n",[46,2146,2147],{"class":48,"line":136},[46,2148,2149],{},"header('Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin'); \u002F\u002F 设置允许自定义请求头的字段\n",[23,2151,2153],{"id":2152},"六webpack","六、Webpack",[28,2155,2157],{"id":2156},"_1-buildbuildjs","1. build\u002Fbuild.js",[36,2159,2161],{"className":469,"code":2160,"language":471,"meta":41,"style":41},"\u002F\u002F 构建生产版本 node build\u002Fbuild.js\nrequire('.\u002Fcheck-versions')()   \u002F\u002Fcheck-versions 调用检查版本的文件 并直接调用该函数\nprocess.env.NODE_ENV = 'production'   \u002F\u002F 注册到window的全局变量，可以用以区分生产环境和开发环境，此为生产环境\nconst ora = require('ora')   \u002F\u002F 终端显示的转轮loading\nconst rm = require('rimraf')   \u002F\u002F node环境下rm -rf的命令库\nconst path = require('path')   \u002F\u002F 文件路径处理库\nconst chalk = require('chalk')   \u002F\u002F 终端显示带颜色的文字\nconst webpack = require('webpack')   \u002F\u002F webpack\nconst config = require('..\u002Fconfig')   \u002F\u002F 引入配置\nconst webpackConfig = require('.\u002Fwebpack.prod.conf')   \u002F\u002F 引入生产环境下配置\n\nconst spinner = ora('building for production...')   \u002F\u002F 终端显示正在构建\nspinner.start()   \u002F\u002F 终端显示loading\n\nrm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {   \u002F\u002F 删除已编译文件，即dist文件夹\n  if (err) throw err\n  webpack(webpackConfig, (err, stats) => {   \u002F\u002F在删除完成的回调函数中开始编译\n    spinner.stop()   \u002F\u002F 终端终止loading\n    if (err) throw err\n    process.stdout.write(stats.toString({   \u002F\u002F 在编译完成的回调函数中,在终端输出编译的文件\n      colors: true,\n      modules: false,\n      children: false, \u002F\u002F If you are using ts-loader, setting this to true will make TypeScript errors show up during build.\n      chunks: false,\n      chunkModules: false\n    }) + '\\n\\n')\n    \u002F* ... *\u002F \u002F\u002F 以下为编译结果的输出\n  })\n})\n",[43,2162,2163,2168,2173,2178,2183,2188,2193,2198,2203,2208,2213,2217,2222,2227,2231,2236,2241,2246,2251,2256,2261,2266,2271,2276,2281,2286,2291,2296,2300],{"__ignoreMap":41},[46,2164,2165],{"class":48,"line":49},[46,2166,2167],{},"\u002F\u002F 构建生产版本 node build\u002Fbuild.js\n",[46,2169,2170],{"class":48,"line":67},[46,2171,2172],{},"require('.\u002Fcheck-versions')()   \u002F\u002Fcheck-versions 调用检查版本的文件 并直接调用该函数\n",[46,2174,2175],{"class":48,"line":73},[46,2176,2177],{},"process.env.NODE_ENV = 'production'   \u002F\u002F 注册到window的全局变量，可以用以区分生产环境和开发环境，此为生产环境\n",[46,2179,2180],{"class":48,"line":130},[46,2181,2182],{},"const ora = require('ora')   \u002F\u002F 终端显示的转轮loading\n",[46,2184,2185],{"class":48,"line":136},[46,2186,2187],{},"const rm = require('rimraf')   \u002F\u002F node环境下rm -rf的命令库\n",[46,2189,2190],{"class":48,"line":142},[46,2191,2192],{},"const path = require('path')   \u002F\u002F 文件路径处理库\n",[46,2194,2195],{"class":48,"line":148},[46,2196,2197],{},"const chalk = require('chalk')   \u002F\u002F 终端显示带颜色的文字\n",[46,2199,2200],{"class":48,"line":154},[46,2201,2202],{},"const webpack = require('webpack')   \u002F\u002F webpack\n",[46,2204,2205],{"class":48,"line":160},[46,2206,2207],{},"const config = require('..\u002Fconfig')   \u002F\u002F 引入配置\n",[46,2209,2210],{"class":48,"line":166},[46,2211,2212],{},"const webpackConfig = require('.\u002Fwebpack.prod.conf')   \u002F\u002F 引入生产环境下配置\n",[46,2214,2215],{"class":48,"line":172},[46,2216,122],{"emptyLinePlaceholder":121},[46,2218,2219],{"class":48,"line":178},[46,2220,2221],{},"const spinner = ora('building for production...')   \u002F\u002F 终端显示正在构建\n",[46,2223,2224],{"class":48,"line":183},[46,2225,2226],{},"spinner.start()   \u002F\u002F 终端显示loading\n",[46,2228,2229],{"class":48,"line":189},[46,2230,122],{"emptyLinePlaceholder":121},[46,2232,2233],{"class":48,"line":194},[46,2234,2235],{},"rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {   \u002F\u002F 删除已编译文件，即dist文件夹\n",[46,2237,2238],{"class":48,"line":200},[46,2239,2240],{},"  if (err) throw err\n",[46,2242,2243],{"class":48,"line":398},[46,2244,2245],{},"  webpack(webpackConfig, (err, stats) => {   \u002F\u002F在删除完成的回调函数中开始编译\n",[46,2247,2248],{"class":48,"line":404},[46,2249,2250],{},"    spinner.stop()   \u002F\u002F 终端终止loading\n",[46,2252,2253],{"class":48,"line":410},[46,2254,2255],{},"    if (err) throw err\n",[46,2257,2258],{"class":48,"line":416},[46,2259,2260],{},"    process.stdout.write(stats.toString({   \u002F\u002F 在编译完成的回调函数中,在终端输出编译的文件\n",[46,2262,2263],{"class":48,"line":422},[46,2264,2265],{},"      colors: true,\n",[46,2267,2268],{"class":48,"line":428},[46,2269,2270],{},"      modules: false,\n",[46,2272,2273],{"class":48,"line":434},[46,2274,2275],{},"      children: false, \u002F\u002F If you are using ts-loader, setting this to true will make TypeScript errors show up during build.\n",[46,2277,2278],{"class":48,"line":440},[46,2279,2280],{},"      chunks: false,\n",[46,2282,2283],{"class":48,"line":446},[46,2284,2285],{},"      chunkModules: false\n",[46,2287,2288],{"class":48,"line":1142},[46,2289,2290],{},"    }) + '\\n\\n')\n",[46,2292,2293],{"class":48,"line":1148},[46,2294,2295],{},"    \u002F* ... *\u002F \u002F\u002F 以下为编译结果的输出\n",[46,2297,2298],{"class":48,"line":1154},[46,2299,1522],{},[46,2301,2302],{"class":48,"line":1160},[46,2303,1191],{},[28,2305,2307],{"id":2306},"_2-buildcheck-versionjs","2. build\u002Fcheck-version.js",[36,2309,2311],{"className":469,"code":2310,"language":471,"meta":41,"style":41},"const chalk = require('chalk')   \u002F\u002F 终端显示带颜色的文字\nconst semver = require('semver') \u002F\u002F 对版本进行检查\nconst packageConfig = require('..\u002Fpackage.json') \u002F\u002F 读取项目配置文件\nconst shell = require('shelljs') \u002F\u002F shell\n\nfunction exec (cmd) {   \u002F\u002F返回通过child_process模块的新建子进程，执行 Unix 系统命令后转成没有空格的字符串\n  return require('child_process').execSync(cmd).toString().trim()\n}\n\nconst versionRequirements = [\n  {\n    name: 'node',\n    currentVersion: semver.clean(process.version),   \u002F\u002F 使用semver格式化版本\n    versionRequirement: packageConfig.engines.node   \u002F\u002F 获取package.json中设置的node版本\n  }\n]\n\nif (shell.which('npm')) {\n  versionRequirements.push({\n    name: 'npm',\n    currentVersion: exec('npm --version'),   \u002F\u002F 调用npm --version命令，并且把参数返回给exec函数，从而获取纯净的版本号\n    versionRequirement: packageConfig.engines.npm\n  })\n}\n\nmodule.exports = function () {\n  \u002F* ... *\u002F   \u002F\u002F警告或者错误提示\n}\n",[43,2312,2313,2317,2322,2327,2332,2336,2341,2346,2350,2354,2359,2364,2369,2374,2379,2383,2388,2392,2397,2402,2407,2412,2417,2421,2425,2429,2434,2439],{"__ignoreMap":41},[46,2314,2315],{"class":48,"line":49},[46,2316,2197],{},[46,2318,2319],{"class":48,"line":67},[46,2320,2321],{},"const semver = require('semver') \u002F\u002F 对版本进行检查\n",[46,2323,2324],{"class":48,"line":73},[46,2325,2326],{},"const packageConfig = require('..\u002Fpackage.json') \u002F\u002F 读取项目配置文件\n",[46,2328,2329],{"class":48,"line":130},[46,2330,2331],{},"const shell = require('shelljs') \u002F\u002F shell\n",[46,2333,2334],{"class":48,"line":136},[46,2335,122],{"emptyLinePlaceholder":121},[46,2337,2338],{"class":48,"line":142},[46,2339,2340],{},"function exec (cmd) {   \u002F\u002F返回通过child_process模块的新建子进程，执行 Unix 系统命令后转成没有空格的字符串\n",[46,2342,2343],{"class":48,"line":148},[46,2344,2345],{},"  return require('child_process').execSync(cmd).toString().trim()\n",[46,2347,2348],{"class":48,"line":154},[46,2349,593],{},[46,2351,2352],{"class":48,"line":160},[46,2353,122],{"emptyLinePlaceholder":121},[46,2355,2356],{"class":48,"line":166},[46,2357,2358],{},"const versionRequirements = [\n",[46,2360,2361],{"class":48,"line":172},[46,2362,2363],{},"  {\n",[46,2365,2366],{"class":48,"line":178},[46,2367,2368],{},"    name: 'node',\n",[46,2370,2371],{"class":48,"line":183},[46,2372,2373],{},"    currentVersion: semver.clean(process.version),   \u002F\u002F 使用semver格式化版本\n",[46,2375,2376],{"class":48,"line":189},[46,2377,2378],{},"    versionRequirement: packageConfig.engines.node   \u002F\u002F 获取package.json中设置的node版本\n",[46,2380,2381],{"class":48,"line":194},[46,2382,1371],{},[46,2384,2385],{"class":48,"line":200},[46,2386,2387],{},"]\n",[46,2389,2390],{"class":48,"line":398},[46,2391,122],{"emptyLinePlaceholder":121},[46,2393,2394],{"class":48,"line":404},[46,2395,2396],{},"if (shell.which('npm')) {\n",[46,2398,2399],{"class":48,"line":410},[46,2400,2401],{},"  versionRequirements.push({\n",[46,2403,2404],{"class":48,"line":416},[46,2405,2406],{},"    name: 'npm',\n",[46,2408,2409],{"class":48,"line":422},[46,2410,2411],{},"    currentVersion: exec('npm --version'),   \u002F\u002F 调用npm --version命令，并且把参数返回给exec函数，从而获取纯净的版本号\n",[46,2413,2414],{"class":48,"line":428},[46,2415,2416],{},"    versionRequirement: packageConfig.engines.npm\n",[46,2418,2419],{"class":48,"line":434},[46,2420,1522],{},[46,2422,2423],{"class":48,"line":440},[46,2424,593],{},[46,2426,2427],{"class":48,"line":446},[46,2428,122],{"emptyLinePlaceholder":121},[46,2430,2431],{"class":48,"line":1142},[46,2432,2433],{},"module.exports = function () {\n",[46,2435,2436],{"class":48,"line":1148},[46,2437,2438],{},"  \u002F* ... *\u002F   \u002F\u002F警告或者错误提示\n",[46,2440,2441],{"class":48,"line":1154},[46,2442,593],{},[28,2444,2446],{"id":2445},"_3-buildutilsjs","3. build\u002Futils.js",[36,2448,2450],{"className":469,"code":2449,"language":471,"meta":41,"style":41},"\u002F\u002F 处理css\nconst path = require('path')\nconst config = require('..\u002Fconfig')\nconst ExtractTextPlugin = require('extract-text-webpack-plugin')\nconst packageConfig = require('..\u002Fpackage.json')\n\nexports.assetsPath = function (_path) {   \u002F\u002F导出文件的位置，根据环境判断开发环境和生产环境，为config文件中index.js文件中定义的build.assetsSubDirectory或dev.assetsSubDirectory\n  const assetsSubDirectory = process.env.NODE_ENV === 'production'\n    ? config.build.assetsSubDirectory\n    : config.dev.assetsSubDirectory\n  return path.posix.join(assetsSubDirectory, _path) \u002F\u002Fpath 模块提供了一些用于处理文件路径的工具\n}\n\nexports.cssLoaders = function (options) {\n  options = options || {}\n  const cssLoader = { \u002F\u002F使用了css-loader和postcssLoader，通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法\n    loader: 'css-loader',\n    options: {\n      sourceMap: options.sourceMap\n    }\n  }\n\n  const postcssLoader = {\n    loader: 'postcss-loader',\n    options: {\n      sourceMap: options.sourceMap\n    }\n  }\n  function generateLoaders (loader, loaderOptions) {\n    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]\n    if (loader) {\n      loaders.push({\n        loader: loader + '-loader',\n        options: Object.assign({}, loaderOptions, {   \u002F\u002FObject.assign是es6语法的浅拷贝，后两者合并后复制完成赋值\n          sourceMap: options.sourceMap\n        })\n      })\n    }\n    \n    if (options.extract) {\n      return ExtractTextPlugin.extract({   \u002F\u002FExtractTextPlugin可提取出文本，代表首先使用上面处理的loaders，当未能正确引入时使用vue-style-loader\n        use: loaders,\n        fallback: 'vue-style-loader'\n      })\n    } else {\n      return ['vue-style-loader'].concat(loaders)   \u002F\u002F返回vue-style-loader连接loaders的最终值\n    }\n  }\n  return {\n    css: generateLoaders(),\u002F\u002F需要css-loader 和 vue-style-loader\n    postcss: generateLoaders(),\u002F\u002F需要css-loader和postcssLoader  和 vue-style-loader\n    less: generateLoaders('less'),\u002F\u002F需要less-loader 和 vue-style-loader\n    sass: generateLoaders('sass', { indentedSyntax: true }),\u002F\u002F需要sass-loader 和 vue-style-loader\n    scss: generateLoaders('sass'),\u002F\u002F需要sass-loader 和 vue-style-loader\n    stylus: generateLoaders('stylus'),\u002F\u002F需要stylus-loader 和 vue-style-loader\n    styl: generateLoaders('stylus')\u002F\u002F需要stylus-loader 和 vue-style-loader\n  }\n}\nexports.styleLoaders = function (options) {\n  const output = []\n  const loaders = exports.cssLoaders(options)\n  for (const extension in loaders) {  \u002F\u002F将各种css,less,sass等综合在一起得出结果输出output\n    const loader = loaders[extension]\n    output.push({\n      test: new RegExp('\\\\.' + extension + '$'),\n      use: loader\n    })\n  }\n\n  return output\n}\n\nexports.createNotifierCallback = () => {\n  const notifier = require('node-notifier') \u002F\u002F发送跨平台通知系统\n  return (severity, errors) => {\n    if (severity !== 'error') return\n    const error = errors[0] \n    const filename = error.file && error.file.split('!').pop()\n    notifier.notify({   \u002F\u002F当报错时输出错误信息的标题，错误信息详情，副标题以及图标\n      title: packageConfig.name,\n      message: severity + ': ' + error.name,\n      subtitle: filename || '',\n      icon: path.join(__dirname, 'logo.png')   \u002F\u002F 用于连接路径，会正确使用当前系统的路径分隔符，Unix系统是\"\u002F\"，Windows系统是\"\"\n    })\n  }\n}\n",[43,2451,2452,2457,2462,2467,2472,2477,2481,2486,2491,2496,2501,2506,2510,2514,2519,2524,2529,2534,2539,2544,2548,2552,2556,2561,2566,2570,2574,2578,2582,2587,2592,2597,2602,2607,2612,2617,2622,2627,2631,2636,2641,2646,2651,2656,2660,2665,2670,2674,2678,2683,2688,2693,2699,2705,2711,2717,2723,2728,2733,2739,2745,2751,2757,2763,2769,2775,2781,2786,2791,2796,2802,2807,2812,2818,2824,2830,2836,2842,2848,2854,2860,2866,2872,2878,2883,2888],{"__ignoreMap":41},[46,2453,2454],{"class":48,"line":49},[46,2455,2456],{},"\u002F\u002F 处理css\n",[46,2458,2459],{"class":48,"line":67},[46,2460,2461],{},"const path = require('path')\n",[46,2463,2464],{"class":48,"line":73},[46,2465,2466],{},"const config = require('..\u002Fconfig')\n",[46,2468,2469],{"class":48,"line":130},[46,2470,2471],{},"const ExtractTextPlugin = require('extract-text-webpack-plugin')\n",[46,2473,2474],{"class":48,"line":136},[46,2475,2476],{},"const packageConfig = require('..\u002Fpackage.json')\n",[46,2478,2479],{"class":48,"line":142},[46,2480,122],{"emptyLinePlaceholder":121},[46,2482,2483],{"class":48,"line":148},[46,2484,2485],{},"exports.assetsPath = function (_path) {   \u002F\u002F导出文件的位置，根据环境判断开发环境和生产环境，为config文件中index.js文件中定义的build.assetsSubDirectory或dev.assetsSubDirectory\n",[46,2487,2488],{"class":48,"line":154},[46,2489,2490],{},"  const assetsSubDirectory = process.env.NODE_ENV === 'production'\n",[46,2492,2493],{"class":48,"line":160},[46,2494,2495],{},"    ? config.build.assetsSubDirectory\n",[46,2497,2498],{"class":48,"line":166},[46,2499,2500],{},"    : config.dev.assetsSubDirectory\n",[46,2502,2503],{"class":48,"line":172},[46,2504,2505],{},"  return path.posix.join(assetsSubDirectory, _path) \u002F\u002Fpath 模块提供了一些用于处理文件路径的工具\n",[46,2507,2508],{"class":48,"line":178},[46,2509,593],{},[46,2511,2512],{"class":48,"line":183},[46,2513,122],{"emptyLinePlaceholder":121},[46,2515,2516],{"class":48,"line":189},[46,2517,2518],{},"exports.cssLoaders = function (options) {\n",[46,2520,2521],{"class":48,"line":194},[46,2522,2523],{},"  options = options || {}\n",[46,2525,2526],{"class":48,"line":200},[46,2527,2528],{},"  const cssLoader = { \u002F\u002F使用了css-loader和postcssLoader，通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法\n",[46,2530,2531],{"class":48,"line":398},[46,2532,2533],{},"    loader: 'css-loader',\n",[46,2535,2536],{"class":48,"line":404},[46,2537,2538],{},"    options: {\n",[46,2540,2541],{"class":48,"line":410},[46,2542,2543],{},"      sourceMap: options.sourceMap\n",[46,2545,2546],{"class":48,"line":416},[46,2547,588],{},[46,2549,2550],{"class":48,"line":422},[46,2551,1371],{},[46,2553,2554],{"class":48,"line":428},[46,2555,122],{"emptyLinePlaceholder":121},[46,2557,2558],{"class":48,"line":434},[46,2559,2560],{},"  const postcssLoader = {\n",[46,2562,2563],{"class":48,"line":440},[46,2564,2565],{},"    loader: 'postcss-loader',\n",[46,2567,2568],{"class":48,"line":446},[46,2569,2538],{},[46,2571,2572],{"class":48,"line":1142},[46,2573,2543],{},[46,2575,2576],{"class":48,"line":1148},[46,2577,588],{},[46,2579,2580],{"class":48,"line":1154},[46,2581,1371],{},[46,2583,2584],{"class":48,"line":1160},[46,2585,2586],{},"  function generateLoaders (loader, loaderOptions) {\n",[46,2588,2589],{"class":48,"line":1166},[46,2590,2591],{},"    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]\n",[46,2593,2594],{"class":48,"line":1171},[46,2595,2596],{},"    if (loader) {\n",[46,2598,2599],{"class":48,"line":1177},[46,2600,2601],{},"      loaders.push({\n",[46,2603,2604],{"class":48,"line":1182},[46,2605,2606],{},"        loader: loader + '-loader',\n",[46,2608,2609],{"class":48,"line":1188},[46,2610,2611],{},"        options: Object.assign({}, loaderOptions, {   \u002F\u002FObject.assign是es6语法的浅拷贝，后两者合并后复制完成赋值\n",[46,2613,2614],{"class":48,"line":1801},[46,2615,2616],{},"          sourceMap: options.sourceMap\n",[46,2618,2619],{"class":48,"line":1806},[46,2620,2621],{},"        })\n",[46,2623,2624],{"class":48,"line":1811},[46,2625,2626],{},"      })\n",[46,2628,2629],{"class":48,"line":1817},[46,2630,588],{},[46,2632,2633],{"class":48,"line":2020},[46,2634,2635],{},"    \n",[46,2637,2638],{"class":48,"line":2026},[46,2639,2640],{},"    if (options.extract) {\n",[46,2642,2643],{"class":48,"line":2031},[46,2644,2645],{},"      return ExtractTextPlugin.extract({   \u002F\u002FExtractTextPlugin可提取出文本，代表首先使用上面处理的loaders，当未能正确引入时使用vue-style-loader\n",[46,2647,2648],{"class":48,"line":2037},[46,2649,2650],{},"        use: loaders,\n",[46,2652,2653],{"class":48,"line":2042},[46,2654,2655],{},"        fallback: 'vue-style-loader'\n",[46,2657,2658],{"class":48,"line":2047},[46,2659,2626],{},[46,2661,2662],{"class":48,"line":2052},[46,2663,2664],{},"    } else {\n",[46,2666,2667],{"class":48,"line":2058},[46,2668,2669],{},"      return ['vue-style-loader'].concat(loaders)   \u002F\u002F返回vue-style-loader连接loaders的最终值\n",[46,2671,2672],{"class":48,"line":2063},[46,2673,588],{},[46,2675,2676],{"class":48,"line":2068},[46,2677,1371],{},[46,2679,2680],{"class":48,"line":2073},[46,2681,2682],{},"  return {\n",[46,2684,2685],{"class":48,"line":2078},[46,2686,2687],{},"    css: generateLoaders(),\u002F\u002F需要css-loader 和 vue-style-loader\n",[46,2689,2690],{"class":48,"line":2084},[46,2691,2692],{},"    postcss: generateLoaders(),\u002F\u002F需要css-loader和postcssLoader  和 vue-style-loader\n",[46,2694,2696],{"class":48,"line":2695},52,[46,2697,2698],{},"    less: generateLoaders('less'),\u002F\u002F需要less-loader 和 vue-style-loader\n",[46,2700,2702],{"class":48,"line":2701},53,[46,2703,2704],{},"    sass: generateLoaders('sass', { indentedSyntax: true }),\u002F\u002F需要sass-loader 和 vue-style-loader\n",[46,2706,2708],{"class":48,"line":2707},54,[46,2709,2710],{},"    scss: generateLoaders('sass'),\u002F\u002F需要sass-loader 和 vue-style-loader\n",[46,2712,2714],{"class":48,"line":2713},55,[46,2715,2716],{},"    stylus: generateLoaders('stylus'),\u002F\u002F需要stylus-loader 和 vue-style-loader\n",[46,2718,2720],{"class":48,"line":2719},56,[46,2721,2722],{},"    styl: generateLoaders('stylus')\u002F\u002F需要stylus-loader 和 vue-style-loader\n",[46,2724,2726],{"class":48,"line":2725},57,[46,2727,1371],{},[46,2729,2731],{"class":48,"line":2730},58,[46,2732,593],{},[46,2734,2736],{"class":48,"line":2735},59,[46,2737,2738],{},"exports.styleLoaders = function (options) {\n",[46,2740,2742],{"class":48,"line":2741},60,[46,2743,2744],{},"  const output = []\n",[46,2746,2748],{"class":48,"line":2747},61,[46,2749,2750],{},"  const loaders = exports.cssLoaders(options)\n",[46,2752,2754],{"class":48,"line":2753},62,[46,2755,2756],{},"  for (const extension in loaders) {  \u002F\u002F将各种css,less,sass等综合在一起得出结果输出output\n",[46,2758,2760],{"class":48,"line":2759},63,[46,2761,2762],{},"    const loader = loaders[extension]\n",[46,2764,2766],{"class":48,"line":2765},64,[46,2767,2768],{},"    output.push({\n",[46,2770,2772],{"class":48,"line":2771},65,[46,2773,2774],{},"      test: new RegExp('\\\\.' + extension + '$'),\n",[46,2776,2778],{"class":48,"line":2777},66,[46,2779,2780],{},"      use: loader\n",[46,2782,2784],{"class":48,"line":2783},67,[46,2785,1356],{},[46,2787,2789],{"class":48,"line":2788},68,[46,2790,1371],{},[46,2792,2794],{"class":48,"line":2793},69,[46,2795,122],{"emptyLinePlaceholder":121},[46,2797,2799],{"class":48,"line":2798},70,[46,2800,2801],{},"  return output\n",[46,2803,2805],{"class":48,"line":2804},71,[46,2806,593],{},[46,2808,2810],{"class":48,"line":2809},72,[46,2811,122],{"emptyLinePlaceholder":121},[46,2813,2815],{"class":48,"line":2814},73,[46,2816,2817],{},"exports.createNotifierCallback = () => {\n",[46,2819,2821],{"class":48,"line":2820},74,[46,2822,2823],{},"  const notifier = require('node-notifier') \u002F\u002F发送跨平台通知系统\n",[46,2825,2827],{"class":48,"line":2826},75,[46,2828,2829],{},"  return (severity, errors) => {\n",[46,2831,2833],{"class":48,"line":2832},76,[46,2834,2835],{},"    if (severity !== 'error') return\n",[46,2837,2839],{"class":48,"line":2838},77,[46,2840,2841],{},"    const error = errors[0] \n",[46,2843,2845],{"class":48,"line":2844},78,[46,2846,2847],{},"    const filename = error.file && error.file.split('!').pop()\n",[46,2849,2851],{"class":48,"line":2850},79,[46,2852,2853],{},"    notifier.notify({   \u002F\u002F当报错时输出错误信息的标题，错误信息详情，副标题以及图标\n",[46,2855,2857],{"class":48,"line":2856},80,[46,2858,2859],{},"      title: packageConfig.name,\n",[46,2861,2863],{"class":48,"line":2862},81,[46,2864,2865],{},"      message: severity + ': ' + error.name,\n",[46,2867,2869],{"class":48,"line":2868},82,[46,2870,2871],{},"      subtitle: filename || '',\n",[46,2873,2875],{"class":48,"line":2874},83,[46,2876,2877],{},"      icon: path.join(__dirname, 'logo.png')   \u002F\u002F 用于连接路径，会正确使用当前系统的路径分隔符，Unix系统是\"\u002F\"，Windows系统是\"\"\n",[46,2879,2881],{"class":48,"line":2880},84,[46,2882,1356],{},[46,2884,2886],{"class":48,"line":2885},85,[46,2887,1371],{},[46,2889,2891],{"class":48,"line":2890},86,[46,2892,593],{},[28,2894,2896],{"id":2895},"_4-buildvue-loaderconfjs","4. build\u002Fvue-loader.conf.js",[36,2898,2900],{"className":469,"code":2899,"language":471,"meta":41,"style":41},"\u002F\u002F 处理.vue文件，解析这个文件中的每个语言块（template、script、style),转换成js可用的js模块\nconst utils = require('.\u002Futils')\nconst config = require('..\u002Fconfig')\nconst isProduction = process.env.NODE_ENV === 'production'\nconst sourceMapEnabled = isProduction\n  ? config.build.productionSourceMap\n  : config.dev.cssSourceMap\n  \nmodule.exports = {   \u002F\u002F 处理项目中的css文件，生产环境和测试环境默认是打开sourceMap，而extract中的提取样式到单独文件只有在生产环境中才需要\n  loaders: utils.cssLoaders({\n    sourceMap: sourceMapEnabled,\n    extract: isProduction\n  }),\n  cssSourceMap: sourceMapEnabled,\n  cacheBusting: config.dev.cacheBusting,\n  transformToRequire: {   \u002F\u002F 在模版编译过程中，编译器可以将某些属性，如 src 路径，转换为require调用，以便目标资源可以由 webpack 处理\n    video: ['src', 'poster'],\n    source: 'src',\n    img: 'src',\n    image: 'xlink:href'\n  }\n}\n",[43,2901,2902,2907,2912,2916,2921,2926,2931,2936,2941,2946,2951,2956,2961,2966,2971,2976,2981,2986,2991,2996,3001,3005],{"__ignoreMap":41},[46,2903,2904],{"class":48,"line":49},[46,2905,2906],{},"\u002F\u002F 处理.vue文件，解析这个文件中的每个语言块（template、script、style),转换成js可用的js模块\n",[46,2908,2909],{"class":48,"line":67},[46,2910,2911],{},"const utils = require('.\u002Futils')\n",[46,2913,2914],{"class":48,"line":73},[46,2915,2466],{},[46,2917,2918],{"class":48,"line":130},[46,2919,2920],{},"const isProduction = process.env.NODE_ENV === 'production'\n",[46,2922,2923],{"class":48,"line":136},[46,2924,2925],{},"const sourceMapEnabled = isProduction\n",[46,2927,2928],{"class":48,"line":142},[46,2929,2930],{},"  ? config.build.productionSourceMap\n",[46,2932,2933],{"class":48,"line":148},[46,2934,2935],{},"  : config.dev.cssSourceMap\n",[46,2937,2938],{"class":48,"line":154},[46,2939,2940],{},"  \n",[46,2942,2943],{"class":48,"line":160},[46,2944,2945],{},"module.exports = {   \u002F\u002F 处理项目中的css文件，生产环境和测试环境默认是打开sourceMap，而extract中的提取样式到单独文件只有在生产环境中才需要\n",[46,2947,2948],{"class":48,"line":166},[46,2949,2950],{},"  loaders: utils.cssLoaders({\n",[46,2952,2953],{"class":48,"line":172},[46,2954,2955],{},"    sourceMap: sourceMapEnabled,\n",[46,2957,2958],{"class":48,"line":178},[46,2959,2960],{},"    extract: isProduction\n",[46,2962,2963],{"class":48,"line":183},[46,2964,2965],{},"  }),\n",[46,2967,2968],{"class":48,"line":189},[46,2969,2970],{},"  cssSourceMap: sourceMapEnabled,\n",[46,2972,2973],{"class":48,"line":194},[46,2974,2975],{},"  cacheBusting: config.dev.cacheBusting,\n",[46,2977,2978],{"class":48,"line":200},[46,2979,2980],{},"  transformToRequire: {   \u002F\u002F 在模版编译过程中，编译器可以将某些属性，如 src 路径，转换为require调用，以便目标资源可以由 webpack 处理\n",[46,2982,2983],{"class":48,"line":398},[46,2984,2985],{},"    video: ['src', 'poster'],\n",[46,2987,2988],{"class":48,"line":404},[46,2989,2990],{},"    source: 'src',\n",[46,2992,2993],{"class":48,"line":410},[46,2994,2995],{},"    img: 'src',\n",[46,2997,2998],{"class":48,"line":416},[46,2999,3000],{},"    image: 'xlink:href'\n",[46,3002,3003],{"class":48,"line":422},[46,3004,1371],{},[46,3006,3007],{"class":48,"line":428},[46,3008,593],{},[28,3010,3012],{"id":3011},"_5-buildwebpackbaseconfjs","5. build\u002Fwebpack.base.conf.js",[36,3014,3016],{"className":469,"code":3015,"language":471,"meta":41,"style":41},"\u002F\u002F 开发和生产共同使用提出来的基础配置文件，主要实现配制入口，配置输出环境，配置模块resolve和插件等\n'use strict'\nconst path = require('path')\nconst utils = require('.\u002Futils')\nconst config = require('..\u002Fconfig')\nconst vueLoaderConfig = require('.\u002Fvue-loader.conf')\n\nfunction resolve (dir) {   \u002F\u002F 拼接出绝对路径\n  return path.join(__dirname, '..', dir)\n}\n\nmodule.exports = {\n  context: path.resolve(__dirname, '..\u002F'),\n  entry: {   \u002F\u002F 入口文件,可以有多个入口,也可只有一个,默认为单页面所以只有app一个入口\n    app: '.\u002Fsrc\u002Fmain.js'\n  },\n  output: {    \u002F\u002F配置出口，默认是\u002Fdist作为目标文件夹的路径\n    path: config.build.assetsRoot,   \u002F\u002F 路径\n    filename: '[name].js',   \u002F\u002F 输出文件名\n    publicPath: process.env.NODE_ENV === 'production'\n      ? config.build.assetsPublicPath\n      : config.dev.assetsPublicPath\n  },\n  resolve: {\n    extensions: ['.js', '.vue', '.json'],  \u002F\u002F 自动的扩展后缀，比如一个js文件，则引用时书写可不要写.js\n    alias: {\n      'vue$': 'vue\u002Fdist\u002Fvue.esm.js',\n      '@': resolve('src'),   \u002F\u002F @ 即为 \u002Fsrc\n    }\n  },\n  module: {   \u002F\u002F 使用插件配置相应文件的处理方法\n    rules: [{   \n        test: \u002F\\.vue$\u002F,\n        loader: 'vue-loader',   \u002F\u002F 使用vue-loader将vue文件转化成js的模块\n        options: vueLoaderConfig\n      },{\n        test: \u002F\\.js$\u002F,\n        loader: 'babel-loader',   \u002F\u002F js文件需要通过babel-loader进行编译成es5文件以及压缩等操作\n        include: [resolve('src'), resolve('test'), resolve('node_modules\u002Fwebpack-dev-server\u002Fclient')]\n      },{\n        test: \u002F\\.(png|jpe?g|gif|svg)(\\?.*)?$\u002F,\n        loader: 'url-loader',   \u002F\u002F 图片、音像、字体都使用url-loader进行处理，超过10000会编译成base64\n        options: {\n          limit: 10000,\n          name: utils.assetsPath('img\u002F[name].[hash:7].[ext]')\n        }\n      },{\n        test: \u002F\\.(mp4|webm|ogg|mp3|wav|flac|aac)(\\?.*)?$\u002F,\n        loader: 'url-loader',\n        options: {\n          limit: 10000,\n          name: utils.assetsPath('media\u002F[name].[hash:7].[ext]')\n        }\n      },{\n        test: \u002F\\.(woff2?|eot|ttf|otf)(\\?.*)?$\u002F,\n        loader: 'url-loader',\n        options: {\n          limit: 10000,\n          name: utils.assetsPath('fonts\u002F[name].[hash:7].[ext]')\n        }\n      }\n    ]\n  },\n  node: {   \u002F\u002F以下选项是Node.js全局变量或模块，这里主要是防止webpack注入一些Node.js的东西到vue中\n    setImmediate: false,\n    dgram: 'empty',\n    fs: 'empty',\n    net: 'empty',\n    tls: 'empty',\n    child_process: 'empty'\n  }\n}\n",[43,3017,3018,3023,3028,3032,3036,3040,3045,3049,3054,3059,3063,3067,3072,3077,3082,3087,3092,3097,3102,3107,3112,3117,3122,3126,3131,3136,3141,3146,3154,3158,3162,3167,3172,3177,3182,3187,3192,3197,3202,3207,3211,3216,3221,3226,3231,3236,3240,3244,3249,3254,3258,3262,3267,3271,3275,3280,3284,3288,3292,3297,3301,3305,3310,3314,3319,3324,3329,3334,3339,3344,3349,3353],{"__ignoreMap":41},[46,3019,3020],{"class":48,"line":49},[46,3021,3022],{},"\u002F\u002F 开发和生产共同使用提出来的基础配置文件，主要实现配制入口，配置输出环境，配置模块resolve和插件等\n",[46,3024,3025],{"class":48,"line":67},[46,3026,3027],{},"'use strict'\n",[46,3029,3030],{"class":48,"line":73},[46,3031,2461],{},[46,3033,3034],{"class":48,"line":130},[46,3035,2911],{},[46,3037,3038],{"class":48,"line":136},[46,3039,2466],{},[46,3041,3042],{"class":48,"line":142},[46,3043,3044],{},"const vueLoaderConfig = require('.\u002Fvue-loader.conf')\n",[46,3046,3047],{"class":48,"line":148},[46,3048,122],{"emptyLinePlaceholder":121},[46,3050,3051],{"class":48,"line":154},[46,3052,3053],{},"function resolve (dir) {   \u002F\u002F 拼接出绝对路径\n",[46,3055,3056],{"class":48,"line":160},[46,3057,3058],{},"  return path.join(__dirname, '..', dir)\n",[46,3060,3061],{"class":48,"line":166},[46,3062,593],{},[46,3064,3065],{"class":48,"line":172},[46,3066,122],{"emptyLinePlaceholder":121},[46,3068,3069],{"class":48,"line":178},[46,3070,3071],{},"module.exports = {\n",[46,3073,3074],{"class":48,"line":183},[46,3075,3076],{},"  context: path.resolve(__dirname, '..\u002F'),\n",[46,3078,3079],{"class":48,"line":189},[46,3080,3081],{},"  entry: {   \u002F\u002F 入口文件,可以有多个入口,也可只有一个,默认为单页面所以只有app一个入口\n",[46,3083,3084],{"class":48,"line":194},[46,3085,3086],{},"    app: '.\u002Fsrc\u002Fmain.js'\n",[46,3088,3089],{"class":48,"line":200},[46,3090,3091],{},"  },\n",[46,3093,3094],{"class":48,"line":398},[46,3095,3096],{},"  output: {    \u002F\u002F配置出口，默认是\u002Fdist作为目标文件夹的路径\n",[46,3098,3099],{"class":48,"line":404},[46,3100,3101],{},"    path: config.build.assetsRoot,   \u002F\u002F 路径\n",[46,3103,3104],{"class":48,"line":410},[46,3105,3106],{},"    filename: '[name].js',   \u002F\u002F 输出文件名\n",[46,3108,3109],{"class":48,"line":416},[46,3110,3111],{},"    publicPath: process.env.NODE_ENV === 'production'\n",[46,3113,3114],{"class":48,"line":422},[46,3115,3116],{},"      ? config.build.assetsPublicPath\n",[46,3118,3119],{"class":48,"line":428},[46,3120,3121],{},"      : config.dev.assetsPublicPath\n",[46,3123,3124],{"class":48,"line":434},[46,3125,3091],{},[46,3127,3128],{"class":48,"line":440},[46,3129,3130],{},"  resolve: {\n",[46,3132,3133],{"class":48,"line":446},[46,3134,3135],{},"    extensions: ['.js', '.vue', '.json'],  \u002F\u002F 自动的扩展后缀，比如一个js文件，则引用时书写可不要写.js\n",[46,3137,3138],{"class":48,"line":1142},[46,3139,3140],{},"    alias: {\n",[46,3142,3143],{"class":48,"line":1148},[46,3144,3145],{},"      'vue$': 'vue\u002Fdist\u002Fvue.esm.js',\n",[46,3147,3148,3151],{"class":48,"line":1154},[46,3149,3150],{},"      '@': resolve('src'),",[46,3152,3153],{},"   \u002F\u002F @ 即为 \u002Fsrc\n",[46,3155,3156],{"class":48,"line":1160},[46,3157,588],{},[46,3159,3160],{"class":48,"line":1166},[46,3161,3091],{},[46,3163,3164],{"class":48,"line":1171},[46,3165,3166],{},"  module: {   \u002F\u002F 使用插件配置相应文件的处理方法\n",[46,3168,3169],{"class":48,"line":1177},[46,3170,3171],{},"    rules: [{   \n",[46,3173,3174],{"class":48,"line":1182},[46,3175,3176],{},"        test: \u002F\\.vue$\u002F,\n",[46,3178,3179],{"class":48,"line":1188},[46,3180,3181],{},"        loader: 'vue-loader',   \u002F\u002F 使用vue-loader将vue文件转化成js的模块\n",[46,3183,3184],{"class":48,"line":1801},[46,3185,3186],{},"        options: vueLoaderConfig\n",[46,3188,3189],{"class":48,"line":1806},[46,3190,3191],{},"      },{\n",[46,3193,3194],{"class":48,"line":1811},[46,3195,3196],{},"        test: \u002F\\.js$\u002F,\n",[46,3198,3199],{"class":48,"line":1817},[46,3200,3201],{},"        loader: 'babel-loader',   \u002F\u002F js文件需要通过babel-loader进行编译成es5文件以及压缩等操作\n",[46,3203,3204],{"class":48,"line":2020},[46,3205,3206],{},"        include: [resolve('src'), resolve('test'), resolve('node_modules\u002Fwebpack-dev-server\u002Fclient')]\n",[46,3208,3209],{"class":48,"line":2026},[46,3210,3191],{},[46,3212,3213],{"class":48,"line":2031},[46,3214,3215],{},"        test: \u002F\\.(png|jpe?g|gif|svg)(\\?.*)?$\u002F,\n",[46,3217,3218],{"class":48,"line":2037},[46,3219,3220],{},"        loader: 'url-loader',   \u002F\u002F 图片、音像、字体都使用url-loader进行处理，超过10000会编译成base64\n",[46,3222,3223],{"class":48,"line":2042},[46,3224,3225],{},"        options: {\n",[46,3227,3228],{"class":48,"line":2047},[46,3229,3230],{},"          limit: 10000,\n",[46,3232,3233],{"class":48,"line":2052},[46,3234,3235],{},"          name: utils.assetsPath('img\u002F[name].[hash:7].[ext]')\n",[46,3237,3238],{"class":48,"line":2058},[46,3239,541],{},[46,3241,3242],{"class":48,"line":2063},[46,3243,3191],{},[46,3245,3246],{"class":48,"line":2068},[46,3247,3248],{},"        test: \u002F\\.(mp4|webm|ogg|mp3|wav|flac|aac)(\\?.*)?$\u002F,\n",[46,3250,3251],{"class":48,"line":2073},[46,3252,3253],{},"        loader: 'url-loader',\n",[46,3255,3256],{"class":48,"line":2078},[46,3257,3225],{},[46,3259,3260],{"class":48,"line":2084},[46,3261,3230],{},[46,3263,3264],{"class":48,"line":2695},[46,3265,3266],{},"          name: utils.assetsPath('media\u002F[name].[hash:7].[ext]')\n",[46,3268,3269],{"class":48,"line":2701},[46,3270,541],{},[46,3272,3273],{"class":48,"line":2707},[46,3274,3191],{},[46,3276,3277],{"class":48,"line":2713},[46,3278,3279],{},"        test: \u002F\\.(woff2?|eot|ttf|otf)(\\?.*)?$\u002F,\n",[46,3281,3282],{"class":48,"line":2719},[46,3283,3253],{},[46,3285,3286],{"class":48,"line":2725},[46,3287,3225],{},[46,3289,3290],{"class":48,"line":2730},[46,3291,3230],{},[46,3293,3294],{"class":48,"line":2735},[46,3295,3296],{},"          name: utils.assetsPath('fonts\u002F[name].[hash:7].[ext]')\n",[46,3298,3299],{"class":48,"line":2741},[46,3300,541],{},[46,3302,3303],{"class":48,"line":2747},[46,3304,654],{},[46,3306,3307],{"class":48,"line":2753},[46,3308,3309],{},"    ]\n",[46,3311,3312],{"class":48,"line":2759},[46,3313,3091],{},[46,3315,3316],{"class":48,"line":2765},[46,3317,3318],{},"  node: {   \u002F\u002F以下选项是Node.js全局变量或模块，这里主要是防止webpack注入一些Node.js的东西到vue中\n",[46,3320,3321],{"class":48,"line":2771},[46,3322,3323],{},"    setImmediate: false,\n",[46,3325,3326],{"class":48,"line":2777},[46,3327,3328],{},"    dgram: 'empty',\n",[46,3330,3331],{"class":48,"line":2783},[46,3332,3333],{},"    fs: 'empty',\n",[46,3335,3336],{"class":48,"line":2788},[46,3337,3338],{},"    net: 'empty',\n",[46,3340,3341],{"class":48,"line":2793},[46,3342,3343],{},"    tls: 'empty',\n",[46,3345,3346],{"class":48,"line":2798},[46,3347,3348],{},"    child_process: 'empty'\n",[46,3350,3351],{"class":48,"line":2804},[46,3352,1371],{},[46,3354,3355],{"class":48,"line":2809},[46,3356,593],{},[28,3358,3360],{"id":3359},"_6-buildwebpackdevconfjs","6. build\u002Fwebpack.dev.conf.js",[36,3362,3364],{"className":469,"code":3363,"language":471,"meta":41,"style":41},"\u002F\u002F 开发环境的wepack相关配置\nconst utils = require('.\u002Futils')\nconst webpack = require('webpack')\nconst config = require('..\u002Fconfig')\nconst merge = require('webpack-merge')   \u002F\u002F 通过webpack-merge实现webpack.dev.conf.js对wepack.base.config.js的继承\nconst path = require('path')\nconst baseWebpackConfig = require('.\u002Fwebpack.base.conf')\nconst CopyWebpackPlugin = require('copy-webpack-plugin')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')   \u002F\u002F 美化webpack的错误信息和日志的插件\nconst portfinder = require('portfinder')   \u002F\u002F 查看空闲端口位置，默认情况下搜索8000这个端口\n\nconst HOST = process.env.HOST   \u002F\u002Fprocesss为node的一个全局对象获取当前程序的环境变量，即HOST\nconst PORT = process.env.PORT && Number(process.env.PORT)\n\nconst devWebpackConfig = merge(baseWebpackConfig, {\n  module: {\n    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })   \u002F\u002F 规则是工具utils中处理出来的styleLoaders，生成了css，less,postcss等规则\n  },\n  devtool: config.dev.devtool,   \u002F\u002F 增强调试\n\n  devServer: {   \u002F\u002F 此处的配置都是在config的index.js中设定好了\n    clientLogLevel: 'warning',\n    historyApiFallback: {   \u002F\u002F 当使用 HTML5 History API 时，任意的 404 响应都可能需要被替代为 index.html\n      rewrites: [\n        { from: \u002F.*\u002F, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },\n      ],\n    },\n    hot: true,   \u002F\u002F 热加载\n    contentBase: false, \n    compress: true,   \u002F\u002F 压缩\n    host: HOST || config.dev.host,\n    port: PORT || config.dev.port,\n    open: config.dev.autoOpenBrowser,   \u002F\u002F 调试时自动打开浏览器\n    overlay: config.dev.errorOverlay\n      ? { warnings: false, errors: true }\n      : false,\n    publicPath: config.dev.assetsPublicPath,\n    proxy: config.dev.proxyTable,   \u002F\u002F 接口代理\n    quiet: true,   \u002F\u002F 控制台是否禁止打印警告和错误,若用FriendlyErrorsPlugin 此处为 true\n    watchOptions: {\n      poll: config.dev.poll,   \u002F\u002F 文件系统检测改动\n    }\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': require('..\u002Fconfig\u002Fdev.env')\n    }),\n    new webpack.HotModuleReplacementPlugin(),   \u002F\u002F 模块热替换插件，修改模块时不需要刷新页面\n    new webpack.NamedModulesPlugin(),   \u002F\u002F 显示文件的正确名字\n    new webpack.NoEmitOnErrorsPlugin(),   \u002F\u002F 当webpack编译错误的时候，来中端打包进程，防止错误代码打包到文件中\n    new HtmlWebpackPlugin({   \u002F\u002F 该插件可自动生成一个 html5 文件或使用模板文件将编译好的代码注入进去\n      filename: 'index.html',\n      template: 'index.html',\n      inject: true\n    }),\n    new CopyWebpackPlugin([   \u002F\u002F 复制插件\n      {\n        from: path.resolve(__dirname, '..\u002Fstatic'),\n        to: config.dev.assetsSubDirectory,\n        ignore: ['.*']\n      }\n    ])\n  ]\n})\n\nmodule.exports = new Promise((resolve, reject) => {\n  portfinder.basePort = process.env.PORT || config.dev.port\n  portfinder.getPort((err, port) => {   \u002F\u002F 查找端口号\n    if (err) {\n      reject(err)\n    } else {   \u002F\u002F 端口被占用时就重新设置evn和devServer的端口\n      process.env.PORT = port\n      devWebpackConfig.devServer.port = port\n      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({\n        compilationSuccessInfo: {\n          messages: [`Your application is running here: http:\u002F\u002F${devWebpackConfig.devServer.host}:${port}`],\n        },\n        onErrors: config.dev.notifyOnErrors\n        ? utils.createNotifierCallback()\n        : undefined\n      }))\n      resolve(devWebpackConfig)\n    }\n  })\n})\n",[43,3365,3366,3371,3375,3380,3384,3389,3393,3398,3403,3408,3413,3418,3422,3427,3432,3436,3441,3446,3451,3455,3460,3464,3469,3474,3479,3484,3489,3494,3498,3503,3508,3513,3518,3523,3528,3533,3538,3543,3548,3553,3558,3563,3568,3572,3576,3581,3586,3591,3596,3601,3606,3611,3616,3621,3626,3631,3635,3640,3644,3649,3654,3659,3663,3668,3672,3676,3680,3685,3690,3695,3700,3705,3710,3715,3720,3725,3730,3735,3740,3745,3750,3755,3760,3765,3769,3773],{"__ignoreMap":41},[46,3367,3368],{"class":48,"line":49},[46,3369,3370],{},"\u002F\u002F 开发环境的wepack相关配置\n",[46,3372,3373],{"class":48,"line":67},[46,3374,2911],{},[46,3376,3377],{"class":48,"line":73},[46,3378,3379],{},"const webpack = require('webpack')\n",[46,3381,3382],{"class":48,"line":130},[46,3383,2466],{},[46,3385,3386],{"class":48,"line":136},[46,3387,3388],{},"const merge = require('webpack-merge')   \u002F\u002F 通过webpack-merge实现webpack.dev.conf.js对wepack.base.config.js的继承\n",[46,3390,3391],{"class":48,"line":142},[46,3392,2461],{},[46,3394,3395],{"class":48,"line":148},[46,3396,3397],{},"const baseWebpackConfig = require('.\u002Fwebpack.base.conf')\n",[46,3399,3400],{"class":48,"line":154},[46,3401,3402],{},"const CopyWebpackPlugin = require('copy-webpack-plugin')\n",[46,3404,3405],{"class":48,"line":160},[46,3406,3407],{},"const HtmlWebpackPlugin = require('html-webpack-plugin')\n",[46,3409,3410],{"class":48,"line":166},[46,3411,3412],{},"const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')   \u002F\u002F 美化webpack的错误信息和日志的插件\n",[46,3414,3415],{"class":48,"line":172},[46,3416,3417],{},"const portfinder = require('portfinder')   \u002F\u002F 查看空闲端口位置，默认情况下搜索8000这个端口\n",[46,3419,3420],{"class":48,"line":178},[46,3421,122],{"emptyLinePlaceholder":121},[46,3423,3424],{"class":48,"line":183},[46,3425,3426],{},"const HOST = process.env.HOST   \u002F\u002Fprocesss为node的一个全局对象获取当前程序的环境变量，即HOST\n",[46,3428,3429],{"class":48,"line":189},[46,3430,3431],{},"const PORT = process.env.PORT && Number(process.env.PORT)\n",[46,3433,3434],{"class":48,"line":194},[46,3435,122],{"emptyLinePlaceholder":121},[46,3437,3438],{"class":48,"line":200},[46,3439,3440],{},"const devWebpackConfig = merge(baseWebpackConfig, {\n",[46,3442,3443],{"class":48,"line":398},[46,3444,3445],{},"  module: {\n",[46,3447,3448],{"class":48,"line":404},[46,3449,3450],{},"    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })   \u002F\u002F 规则是工具utils中处理出来的styleLoaders，生成了css，less,postcss等规则\n",[46,3452,3453],{"class":48,"line":410},[46,3454,3091],{},[46,3456,3457],{"class":48,"line":416},[46,3458,3459],{},"  devtool: config.dev.devtool,   \u002F\u002F 增强调试\n",[46,3461,3462],{"class":48,"line":422},[46,3463,122],{"emptyLinePlaceholder":121},[46,3465,3466],{"class":48,"line":428},[46,3467,3468],{},"  devServer: {   \u002F\u002F 此处的配置都是在config的index.js中设定好了\n",[46,3470,3471],{"class":48,"line":434},[46,3472,3473],{},"    clientLogLevel: 'warning',\n",[46,3475,3476],{"class":48,"line":440},[46,3477,3478],{},"    historyApiFallback: {   \u002F\u002F 当使用 HTML5 History API 时，任意的 404 响应都可能需要被替代为 index.html\n",[46,3480,3481],{"class":48,"line":446},[46,3482,3483],{},"      rewrites: [\n",[46,3485,3486],{"class":48,"line":1142},[46,3487,3488],{},"        { from: \u002F.*\u002F, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },\n",[46,3490,3491],{"class":48,"line":1148},[46,3492,3493],{},"      ],\n",[46,3495,3496],{"class":48,"line":1154},[46,3497,698],{},[46,3499,3500],{"class":48,"line":1160},[46,3501,3502],{},"    hot: true,   \u002F\u002F 热加载\n",[46,3504,3505],{"class":48,"line":1166},[46,3506,3507],{},"    contentBase: false, \n",[46,3509,3510],{"class":48,"line":1171},[46,3511,3512],{},"    compress: true,   \u002F\u002F 压缩\n",[46,3514,3515],{"class":48,"line":1177},[46,3516,3517],{},"    host: HOST || config.dev.host,\n",[46,3519,3520],{"class":48,"line":1182},[46,3521,3522],{},"    port: PORT || config.dev.port,\n",[46,3524,3525],{"class":48,"line":1188},[46,3526,3527],{},"    open: config.dev.autoOpenBrowser,   \u002F\u002F 调试时自动打开浏览器\n",[46,3529,3530],{"class":48,"line":1801},[46,3531,3532],{},"    overlay: config.dev.errorOverlay\n",[46,3534,3535],{"class":48,"line":1806},[46,3536,3537],{},"      ? { warnings: false, errors: true }\n",[46,3539,3540],{"class":48,"line":1811},[46,3541,3542],{},"      : false,\n",[46,3544,3545],{"class":48,"line":1817},[46,3546,3547],{},"    publicPath: config.dev.assetsPublicPath,\n",[46,3549,3550],{"class":48,"line":2020},[46,3551,3552],{},"    proxy: config.dev.proxyTable,   \u002F\u002F 接口代理\n",[46,3554,3555],{"class":48,"line":2026},[46,3556,3557],{},"    quiet: true,   \u002F\u002F 控制台是否禁止打印警告和错误,若用FriendlyErrorsPlugin 此处为 true\n",[46,3559,3560],{"class":48,"line":2031},[46,3561,3562],{},"    watchOptions: {\n",[46,3564,3565],{"class":48,"line":2037},[46,3566,3567],{},"      poll: config.dev.poll,   \u002F\u002F 文件系统检测改动\n",[46,3569,3570],{"class":48,"line":2042},[46,3571,588],{},[46,3573,3574],{"class":48,"line":2047},[46,3575,3091],{},[46,3577,3578],{"class":48,"line":2052},[46,3579,3580],{},"  plugins: [\n",[46,3582,3583],{"class":48,"line":2058},[46,3584,3585],{},"    new webpack.DefinePlugin({\n",[46,3587,3588],{"class":48,"line":2063},[46,3589,3590],{},"      'process.env': require('..\u002Fconfig\u002Fdev.env')\n",[46,3592,3593],{"class":48,"line":2068},[46,3594,3595],{},"    }),\n",[46,3597,3598],{"class":48,"line":2073},[46,3599,3600],{},"    new webpack.HotModuleReplacementPlugin(),   \u002F\u002F 模块热替换插件，修改模块时不需要刷新页面\n",[46,3602,3603],{"class":48,"line":2078},[46,3604,3605],{},"    new webpack.NamedModulesPlugin(),   \u002F\u002F 显示文件的正确名字\n",[46,3607,3608],{"class":48,"line":2084},[46,3609,3610],{},"    new webpack.NoEmitOnErrorsPlugin(),   \u002F\u002F 当webpack编译错误的时候，来中端打包进程，防止错误代码打包到文件中\n",[46,3612,3613],{"class":48,"line":2695},[46,3614,3615],{},"    new HtmlWebpackPlugin({   \u002F\u002F 该插件可自动生成一个 html5 文件或使用模板文件将编译好的代码注入进去\n",[46,3617,3618],{"class":48,"line":2701},[46,3619,3620],{},"      filename: 'index.html',\n",[46,3622,3623],{"class":48,"line":2707},[46,3624,3625],{},"      template: 'index.html',\n",[46,3627,3628],{"class":48,"line":2713},[46,3629,3630],{},"      inject: true\n",[46,3632,3633],{"class":48,"line":2719},[46,3634,3595],{},[46,3636,3637],{"class":48,"line":2725},[46,3638,3639],{},"    new CopyWebpackPlugin([   \u002F\u002F 复制插件\n",[46,3641,3642],{"class":48,"line":2730},[46,3643,889],{},[46,3645,3646],{"class":48,"line":2735},[46,3647,3648],{},"        from: path.resolve(__dirname, '..\u002Fstatic'),\n",[46,3650,3651],{"class":48,"line":2741},[46,3652,3653],{},"        to: config.dev.assetsSubDirectory,\n",[46,3655,3656],{"class":48,"line":2747},[46,3657,3658],{},"        ignore: ['.*']\n",[46,3660,3661],{"class":48,"line":2753},[46,3662,654],{},[46,3664,3665],{"class":48,"line":2759},[46,3666,3667],{},"    ])\n",[46,3669,3670],{"class":48,"line":2765},[46,3671,1185],{},[46,3673,3674],{"class":48,"line":2771},[46,3675,1191],{},[46,3677,3678],{"class":48,"line":2777},[46,3679,122],{"emptyLinePlaceholder":121},[46,3681,3682],{"class":48,"line":2783},[46,3683,3684],{},"module.exports = new Promise((resolve, reject) => {\n",[46,3686,3687],{"class":48,"line":2788},[46,3688,3689],{},"  portfinder.basePort = process.env.PORT || config.dev.port\n",[46,3691,3692],{"class":48,"line":2793},[46,3693,3694],{},"  portfinder.getPort((err, port) => {   \u002F\u002F 查找端口号\n",[46,3696,3697],{"class":48,"line":2798},[46,3698,3699],{},"    if (err) {\n",[46,3701,3702],{"class":48,"line":2804},[46,3703,3704],{},"      reject(err)\n",[46,3706,3707],{"class":48,"line":2809},[46,3708,3709],{},"    } else {   \u002F\u002F 端口被占用时就重新设置evn和devServer的端口\n",[46,3711,3712],{"class":48,"line":2814},[46,3713,3714],{},"      process.env.PORT = port\n",[46,3716,3717],{"class":48,"line":2820},[46,3718,3719],{},"      devWebpackConfig.devServer.port = port\n",[46,3721,3722],{"class":48,"line":2826},[46,3723,3724],{},"      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({\n",[46,3726,3727],{"class":48,"line":2832},[46,3728,3729],{},"        compilationSuccessInfo: {\n",[46,3731,3732],{"class":48,"line":2838},[46,3733,3734],{},"          messages: [`Your application is running here: http:\u002F\u002F${devWebpackConfig.devServer.host}:${port}`],\n",[46,3736,3737],{"class":48,"line":2844},[46,3738,3739],{},"        },\n",[46,3741,3742],{"class":48,"line":2850},[46,3743,3744],{},"        onErrors: config.dev.notifyOnErrors\n",[46,3746,3747],{"class":48,"line":2856},[46,3748,3749],{},"        ? utils.createNotifierCallback()\n",[46,3751,3752],{"class":48,"line":2862},[46,3753,3754],{},"        : undefined\n",[46,3756,3757],{"class":48,"line":2868},[46,3758,3759],{},"      }))\n",[46,3761,3762],{"class":48,"line":2874},[46,3763,3764],{},"      resolve(devWebpackConfig)\n",[46,3766,3767],{"class":48,"line":2880},[46,3768,588],{},[46,3770,3771],{"class":48,"line":2885},[46,3772,1522],{},[46,3774,3775],{"class":48,"line":2890},[46,3776,1191],{},[28,3778,3780],{"id":3779},"_7-buildwebpackprodconfjs","7. build\u002Fwebpack.prod.conf.js",[36,3782,3784],{"className":469,"code":3783,"language":471,"meta":41,"style":41},"\u002F\u002F 生产环境的wepack相关配置文件\nconst path = require('path')\nconst utils = require('.\u002Futils')\nconst webpack = require('webpack')\nconst config = require('..\u002Fconfig')\nconst merge = require('webpack-merge')   \u002F\u002F webpack 配置合并插件\nconst baseWebpackConfig = require('.\u002Fwebpack.base.conf')   \u002F\u002F webpack 基本配置\nconst CopyWebpackPlugin = require('copy-webpack-plugin')   \u002F\u002F webpack 复制文件和文件夹的插件\nconst HtmlWebpackPlugin = require('html-webpack-plugin')   \u002F\u002F 自动生成 html 并且注入到 .html 文件中的插件\nconst ExtractTextPlugin = require('extract-text-webpack-plugin')   \u002F\u002F 提取css的插件\nconst OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')   \u002F\u002F webpack 优化压缩和优化 css 的插件\nconst UglifyJsPlugin = require('uglifyjs-webpack-plugin')\n\nconst env = require('..\u002Fconfig\u002Fprod.env')\n\nconst webpackConfig = merge(baseWebpackConfig, {\n  module: {\n    rules: utils.styleLoaders({   \n      sourceMap: config.build.productionSourceMap,   \u002F\u002F 开启调试的模式。默认为true\n      extract: true,\n      usePostCSS: true\n    })\n  },\n  devtool: config.build.productionSourceMap ? config.build.devtool : false,\n  output: {\n    path: config.build.assetsRoot,\n    filename: utils.assetsPath('js\u002F[name].[chunkhash].js'),\n    chunkFilename: utils.assetsPath('js\u002F[id].[chunkhash].js')\n  },\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': env\n    }),\n    new UglifyJsPlugin({\n      uglifyOptions: {\n        compress: {   \u002F\u002F 压缩\n          warnings: false\n        }\n      },\n      sourceMap: config.build.productionSourceMap,\n      parallel: true\n    }),\n    new ExtractTextPlugin({   \u002F\u002F 抽取文本,比如打包之后的index页面有style插入,就是这个插件抽取出来的,减少请求\n      filename: utils.assetsPath('css\u002F[name].[contenthash].css'),\n      allChunks: true,\n    }),\n    new OptimizeCSSPlugin({   \u002F\u002F 优化css的插件\n      cssProcessorOptions: config.build.productionSourceMap\n        ? { safe: true, map: { inline: false } }\n        : { safe: true }\n    }),\n    new HtmlWebpackPlugin({   \u002F\u002F html打包\n      filename: config.build.index,\n      template: 'index.html',\n      inject: true,\n      minify: {\n        removeComments: true,   \u002F\u002F 删除注释\n        collapseWhitespace: true,   \u002F\u002F 删除空格\n        removeAttributeQuotes: true   \u002F\u002F 删除属性的引号\n      },\n      chunksSortMode: 'dependency' \u002F\u002F 模块排序，按照我们需要的顺序排序\n    }),\n    new webpack.HashedModuleIdsPlugin(),\n    new webpack.optimize.ModuleConcatenationPlugin(),\n    new webpack.optimize.CommonsChunkPlugin({   \u002F\u002F 抽取公共的模块\n      name: 'vendor',\n      minChunks (module) {\n        \u002F\u002F any required modules inside node_modules are extracted to vendor\n        return (\n          module.resource &&\n          \u002F\\.js$\u002F.test(module.resource) &&\n          module.resource.indexOf(\n            path.join(__dirname, '..\u002Fnode_modules')\n          ) === 0\n        )\n      }\n    }),\n\n    new webpack.optimize.CommonsChunkPlugin({\n      name: 'manifest',\n      minChunks: Infinity\n    }),\n    new webpack.optimize.CommonsChunkPlugin({\n      name: 'app',\n      async: 'vendor-async',\n      children: true,\n      minChunks: 3\n    }),\n\n    new CopyWebpackPlugin([   \u002F\u002F 复制，比如打包完之后需要把打包的文件复制到dist里面\n      {\n        from: path.resolve(__dirname, '..\u002Fstatic'),\n        to: config.build.assetsSubDirectory,\n        ignore: ['.*']\n      }\n    ])\n  ]\n})\n\nif (config.build.productionGzip) {\n  const CompressionWebpackPlugin = require('compression-webpack-plugin')\n  webpackConfig.plugins.push(\n    new CompressionWebpackPlugin({\n      asset: '[path].gz[query]',\n      algorithm: 'gzip',\n      test: new RegExp(\n        '\\\\.(' +\n        config.build.productionGzipExtensions.join('|') +\n        ')$'\n      ),\n      threshold: 10240,\n      minRatio: 0.8\n    })\n  )\n}\nif (config.build.bundleAnalyzerReport) {\n  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin\n  webpackConfig.plugins.push(new BundleAnalyzerPlugin())\n}\nmodule.exports = webpackConfig\n",[43,3785,3786,3791,3795,3799,3803,3807,3812,3817,3822,3827,3832,3837,3842,3846,3851,3855,3860,3864,3869,3874,3879,3884,3888,3892,3897,3902,3907,3912,3917,3921,3925,3929,3934,3938,3943,3948,3953,3958,3962,3966,3971,3976,3980,3985,3990,3995,3999,4004,4009,4014,4019,4023,4028,4033,4037,4042,4047,4052,4057,4062,4066,4071,4075,4080,4085,4090,4095,4100,4105,4110,4115,4120,4125,4130,4135,4140,4144,4148,4152,4157,4162,4167,4171,4175,4180,4185,4190,4196,4201,4206,4212,4217,4222,4228,4233,4238,4243,4248,4253,4258,4264,4270,4276,4282,4288,4294,4300,4306,4312,4318,4324,4330,4336,4341,4347,4352,4358,4364,4370,4375],{"__ignoreMap":41},[46,3787,3788],{"class":48,"line":49},[46,3789,3790],{},"\u002F\u002F 生产环境的wepack相关配置文件\n",[46,3792,3793],{"class":48,"line":67},[46,3794,2461],{},[46,3796,3797],{"class":48,"line":73},[46,3798,2911],{},[46,3800,3801],{"class":48,"line":130},[46,3802,3379],{},[46,3804,3805],{"class":48,"line":136},[46,3806,2466],{},[46,3808,3809],{"class":48,"line":142},[46,3810,3811],{},"const merge = require('webpack-merge')   \u002F\u002F webpack 配置合并插件\n",[46,3813,3814],{"class":48,"line":148},[46,3815,3816],{},"const baseWebpackConfig = require('.\u002Fwebpack.base.conf')   \u002F\u002F webpack 基本配置\n",[46,3818,3819],{"class":48,"line":154},[46,3820,3821],{},"const CopyWebpackPlugin = require('copy-webpack-plugin')   \u002F\u002F webpack 复制文件和文件夹的插件\n",[46,3823,3824],{"class":48,"line":160},[46,3825,3826],{},"const HtmlWebpackPlugin = require('html-webpack-plugin')   \u002F\u002F 自动生成 html 并且注入到 .html 文件中的插件\n",[46,3828,3829],{"class":48,"line":166},[46,3830,3831],{},"const ExtractTextPlugin = require('extract-text-webpack-plugin')   \u002F\u002F 提取css的插件\n",[46,3833,3834],{"class":48,"line":172},[46,3835,3836],{},"const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')   \u002F\u002F webpack 优化压缩和优化 css 的插件\n",[46,3838,3839],{"class":48,"line":178},[46,3840,3841],{},"const UglifyJsPlugin = require('uglifyjs-webpack-plugin')\n",[46,3843,3844],{"class":48,"line":183},[46,3845,122],{"emptyLinePlaceholder":121},[46,3847,3848],{"class":48,"line":189},[46,3849,3850],{},"const env = require('..\u002Fconfig\u002Fprod.env')\n",[46,3852,3853],{"class":48,"line":194},[46,3854,122],{"emptyLinePlaceholder":121},[46,3856,3857],{"class":48,"line":200},[46,3858,3859],{},"const webpackConfig = merge(baseWebpackConfig, {\n",[46,3861,3862],{"class":48,"line":398},[46,3863,3445],{},[46,3865,3866],{"class":48,"line":404},[46,3867,3868],{},"    rules: utils.styleLoaders({   \n",[46,3870,3871],{"class":48,"line":410},[46,3872,3873],{},"      sourceMap: config.build.productionSourceMap,   \u002F\u002F 开启调试的模式。默认为true\n",[46,3875,3876],{"class":48,"line":416},[46,3877,3878],{},"      extract: true,\n",[46,3880,3881],{"class":48,"line":422},[46,3882,3883],{},"      usePostCSS: true\n",[46,3885,3886],{"class":48,"line":428},[46,3887,1356],{},[46,3889,3890],{"class":48,"line":434},[46,3891,3091],{},[46,3893,3894],{"class":48,"line":440},[46,3895,3896],{},"  devtool: config.build.productionSourceMap ? config.build.devtool : false,\n",[46,3898,3899],{"class":48,"line":446},[46,3900,3901],{},"  output: {\n",[46,3903,3904],{"class":48,"line":1142},[46,3905,3906],{},"    path: config.build.assetsRoot,\n",[46,3908,3909],{"class":48,"line":1148},[46,3910,3911],{},"    filename: utils.assetsPath('js\u002F[name].[chunkhash].js'),\n",[46,3913,3914],{"class":48,"line":1154},[46,3915,3916],{},"    chunkFilename: utils.assetsPath('js\u002F[id].[chunkhash].js')\n",[46,3918,3919],{"class":48,"line":1160},[46,3920,3091],{},[46,3922,3923],{"class":48,"line":1166},[46,3924,3580],{},[46,3926,3927],{"class":48,"line":1171},[46,3928,3585],{},[46,3930,3931],{"class":48,"line":1177},[46,3932,3933],{},"      'process.env': env\n",[46,3935,3936],{"class":48,"line":1182},[46,3937,3595],{},[46,3939,3940],{"class":48,"line":1188},[46,3941,3942],{},"    new UglifyJsPlugin({\n",[46,3944,3945],{"class":48,"line":1801},[46,3946,3947],{},"      uglifyOptions: {\n",[46,3949,3950],{"class":48,"line":1806},[46,3951,3952],{},"        compress: {   \u002F\u002F 压缩\n",[46,3954,3955],{"class":48,"line":1811},[46,3956,3957],{},"          warnings: false\n",[46,3959,3960],{"class":48,"line":1817},[46,3961,541],{},[46,3963,3964],{"class":48,"line":2020},[46,3965,551],{},[46,3967,3968],{"class":48,"line":2026},[46,3969,3970],{},"      sourceMap: config.build.productionSourceMap,\n",[46,3972,3973],{"class":48,"line":2031},[46,3974,3975],{},"      parallel: true\n",[46,3977,3978],{"class":48,"line":2037},[46,3979,3595],{},[46,3981,3982],{"class":48,"line":2042},[46,3983,3984],{},"    new ExtractTextPlugin({   \u002F\u002F 抽取文本,比如打包之后的index页面有style插入,就是这个插件抽取出来的,减少请求\n",[46,3986,3987],{"class":48,"line":2047},[46,3988,3989],{},"      filename: utils.assetsPath('css\u002F[name].[contenthash].css'),\n",[46,3991,3992],{"class":48,"line":2052},[46,3993,3994],{},"      allChunks: true,\n",[46,3996,3997],{"class":48,"line":2058},[46,3998,3595],{},[46,4000,4001],{"class":48,"line":2063},[46,4002,4003],{},"    new OptimizeCSSPlugin({   \u002F\u002F 优化css的插件\n",[46,4005,4006],{"class":48,"line":2068},[46,4007,4008],{},"      cssProcessorOptions: config.build.productionSourceMap\n",[46,4010,4011],{"class":48,"line":2073},[46,4012,4013],{},"        ? { safe: true, map: { inline: false } }\n",[46,4015,4016],{"class":48,"line":2078},[46,4017,4018],{},"        : { safe: true }\n",[46,4020,4021],{"class":48,"line":2084},[46,4022,3595],{},[46,4024,4025],{"class":48,"line":2695},[46,4026,4027],{},"    new HtmlWebpackPlugin({   \u002F\u002F html打包\n",[46,4029,4030],{"class":48,"line":2701},[46,4031,4032],{},"      filename: config.build.index,\n",[46,4034,4035],{"class":48,"line":2707},[46,4036,3625],{},[46,4038,4039],{"class":48,"line":2713},[46,4040,4041],{},"      inject: true,\n",[46,4043,4044],{"class":48,"line":2719},[46,4045,4046],{},"      minify: {\n",[46,4048,4049],{"class":48,"line":2725},[46,4050,4051],{},"        removeComments: true,   \u002F\u002F 删除注释\n",[46,4053,4054],{"class":48,"line":2730},[46,4055,4056],{},"        collapseWhitespace: true,   \u002F\u002F 删除空格\n",[46,4058,4059],{"class":48,"line":2735},[46,4060,4061],{},"        removeAttributeQuotes: true   \u002F\u002F 删除属性的引号\n",[46,4063,4064],{"class":48,"line":2741},[46,4065,551],{},[46,4067,4068],{"class":48,"line":2747},[46,4069,4070],{},"      chunksSortMode: 'dependency' \u002F\u002F 模块排序，按照我们需要的顺序排序\n",[46,4072,4073],{"class":48,"line":2753},[46,4074,3595],{},[46,4076,4077],{"class":48,"line":2759},[46,4078,4079],{},"    new webpack.HashedModuleIdsPlugin(),\n",[46,4081,4082],{"class":48,"line":2765},[46,4083,4084],{},"    new webpack.optimize.ModuleConcatenationPlugin(),\n",[46,4086,4087],{"class":48,"line":2771},[46,4088,4089],{},"    new webpack.optimize.CommonsChunkPlugin({   \u002F\u002F 抽取公共的模块\n",[46,4091,4092],{"class":48,"line":2777},[46,4093,4094],{},"      name: 'vendor',\n",[46,4096,4097],{"class":48,"line":2783},[46,4098,4099],{},"      minChunks (module) {\n",[46,4101,4102],{"class":48,"line":2788},[46,4103,4104],{},"        \u002F\u002F any required modules inside node_modules are extracted to vendor\n",[46,4106,4107],{"class":48,"line":2793},[46,4108,4109],{},"        return (\n",[46,4111,4112],{"class":48,"line":2798},[46,4113,4114],{},"          module.resource &&\n",[46,4116,4117],{"class":48,"line":2804},[46,4118,4119],{},"          \u002F\\.js$\u002F.test(module.resource) &&\n",[46,4121,4122],{"class":48,"line":2809},[46,4123,4124],{},"          module.resource.indexOf(\n",[46,4126,4127],{"class":48,"line":2814},[46,4128,4129],{},"            path.join(__dirname, '..\u002Fnode_modules')\n",[46,4131,4132],{"class":48,"line":2820},[46,4133,4134],{},"          ) === 0\n",[46,4136,4137],{"class":48,"line":2826},[46,4138,4139],{},"        )\n",[46,4141,4142],{"class":48,"line":2832},[46,4143,654],{},[46,4145,4146],{"class":48,"line":2838},[46,4147,3595],{},[46,4149,4150],{"class":48,"line":2844},[46,4151,122],{"emptyLinePlaceholder":121},[46,4153,4154],{"class":48,"line":2850},[46,4155,4156],{},"    new webpack.optimize.CommonsChunkPlugin({\n",[46,4158,4159],{"class":48,"line":2856},[46,4160,4161],{},"      name: 'manifest',\n",[46,4163,4164],{"class":48,"line":2862},[46,4165,4166],{},"      minChunks: Infinity\n",[46,4168,4169],{"class":48,"line":2868},[46,4170,3595],{},[46,4172,4173],{"class":48,"line":2874},[46,4174,4156],{},[46,4176,4177],{"class":48,"line":2880},[46,4178,4179],{},"      name: 'app',\n",[46,4181,4182],{"class":48,"line":2885},[46,4183,4184],{},"      async: 'vendor-async',\n",[46,4186,4187],{"class":48,"line":2890},[46,4188,4189],{},"      children: true,\n",[46,4191,4193],{"class":48,"line":4192},87,[46,4194,4195],{},"      minChunks: 3\n",[46,4197,4199],{"class":48,"line":4198},88,[46,4200,3595],{},[46,4202,4204],{"class":48,"line":4203},89,[46,4205,122],{"emptyLinePlaceholder":121},[46,4207,4209],{"class":48,"line":4208},90,[46,4210,4211],{},"    new CopyWebpackPlugin([   \u002F\u002F 复制，比如打包完之后需要把打包的文件复制到dist里面\n",[46,4213,4215],{"class":48,"line":4214},91,[46,4216,889],{},[46,4218,4220],{"class":48,"line":4219},92,[46,4221,3648],{},[46,4223,4225],{"class":48,"line":4224},93,[46,4226,4227],{},"        to: config.build.assetsSubDirectory,\n",[46,4229,4231],{"class":48,"line":4230},94,[46,4232,3658],{},[46,4234,4236],{"class":48,"line":4235},95,[46,4237,654],{},[46,4239,4241],{"class":48,"line":4240},96,[46,4242,3667],{},[46,4244,4246],{"class":48,"line":4245},97,[46,4247,1185],{},[46,4249,4251],{"class":48,"line":4250},98,[46,4252,1191],{},[46,4254,4256],{"class":48,"line":4255},99,[46,4257,122],{"emptyLinePlaceholder":121},[46,4259,4261],{"class":48,"line":4260},100,[46,4262,4263],{},"if (config.build.productionGzip) {\n",[46,4265,4267],{"class":48,"line":4266},101,[46,4268,4269],{},"  const CompressionWebpackPlugin = require('compression-webpack-plugin')\n",[46,4271,4273],{"class":48,"line":4272},102,[46,4274,4275],{},"  webpackConfig.plugins.push(\n",[46,4277,4279],{"class":48,"line":4278},103,[46,4280,4281],{},"    new CompressionWebpackPlugin({\n",[46,4283,4285],{"class":48,"line":4284},104,[46,4286,4287],{},"      asset: '[path].gz[query]',\n",[46,4289,4291],{"class":48,"line":4290},105,[46,4292,4293],{},"      algorithm: 'gzip',\n",[46,4295,4297],{"class":48,"line":4296},106,[46,4298,4299],{},"      test: new RegExp(\n",[46,4301,4303],{"class":48,"line":4302},107,[46,4304,4305],{},"        '\\\\.(' +\n",[46,4307,4309],{"class":48,"line":4308},108,[46,4310,4311],{},"        config.build.productionGzipExtensions.join('|') +\n",[46,4313,4315],{"class":48,"line":4314},109,[46,4316,4317],{},"        ')$'\n",[46,4319,4321],{"class":48,"line":4320},110,[46,4322,4323],{},"      ),\n",[46,4325,4327],{"class":48,"line":4326},111,[46,4328,4329],{},"      threshold: 10240,\n",[46,4331,4333],{"class":48,"line":4332},112,[46,4334,4335],{},"      minRatio: 0.8\n",[46,4337,4339],{"class":48,"line":4338},113,[46,4340,1356],{},[46,4342,4344],{"class":48,"line":4343},114,[46,4345,4346],{},"  )\n",[46,4348,4350],{"class":48,"line":4349},115,[46,4351,593],{},[46,4353,4355],{"class":48,"line":4354},116,[46,4356,4357],{},"if (config.build.bundleAnalyzerReport) {\n",[46,4359,4361],{"class":48,"line":4360},117,[46,4362,4363],{},"  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin\n",[46,4365,4367],{"class":48,"line":4366},118,[46,4368,4369],{},"  webpackConfig.plugins.push(new BundleAnalyzerPlugin())\n",[46,4371,4373],{"class":48,"line":4372},119,[46,4374,593],{},[46,4376,4378],{"class":48,"line":4377},120,[46,4379,4380],{},"module.exports = webpackConfig\n",[28,4382,4384],{"id":4383},"_8-configdevenvjs","8. config\u002Fdev.env.js",[36,4386,4388],{"className":469,"code":4387,"language":471,"meta":41,"style":41},"\u002F\u002F config内的文件是服务于build的\nconst merge = require('webpack-merge')   \u002F\u002F webpack-merge提供了一个合并函数，它将数组和合并对象创建一个新对象,遇到函数，执行它们，将返回的值封装在函数中,这边将dev和prod进行合并\nconst prodEnv = require('.\u002Fprod.env')\nmodule.exports = merge(prodEnv, {\n  NODE_ENV: '\"development\"'\n})\n",[43,4389,4390,4395,4400,4405,4410,4415],{"__ignoreMap":41},[46,4391,4392],{"class":48,"line":49},[46,4393,4394],{},"\u002F\u002F config内的文件是服务于build的\n",[46,4396,4397],{"class":48,"line":67},[46,4398,4399],{},"const merge = require('webpack-merge')   \u002F\u002F webpack-merge提供了一个合并函数，它将数组和合并对象创建一个新对象,遇到函数，执行它们，将返回的值封装在函数中,这边将dev和prod进行合并\n",[46,4401,4402],{"class":48,"line":73},[46,4403,4404],{},"const prodEnv = require('.\u002Fprod.env')\n",[46,4406,4407],{"class":48,"line":130},[46,4408,4409],{},"module.exports = merge(prodEnv, {\n",[46,4411,4412],{"class":48,"line":136},[46,4413,4414],{},"  NODE_ENV: '\"development\"'\n",[46,4416,4417],{"class":48,"line":142},[46,4418,1191],{},[28,4420,4422],{"id":4421},"_9-configindexjs","9. config\u002Findex.js",[36,4424,4426],{"className":469,"code":4425,"language":471,"meta":41,"style":41},"\u002F\u002F 配置文件是用来定义开发环境和生产环境中所需要的参数\nconst path = require('path')\nmodule.exports = {\n  dev: {   \u002F\u002F 开发环境下面的配置\n    assetsSubDirectory: 'static',   \u002F\u002F 子目录，一般存放css,js,image等文件\n    assetsPublicPath: '\u002F',   \u002F\u002F 根目录\n    proxyTable: {},   \u002F\u002F 可利用该属性解决跨域的问题\n    host: 'localhost', \u002F\u002F 服务启动地址\n    port: 8080, \u002F\u002F 服务启动端口\n    autoOpenBrowser: false,   \u002F\u002F 是否自动打开浏览器\n    errorOverlay: true,   \u002F\u002F 浏览器错误提示\n    notifyOnErrors: true,   \u002F\u002F 跨平台错误提示\n    poll: false,  \u002F\u002F 使用文件系统(file system)获取文件改动的通知devServer.watchOptions\n    devtool: 'cheap-module-eval-source-map',   \u002F\u002F 增加调试，该属性为原始源代码（仅限行）不可在生产环境中使用\n    cacheBusting: true,   \u002F\u002F 使缓存失效\n    cssSourceMap: true   \u002F\u002F 代码压缩后进行调bug定位将非常困难，于是引入sourcemap记录压缩前后的位置信息记录，当产生错误时直接定位到未压缩前的位置\n  },\n\n  build: {    \u002F\u002F 生产环境下面的配置\n    index: path.resolve(__dirname, '..\u002Fdist\u002Findex.html'),   \u002F\u002F index编译后生成的位置和名字，根据需要改变后缀，比如index.php\n    assetsRoot: path.resolve(__dirname, '..\u002Fdist'),   \u002F\u002F 编译后存放生成环境代码的位置\n    assetsSubDirectory: 'public\u002Fvue-app\u002Findex',   \u002F\u002F js,css,images等存放文件夹名\n    assetsPublicPath: '\u002F',   \u002F\u002F 发布的根目录为Web容器绝对路径，修改为.\u002F则为相对路径\n    productionSourceMap: true,\n    devtool: '#source-map',\n    productionGzip: false,   \u002F\u002Funit的gzip命令用来压缩文件，gzip模式下需要压缩的文件的扩展名有js和css\n    productionGzipExtensions: ['js', 'css'],\n    bundleAnalyzerReport: process.env.npm_config_report\n  }\n}\n",[43,4427,4428,4433,4437,4441,4446,4451,4456,4461,4466,4471,4476,4481,4486,4491,4496,4501,4506,4510,4514,4519,4524,4529,4534,4539,4544,4549,4554,4559,4564,4568],{"__ignoreMap":41},[46,4429,4430],{"class":48,"line":49},[46,4431,4432],{},"\u002F\u002F 配置文件是用来定义开发环境和生产环境中所需要的参数\n",[46,4434,4435],{"class":48,"line":67},[46,4436,2461],{},[46,4438,4439],{"class":48,"line":73},[46,4440,3071],{},[46,4442,4443],{"class":48,"line":130},[46,4444,4445],{},"  dev: {   \u002F\u002F 开发环境下面的配置\n",[46,4447,4448],{"class":48,"line":136},[46,4449,4450],{},"    assetsSubDirectory: 'static',   \u002F\u002F 子目录，一般存放css,js,image等文件\n",[46,4452,4453],{"class":48,"line":142},[46,4454,4455],{},"    assetsPublicPath: '\u002F',   \u002F\u002F 根目录\n",[46,4457,4458],{"class":48,"line":148},[46,4459,4460],{},"    proxyTable: {},   \u002F\u002F 可利用该属性解决跨域的问题\n",[46,4462,4463],{"class":48,"line":154},[46,4464,4465],{},"    host: 'localhost', \u002F\u002F 服务启动地址\n",[46,4467,4468],{"class":48,"line":160},[46,4469,4470],{},"    port: 8080, \u002F\u002F 服务启动端口\n",[46,4472,4473],{"class":48,"line":166},[46,4474,4475],{},"    autoOpenBrowser: false,   \u002F\u002F 是否自动打开浏览器\n",[46,4477,4478],{"class":48,"line":172},[46,4479,4480],{},"    errorOverlay: true,   \u002F\u002F 浏览器错误提示\n",[46,4482,4483],{"class":48,"line":178},[46,4484,4485],{},"    notifyOnErrors: true,   \u002F\u002F 跨平台错误提示\n",[46,4487,4488],{"class":48,"line":183},[46,4489,4490],{},"    poll: false,  \u002F\u002F 使用文件系统(file system)获取文件改动的通知devServer.watchOptions\n",[46,4492,4493],{"class":48,"line":189},[46,4494,4495],{},"    devtool: 'cheap-module-eval-source-map',   \u002F\u002F 增加调试，该属性为原始源代码（仅限行）不可在生产环境中使用\n",[46,4497,4498],{"class":48,"line":194},[46,4499,4500],{},"    cacheBusting: true,   \u002F\u002F 使缓存失效\n",[46,4502,4503],{"class":48,"line":200},[46,4504,4505],{},"    cssSourceMap: true   \u002F\u002F 代码压缩后进行调bug定位将非常困难，于是引入sourcemap记录压缩前后的位置信息记录，当产生错误时直接定位到未压缩前的位置\n",[46,4507,4508],{"class":48,"line":398},[46,4509,3091],{},[46,4511,4512],{"class":48,"line":404},[46,4513,122],{"emptyLinePlaceholder":121},[46,4515,4516],{"class":48,"line":410},[46,4517,4518],{},"  build: {    \u002F\u002F 生产环境下面的配置\n",[46,4520,4521],{"class":48,"line":416},[46,4522,4523],{},"    index: path.resolve(__dirname, '..\u002Fdist\u002Findex.html'),   \u002F\u002F index编译后生成的位置和名字，根据需要改变后缀，比如index.php\n",[46,4525,4526],{"class":48,"line":422},[46,4527,4528],{},"    assetsRoot: path.resolve(__dirname, '..\u002Fdist'),   \u002F\u002F 编译后存放生成环境代码的位置\n",[46,4530,4531],{"class":48,"line":428},[46,4532,4533],{},"    assetsSubDirectory: 'public\u002Fvue-app\u002Findex',   \u002F\u002F js,css,images等存放文件夹名\n",[46,4535,4536],{"class":48,"line":434},[46,4537,4538],{},"    assetsPublicPath: '\u002F',   \u002F\u002F 发布的根目录为Web容器绝对路径，修改为.\u002F则为相对路径\n",[46,4540,4541],{"class":48,"line":440},[46,4542,4543],{},"    productionSourceMap: true,\n",[46,4545,4546],{"class":48,"line":446},[46,4547,4548],{},"    devtool: '#source-map',\n",[46,4550,4551],{"class":48,"line":1142},[46,4552,4553],{},"    productionGzip: false,   \u002F\u002Funit的gzip命令用来压缩文件，gzip模式下需要压缩的文件的扩展名有js和css\n",[46,4555,4556],{"class":48,"line":1148},[46,4557,4558],{},"    productionGzipExtensions: ['js', 'css'],\n",[46,4560,4561],{"class":48,"line":1154},[46,4562,4563],{},"    bundleAnalyzerReport: process.env.npm_config_report\n",[46,4565,4566],{"class":48,"line":1160},[46,4567,1371],{},[46,4569,4570],{"class":48,"line":1166},[46,4571,593],{},[28,4573,4575],{"id":4574},"_10-configprodenvjs","10. config\u002Fprod.env.js",[36,4577,4579],{"className":469,"code":4578,"language":471,"meta":41,"style":41},"\u002F\u002F 发布时调用prod.env.js的生产环境配置\nmodule.exports = {\n  NODE_ENV: '\"production\"'\n}\n",[43,4580,4581,4586,4590,4595],{"__ignoreMap":41},[46,4582,4583],{"class":48,"line":49},[46,4584,4585],{},"\u002F\u002F 发布时调用prod.env.js的生产环境配置\n",[46,4587,4588],{"class":48,"line":67},[46,4589,3071],{},[46,4591,4592],{"class":48,"line":73},[46,4593,4594],{},"  NODE_ENV: '\"production\"'\n",[46,4596,4597],{"class":48,"line":130},[46,4598,593],{},[28,4600,4602],{"id":4601},"_11-配置代理解决跨域问题","11. 配置代理解决跨域问题",[36,4604,4606],{"className":469,"code":4605,"language":471,"meta":41,"style":41},"\u002F\u002F 在 config\u002Findex.js 中的 proxyTable 配置\nproxyTable: {\n  '\u002F':{\n    target: \"http:\u002F\u002Fwww.xxx.com\",   \u002F\u002F 要访问的地址\n    changeOrigin: true   \u002F\u002F 开启跨域\n  }\n}\n\u002F\u002F 配置理解为将访问 \u002F 代理为 http:\u002F\u002Fwww.xxx.com 这样就不会触发跨域问题，即不会被浏览器拦截请求\n\u002F\u002F 在Vue的请求中要访问 http:\u002F\u002Fwww.xxx.com\u002FtestData 接口直接写成对 \u002FtestData 请求即可\n\u002F\u002F 通过 process.env.NODE_ENV 判断开发环境与生产环境区别请求 Url\n",[43,4607,4608,4613,4618,4623,4628,4633,4637,4641,4646,4651],{"__ignoreMap":41},[46,4609,4610],{"class":48,"line":49},[46,4611,4612],{},"\u002F\u002F 在 config\u002Findex.js 中的 proxyTable 配置\n",[46,4614,4615],{"class":48,"line":67},[46,4616,4617],{},"proxyTable: {\n",[46,4619,4620],{"class":48,"line":73},[46,4621,4622],{},"  '\u002F':{\n",[46,4624,4625],{"class":48,"line":130},[46,4626,4627],{},"    target: \"http:\u002F\u002Fwww.xxx.com\",   \u002F\u002F 要访问的地址\n",[46,4629,4630],{"class":48,"line":136},[46,4631,4632],{},"    changeOrigin: true   \u002F\u002F 开启跨域\n",[46,4634,4635],{"class":48,"line":142},[46,4636,1371],{},[46,4638,4639],{"class":48,"line":148},[46,4640,593],{},[46,4642,4643],{"class":48,"line":154},[46,4644,4645],{},"\u002F\u002F 配置理解为将访问 \u002F 代理为 http:\u002F\u002Fwww.xxx.com 这样就不会触发跨域问题，即不会被浏览器拦截请求\n",[46,4647,4648],{"class":48,"line":160},[46,4649,4650],{},"\u002F\u002F 在Vue的请求中要访问 http:\u002F\u002Fwww.xxx.com\u002FtestData 接口直接写成对 \u002FtestData 请求即可\n",[46,4652,4653],{"class":48,"line":166},[46,4654,4655],{},"\u002F\u002F 通过 process.env.NODE_ENV 判断开发环境与生产环境区别请求 Url\n",[4657,4658,4659],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":41,"searchDepth":67,"depth":67,"links":4661},[4662,4666,4674,4679,4685,4691],{"id":25,"depth":67,"text":26,"children":4663},[4664,4665],{"id":30,"depth":73,"text":31},{"id":102,"depth":73,"text":103},{"id":305,"depth":67,"text":306,"children":4667},[4668,4669,4670,4671,4672,4673],{"id":309,"depth":73,"text":310},{"id":452,"depth":73,"text":453},{"id":462,"depth":73,"text":463},{"id":608,"depth":73,"text":609},{"id":661,"depth":73,"text":662},{"id":705,"depth":73,"text":706},{"id":753,"depth":67,"text":754,"children":4675},[4676,4677,4678],{"id":757,"depth":73,"text":758},{"id":764,"depth":73,"text":765},{"id":942,"depth":73,"text":943},{"id":1009,"depth":67,"text":1010,"children":4680},[4681,4682,4683,4684],{"id":1013,"depth":73,"text":1014},{"id":1194,"depth":73,"text":1195},{"id":1302,"depth":73,"text":1303},{"id":1322,"depth":73,"text":1323},{"id":1378,"depth":67,"text":1379,"children":4686},[4687,4688,4689,4690],{"id":1382,"depth":73,"text":1383},{"id":1459,"depth":73,"text":1460},{"id":1629,"depth":73,"text":1630},{"id":1822,"depth":73,"text":1823},{"id":2152,"depth":67,"text":2153,"children":4692},[4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703],{"id":2156,"depth":73,"text":2157},{"id":2306,"depth":73,"text":2307},{"id":2445,"depth":73,"text":2446},{"id":2895,"depth":73,"text":2896},{"id":3011,"depth":73,"text":3012},{"id":3359,"depth":73,"text":3360},{"id":3779,"depth":73,"text":3780},{"id":4383,"depth":73,"text":4384},{"id":4421,"depth":73,"text":4422},{"id":4574,"depth":73,"text":4575},{"id":4601,"depth":73,"text":4602},"@TOC","md",{},"\u002Fvue\u002Fvue学习笔记",{"title":5,"description":4704},"Vue\u002FVue学习笔记","9YYI0VTiSd3FnwAPcMh0m-sNx-A4agKTwt3jtzVaIQ8",1791042470696]