官网配置参考
每次在终端运行 vue-cli-service
时,都会先找到对应的 vue.config.js,获取到相关配置,才继续执行其它操作
1 | module.exports = { |
拓展:
官网配置参考
每次在终端运行 vue-cli-service
时,都会先找到对应的 vue.config.js,获取到相关配置,才继续执行其它操作
1 | module.exports = { |
拓展:
提到 vue-cli,官方文档对其的介绍如下:
A simple CLI for scaffolding Vue.js projects. 一个简单的Vue.js工程命令行脚手架工具。
说白了,vue-cli
其实就是一个基于webpack
构建,可以让用户快速初始化一个项目的工具。
基本原理: vue-cli
并非从无到有地凭空生成一个项目,而是通过下载/拉取(通过download-git-repo
工具)已有的工程到本地,完成生成项目的工作。
- 注意安装
vue-cli 3
前,如若已安装旧版本vue-cli
,需先卸载旧版本vue-cli
,再重新安装vue-cli 3node
版本要求: 安装 Node.js8.9 或更高版本
这次我分享的主要主要内容是 vue-cli 3
,当然不是全面的介绍,只是将我这次运营系统工作流改造中遇到比较深刻的点进行一番简单介绍
而对于根据我个人对vue-cli 3
的认识,我将需掌握的内容概括为四个部分:Vue.config.js
、Vue-cli-service
、插件
、UI
。
下面这张图是我对vue-cli 3 知识点进行了一个简单的概括
比较常接触到vue
一些基本的命令,比如说:
vue
文件)快速启动一个服务(要求全局安装@vue/cli-service-global
)Vue.config.js
我觉得对于一个普通的项目的工作流构建来说,配置vue.config.js
足够了
而里面比较特别和常用的主要是以下这些:除了 publicPath
、 outputDir
、 filenameHashing
、 pages
等这些常用字段外,我觉得还需要提一下的是 configureWebpack
字段和 chainWebpack
字段
我对这两个字段的理解是
webpack-merge
将原有对象和用户配置的对象进行合并webpack-chain
提供的链式调用方法去直接修改原有的配置对象对于
vue-cli 3
来说,它还存在一个比较特别的模块,就是它提供了自定义插件的功能
说到vue-cli 3
的插件,其实可以将其分为两种情况:
一种是vue-cli
插件,这种情况一般是对外的,主要是开发一些npm
包,并将其发布到npm
上;
另一种就是service 插件
, 也就是我这次工作流改造中用到的主要内容,其主要包括內建命令和配置模块,而这两部分的内容都是在调用vue-cli-service
命令时才会触发;因此,使用到service
插件的用户,需要安装一下vue-cli-service
。
Generator
和Prompts
):为@vue/cli
项目添加额外特性的 npm 包Service
实例被创建时自动加载——比如每次vue-cli-service
命令在项目中被调用时。
- 內建命令
该功能的实现主要是调用了
api.registerCommand
这个方法向vue-cli-service内部注入额外的命令,vue-cli 3
提供的vue-cli-service serve
和vue-cli-service build
等命令的实现也是利用了这个方法。- 配置模块
该功能的实现则是利用的
api.chainWebpack
和api.configureWebpack
方法对webpack
配置进行修改。- 注:稍后我会在文章的下面给出一个自定义命令的 demo
1 | // 可以通过下面这个命令查看所有命令,从而确认自定义的命令是否创建成功 |
然后接下来看一看具体实操例子
watch
和build
命令,并满足以下功能--key
命令读取.json
文件中的key
来进行构建,并支持多个key
.json
配置文件,可以指定entry
路径和output
路径需求示例:
1 | # watch 监听某个入口的文件变动并编译 |
这对第三点,假设项目根目录下有 Views.json
文件,形如:
1 | { |
然而我为什么没有直接使用
vue-cli-service
提供的serve
和build
命令呢?原因如下:
对于watch
和build
命令,其实他们除了要求具备vue-cli-service
提供的serve
和build
命令效果外,还得让用户通过--key
传入打包入口,而vue-cli-service
提供的这些命令是其内部写好了的,我们无法对其内部进行修改,所以为了实现这个需求,我们需要进行自定义命令。
解决方式:
要实现 watch
和 build
功能,其实在 vue-cli 3
中 vue-cli-service
有提供了相对应的 api
给用户进行调用,也就是注册自定义的命令,实际上就是向 vue-cli-service
注入额外的命令。
以注册watch
命令为例,做一个小demo
:
新建一个项目
1 | // 首先进行 vue-cli 安装 |
针对已有项目使用 vue-cli-service
安装vue-cli-service
:
1 | // 进行 vue-cli-service 安装 |
在package.json
中的vuePlugins
对象中的service
字段引入相应的js文件(用于注册watch 命令
的文件, 假设该文件名为:vue-cli-plugin-watch.js
,并放在根目录)
1 | // package.json 中 |
vue-cli-plugin-watch.js
代码如下
1 | module.exports = (api, projectOptions) => { |
在终端输入npm run watch
,看到终端输出“watch
命令注册成功”后,恭喜watch
命令基本注册完成啦。
可以通过运行npx vue-cli-service help
查看vue-cli-service下面的所有命令,可以看到新增加了一个watch
命令
vue.config.js
中的pluginOptions
向插件进行传参数在项目根目录创建vue.config.js
文件
1 | // vue.config.js相关代码 |
修改vue-cli-plugin-watch.js
代码如下
1 | module.exports = (api, projectOptions) => { |
运行
npm run watch
命令,可见终端输出了‘传参数给內建插件’,即通过vue-config.js传参成功
运行npm run watch
命令,可见终端输出了‘传参数给內建插件’,即传参成功
其实再去看看build
命令的实现源码,其实和上面watch的实现是差不多的
Vue-cli-service build 命令源码
注册命令后,就可以通过调用 api.resolveWebpackConfig() 取回解析好的 webpack 配置。每次调用都会新生成一个 webpack 配置用来在需要时进一步修改。
1 | module.exports = api => { |
也可以通过调用 api.resolveChainableWebpackConfig() 获得一个新生成的链式配置
1 | api.registerCommand('my-build', args => { |
再看回operation的项目需求,要求实现
watch
和build
,watch
实现还好说,但是考虑到直接使用vue-cli-service
的内建命令模块实现build
会将其原有的命令进行覆盖,这种操作不太理想,所以改用了另外一种实现方式:使用commander
实现注册命令。
watch
主要实现代码如下:
demo
具体步骤:
script
文件夹,在该文件夹目录下新建一个用于实现注册命令的js文件,我在这创建的文件名为commandar-watch.js
1 | // 安装 Commander |
1 | // commandar-watch 具体实现代码 |
在package.json
文件中scripts
的watch
中,使用node
执行commandar-watch.js
的watch
命令
1 | { |
在终端执行npm run watch
命令,看到终端输出‘watch 命令注册成功’后,恭喜watch
命令注册成功啦。当然,你也可以传入--key
的值,如:npm run watch --key=用户传的key值
,可见到终端输出‘用户传的key值’,证明已经获取到用户传的参数啦。
其实这两个命令主要用到的配置还是Vue-cli 3提供的基本配置,在再次基础上针对不同页面特别设置一些配置,比如说针对某些页面需要进行css提取,还有不同页面设置不同的entry
和output
等等。而着这两个命令的主要区别就是Watch 字段、不同mode;对于是否压缩打包,我通过设置不同的环境模式从而设置文件是否需要打包(webpack 4提供了这个功能);至于是否需要监听文件的改变功能的实现,我借鉴了vue-cli-service build
命令的--watch
实现方式。
vue-cli-service build –watch ,核心代码 是获取webpack 配置,并将配置对象的watch字段的值设置为true。
注:
vue-cli-service
中的build
命令--watch
的实现源码地址
主要用来放置一些无需经过webpack处理的静态资源或模板等等。其目录下的内容会被直接拷贝到构建输出目录下
关于存在原因:index.html模板,动态引入图片,引入不兼容模块
实现源码
审查 vue-cli 项目的 webpack 配置,可以很方便将查看使用 vue-cli 3
配置后,其具体的 webpack
配置
针对这次分享的内容,虽然说我侧重分享了插件部分的内容,但是并不意味着vue-cli 3
内容只有这些,只是我这次开发中遇到比较多的模块就是service
插件这一块,所以就特别提了一下,它还有其他的内容比如说ui那一块等等;
体会:
在开发过程中,当遇到,对api不熟悉,造成无法很好的运用好某些api
的情况时,其实可以考虑去研究研究一下源码,会发现事情变得简单,其实在vue-cli
的官网里面也有提到配合源码去学习api
,这才能真正灵活的使用对应的功能等等。
在这个项目里面,我就是在一边学习一边实现需求。还有,考虑问题要全方面的想,多测试一些页面。比如说npm
与yarn
在终端中的传参方式不一样,导致代码中获取的key
值方式也不一样这个问题,就是得多测试才会发现。还有要多请教一些前辈,你会发现有时候经验对于开发方式和开发效率来说,真的很重要。
参考文章:
拓展文章:
笔记简单整理如下:
(1)node 版本要求:8.9或更高版本
(2)如若已安装旧版本vue-cli ,则将其卸载,重新安装@vue-cli
1 |
|
1 | vue --version |
(1)快速构建命令 vue serve 和 vue build
前提:全局安装 @vue/cli-service-global 依赖
1 | npm install -g @vue/cli-service-global |
(2)vue serve 命令的选项
1 | Usage: serve [options] [entry] |
(3)vue build 命令选项:
1 | Usage: build [options] [entry] |
(4)快速创建一个项目命令
1 | vue create |
(1)vue-cli-service serve 启动一个开发服务器并附带开箱即用的模块热加载
(可通过 devServer 配置开发服务器 )
1 | 用法:vue-cli-service serve [options] [entry] |
(2)vue-cli-service build
( 在输出目录产生一个生产环境的包 ,自动进行代码压缩,vendor chunk splitting,内联chunk manifest 在 HTML 里。 )
1 | 用法:vue-cli-service build [options] [entry|pattern] |
(3)vue-cli-service inspect
(审查 vue-cli 项目的 webpack 配置)
1 | 用法:vue-cli-service inspect [options] [...paths] |
1 | npx vue-cli-service help |
(1)cache-loader:会默认为 Vue/Babel/TypeScript 编译开启。文件会缓存在 node_modules/.cache 中
注:如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
(2)thread-loader
(1)browserslist(指定了项目的目标浏览器的范围)
(2)ployfill
(3)现代模式
(1)index 文件
public/index.html 文件是一个会被 html-webpack-plugin 处理的模板。在构建过程中,资源链接会被自动注入
不生成index:
1 | // vue.config.js |
(2)插值
(3)preload
指定页面加载后很快会被用到的资源,通过 @vue/preload-webpack-plugin 进行注入
(4)Prefetch
是一种 resource hint,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。通过 @vue/preload-webpack-plugin 进行注入
(5)构建一个多页应用
(6)处理静态资源
静态资源处理方式
从相对路径导入
URL转换规则
public 文件夹(不推荐,只是应急手段)
任何放置在 public 文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。
通过webpack 处理的好处:
最终生成的文件名包含了内容哈希,因此你不必担心浏览器会缓存它们的老版本
何时使用
public
文件夹
<script>
标签引入。css
相关(1)引用静态资源
所有编译后的 CSS
都会通过 css-loader
来解析其中的 url() 引用,并将这些引用作为模块请求来处理
(2)预处理器
(3)自动化导入
如自动化导入文件(用于颜色、变量、mixin……),你可以使用style-resources-loader
(4)postCss
(5)css Modules
通过< style module > 以开箱即用的方式在.vue文件里面使用
JavaScript 中作为 CSS Modules
导入CSS
或其它预处理文件,该文件应该以 .module.(css/|less/|sass/|scss/|styl)
结尾(设置 vue.config.js
中的 css.modules
为 true
:导入文件时,文件名无需带上.module
; 同时,即使构建时,import
的文件为css
文件,但也会将其当做 css Modules
来打包)
关于 css Modules
模块的类名
默认的css Modules
模块的类名
自定义生成的css Modules 模块的类名
1 | // 可以通过 vue.config.js中的 css.loaderOptions.css 选项来实现 |
提示: 这样做比使用 chainWebpack 手动指定 loader 更推荐,因为这些选项需要应用在使用了相应 loader 的多个地方。
1 | // vue.config.js |
爬虫和标注系统就是利用这个方式实现scss文件全局使用
(1)简单的配置方式
调整webpack 配置的最简单的方式是修改vue.config.js
中的 configureWebpack
选项提供一个对象,该对象将会被 webpack-merge
合并入最终的 webpack
配置
1 | // vue.config.js |
警告: 有些
webpack
选项是基于vue.config.js
中的值设置的,所以不能直接修改。例如你应该修改vue.config.js
中的outputDir
选项而不是修改output.path
;你应该修改vue.config.js
中的publicPath
选项而不是修改output.publicPath
。这样做是因为vue.config.js
中的值会被用在配置里的多个地方,以确保所有的部分都能正常工作在一起
1 | // 基于环境有条件的配置行为 |
(2)链式操作
(高级,利用 webpack-chain
在 vue.config.js
中的 chainWebpack
进行相应修改,配合vue inspect
比较方便查看对应操作方式)
Loader
选项1 | // vue.config.js |
Loader
Loader
webpack-chain阅读一些源码
1 | // 将其输出重定向到一个文件(被格式化,非有效的webpack 配置文件)以便进行查阅 |
(1).env
.env 文件知识点补充:
该文件中定义的变量,构建过程中,会被注入到process.env
中 ,成为该对象的一个属性;但是针对于浏览器这里没有node
环境情况下,在 process.env
中的字段会被当做是一个全局变量,因此,在所有的页面中都可以获取到该字段的值
1 | // 可以替换项目根目录中的下列文件来指定环境变量 |
补充:
.env.production
) > 一般环境文件(如:.env
)Vue CLI
启动时已经存在的环境变量 > .env
文件。NODE_ENV
,你应该移除它或在运行 vue-cli-service
命令的时候明确地设置 NODE_ENV
。(2)模式
(3)在客户端侧代码中使用环境变量(在代码中始终可用的三种变量)
VUE_APP_
开头的变量会被webpack.DefinePlugin
静态嵌入到客户端侧的包中NODE_ENV
- 会是 "development"
、"production"
或 "test"
中的一个。具体的值取决于应用运行的模式。BASE_URL
- 会和 vue.config.js
中的 publicPath
选项相符,即你的应用会部署到的基础路径。补充:所有解析出来的环境变量都可以在
public/index.html
中以HTML
插值中介绍的方式使用。
(4)只有在本地有效的变量
文件名为:.env.local
可在此基础上指定模式: .env.development.local
6.构建目标
(1)应用
(2)库
(3)Web Component 组件
其他总结:
原文:编译环境中的几种传参方法
1 | "script": { "dev": "echo $1" // ${1} 也可以} |
1 | npm run dev -- hello |
1 | hello |
1 | "script": { "dev": "webpack"} |
1 | console.log('自定义参数:', process.argv); |
1 | npm run dev -- hello |
1 | 自定义参数:PROJECTDIR: [ '/usr/local/bin/node', '/Users/xxx/Desktop/git/webpack-practise/node_modules/.bin/webpack', ‘hello' ] |
1 | console.log('自定义参数:', process.env.test); |
1 | test=hello npm run dev |
1 | 自定义参数:hello |
1 | console.log('自定义参数:', process.env.npm_config_test); |
1 | npm run dev --test=hello |
1 | 自定义参数:hello |
元素先按照正常流定位,当元素滚动到设定的阈值时,元素的显示效果会变成position:fixed效果相同
position: sticky;
top: 20px; //元素滚动到距离顶部为20px时,停止滚动(效果类似position: fixed; top: 20px;)
兼容性:
事件:文档或浏览器窗口中发生特定交互瞬间
事件流:描述从浏览器中接收事件的顺序
IE的事件流:事件冒泡流
Netscape Communicator的事件流:事件捕获流
注:不是所有事件都支持冒泡事件;比如:鼠标事件(mouserleave, mouseenter等),焦点事件(blur, focus等),UI事件(load, unload, abort, error, scroll, resize等)
阻止事件冒泡的方式:(1)event.stopPropagation(); (2)低版本IE取消冒泡:event.cancelBubble(); (3)return false;
注:第三种阻止方式,在取消事件冒泡事件的同时,也阻止了浏览器默认事件(event.preventDefault(); 低版本IE:window.event.returnValue = false; )
其用意:在事件到达预订目标事件之前捕获它
包括三个阶段:事件捕获阶段->处于目标阶段(事件源target)->事件冒泡阶段
注: event.target 取到触发事件的源头;event.currentTarget 取到当前绑定事件的元素;
eg:
1 | <div id = "" onclick = "function() {}"></div> |
缺点:
- 存在时差问题:有可能要调用的函数还没有加载完,用户就触发事件,从而导致错误
- js与html代码紧密耦合:修改代码时很麻烦
eg:
1 | obj.onclick = function() { |
注:删除事件直接将处理事件的值设置为null; obj.onclick=null;
该方法接受的参数:要处理的事件名(不带on开头)、作为事件处理程序的函数和一个布尔值
布尔值表示:
- true:表示在事件捕获阶段调用事件处理程序;
- false:表示在事件冒泡阶段调用事件处理程序;
eg:
1 | obj.addEventListener("click", function() { |
- 优势:可以添加多个事件处理程序,事件触发顺序从上往下执行
- 删除事件:使用removeEventListener(), 传入与添加时相同的参数
- 注意:匿名函数无法移除
attachEvent()添加、detachEvent()移除
参数:事件处理程序名称(带on开头)和事件处理程序函数
eg:
1 | obj.attachEvent("onclick", function() { |
- 与DOM0级方法的区别:this的作用域不一样
- 在DOM0中:事件处理程序会在其所属元素的作用域内运行
- 在attachEvent()方法内:事件处理程序在全局作用域运行,this等于window
- 当绑定多个事件时,事件触发顺序从下往上执行
跨浏览器的事件处理程序,为保证处理事件的代码在不同浏览器下一致执行,只需关注冒泡阶段,可通过封装一个对象,进行方法调用。
参考书籍:
- 《javaScript 高级程序设计》
前天刚做完一个公司的校招笔试题,其中有考到数组的基础方法,故今天在此对其做一番总结,从而温故而知新。
1 |
|
1 |
|
注:两种创建方式的区别
- 通过’[]’是直接告诉处理器创建一个新的运行时数组,无需进行其他处理
- 通过new Array()是让解释器直接查找执行上下文,找到构造函数,并调用它,从而生成数组对象。
- 推荐使用’[]’
分两类:根据是否对原数组产生影响
1 |
|
1 |
|
html模板:
1 |
|
声明:以下示例,主要实现垂直居中的样式代码为加粗的部分
可设置该行内元素的父元素的height与line-heigth的值相等,让行内元素垂直居中
针对行内元素,可通过设置vertical-align: middle;以及line-height进行垂直居中
1 |
|
1 |
|
1 | .content{ |
1 |
|
原理:通过在要进行垂直居中的元素a前面添加一个无内容的元素,并将该无内容元素的高设置为50%,在利用clear:botn清除浮动,则元素a相对于父元素来说是垂直居中。
html如下:
1 | <div class="parent"> |
css如下:
1 |
|
设置position:absolute;和transform:traslate(x,y)实现水平垂直居中
1 | .content{ |
居于视口单位的解决方案:
可通过使用margin-top: 50vh;配合transform:translateY(-50%);实现视口居中
1 |
|
1 | .parent{ |
1 | .parent{ |
1 |
|
1 |
|
原理:
- 元素如果不设置宽度,则默认继承父元素宽度
- overflow:hidden; 清除左边元素浮动
- 右边元素未设置宽度,则宽度=父元素宽度-左边元素宽度;
BFC原理:因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。
1 |
|
1 |
|
1 | .left{ |
1 | .left{ |
1 | .parent{ |
原理:display:table-cell具有以下特性:
- text-algin,vertical-algin等对齐属性起作用,margin以及宽高百分比值不起作用
会生成虚拟的table,tr包裹住自己,当存在相邻兄弟元素也被设置为table-cell时,则生成虚拟table,tr将其与兄弟元素包裹在一起,并一行等高显示
多个table-cell属性的元素会占忙被设置成display:table的元素的宽度;- 当其中一个元素已设置宽度时,其他元素(被设为table-cell)会占满剩下的宽度;
- 如果只有一个table-cell元素,就算设置了宽度也会占满table元素的宽度;
- 对设置了float、absolute的元素不起作用。且IE6、7不支持
1 | .parent{ |
1 | text-align:center; |
常用(前提:已设置width值):margin-left:auto; margin-right:auto;
固定宽度块级元素水平居中,通过使用绝对定位,以及设置元素margin-left为其宽度的一半
1 | .content{ |
1 | .content{ |
使用table标签(或直接将块级元素设值为display:table),再通过给该标签添加左右margin为auto
display:inline-block;(或display:inline)和text-align:center;实现水平居中
存在问题:需额外处理inline-block的浏览器兼容性(解决inline-block元素的空白间距)
绝对定位+transform,translateX可以移动本省元素的50%
1 | .content{ |
用float或者display把父元素变成行内块状元素
1 | .contentParent{ |
1 | .contentParent{ |
1 | .contentParent{ |
1 | .content{ |