基于 vue 的移动端组件库调研结果

vue 移动端组件库调研

注:该文章相关信息截止至2019.10.10

前言

  为了更好地展开移动端项目的开发工作,部门打算开发一个移动端组件库。而要要将自己的移动端组件库开发好,就得先选择一个基于 vue 并且合适的移动端组件库作为基础组件库,所以有了下文的调研和分析。

一、现有 vue 相关组件库基本分析

1. vonic (v1.1.3)

预览 star: 3261; 用户量:218
一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用。

1
2
优势:包含比较全面的组件/服务/指令
劣势:最近更新时间是8个月前,用户量和讨论不是很多,活跃度不高

2. vux (v2.9.4)

预览 star:16337 用户量:9012

1
2
3
4
5
6
7
8
9
10
11
12
13
14
特点:
1.个人维护
2.支持 Nuxt.js
3.支持自定义主题
4.组件样式仿照微信
5.适合微信端移动项目

优势:组件全面,用户量多,讨论活跃度还OK

劣势:
1. 必须配合 vux-loader 使用
2. less@3.x 有严重的兼容问题,请暂时使用 less@^2.7.3
3. 暂未适配 vue-cli@3.x
4. 不推荐使用 umd 方式引用组件

3. Mint UI

预览 github star: 14968 用户量:24931
饿了么前端团队开发的移动端组件库。

1
2
3
4
5
6
7
8
9
10
11
12
13
项目特点

1.团队维护
2.真正做到了按需引入,每个组件有单独的包
3.CSS3 处理各种动效
4.组件齐全
5.适用于移动端常规项目

样式: scss、template、script、css 都在一个文件中,长类名区分

优点:用户量多

劣势:两年多项目和文档都没有更新了,有不少bug,用户反馈的很对问题也没有解决,感觉有点凉,不太敢用

4. MUI

github star: 12077 用户量:495

1
2
3
4
5
6
7
8
9
项目特点:
1.轻量:追求性能体验,MUI不依赖任何第三方JS库,压缩后的JS和CSS文件仅有100+K和60+K。
2.原生UI:以iOS平台UI为基础,补充部分Android平台特有的UI控件
3.流畅体验:各种动画实现。

优势:
1. 有自己的讨论社区(https://ask.dcloud.net.cn/explore/sort_type-new__category-3__day-0),活跃度挺好的

劣势: 一年没有更新了,很多issues 都没有被解决

5. Muse-ui (V3.0.2)

github star: 7714 用户量:4106

1
2
3
4
项目特点:
1.组件丰富:40多个UI 组件,用于适应不同业务环境。
2.可定制:自定义主题方式极为优雅,仅需少量代码即可完成主题样式替换。
3.基于 Vue 2.0:是当下最快的前端框架之一,小巧,api友好,可用于开发的复杂单页应用

6. vant

github star: 10573 用户量:8590
有赞团队开发的移动端组件库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
项目特点;
1.团队维护
2.有多个版本:小程序 UI => Vant Weapp、PC 端 React UI => Zen
3.支持 SSR
4.常规支持:多语言、自定义主题、按需引入
5.文档详细,组件齐全
6.适用于移动端商城购物类网站
7.60+ 高质量组件
8.95% 单元测试覆盖率
9.完善的中英文文档和示例
10.支持按需引入、主题定制、国际化
11.支持 TS 、SSR

优势: 至今一直有人维护,用户量多,社区活跃度高,支持vue-cli3

7. Cube UI

github star:7095 用户量:1855
滴滴团队开发的移动端组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1.团队维护
2.支持后编译
3.常规支持:多语言、自定义主题、按需引入
4.文档详细,组件齐全
5.扩展性强,可以方便地基于现有组件实现二次开发
6.适合移动端需要扩展的项目,或者引用框架部分源代码组合成自己的 ui 组件库

样式:scss、BEM 类名命名法

优势:
1. 支持vue-cli 3
2. 维护积极,直到目前一直有人在更新

劣势:用户量偏少

8. NutUI (V2.1.5)

预览 star: 1346 使用量:69
NutUI是一套京东风格的移动端Vue组件库,开发和服务于移动Web界面的企业级前中后台产品。于2018.01发布。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
项目特性:
1. 跨平台,自动转微信小程序组件(稍后上线,敬请期待)
2. 30+ 京东移动端项目正在使用
3. 基于京东APP 7.0 视觉规范
4. 支持按需加载
5. 详尽的文档和示例
6. 支持定制主题
7. 支持多语言(国际化)
8. 支持 TypeScript
9. 支持服务端渲染(Vue SSR)
10. 单元测试加持
11. 配套有基于Webpack的构建工具,可快速创建已内置本组件库的Vue工程

支持环境
1. Android 4.0+
2. iOS 8.0+
3. 支持服务端渲染

优势:组件很全面,最近更新时间是3个月前

劣势:用户量偏少,目前主要是京东内部项目在使用。

9. vue-carbon

预览
已停止维护,迁移到muse-ui

10. vum

预览 github

1
已经两年没更新,较少用户量,缺少文档

11. Weex

GitHub
兼容多端的库

二、github 数据(至2019.09.22)

组件库 star 仓库使用量 watch 最近更新时间 issue
vonic 3261 218 500 8个月前 62/124
vux 16337 9012 717 5个月前 705/2438
Mint UI 14968 24931 500 2年前 230/972
MUI 12077 495 905 一年前 309/117
Muse-ui 7714 4106 290 6个月前 125/1146
vant 10573 8590 297 今天 14/2647
Cube UI 7095 1855 203 5天前 26/447
NutUI 1346 69 62 2月前 80/65
Weex-UI 4614 531 182 4天前 7/355

三、结合组件库调研结果,抽取以下几个组件库进行进行详细分析

选择的组件库包含: Mint UI/Vux/Muse-ui/vant/Cube-ui/

1. 功能是否全面(需求契合度,多样性等,满分10分)

  • Mint-UI: 缺少对话框,卡片,容器组件,包含三大类组件(JS components, css components, form components),即29种小组件。(7分,扣在缺少部分组件)
  • Vux: 功能比较全面,包含11大类工具或组件(2个样式解决方案,一个新指令,7个工具函数,一个数据展示组件,2种图标展示方式,13种弹窗提示组件,5种导航组件,14种数据展示组件,29种表单组件,5种布局,3种基础组件)。(10分)
  • Muse-Ui: 组件超酷(个人很喜欢),组件风格可拓展(颜色,主题,icon,字体,布局),包含3种工具(过渡动画,4个指令,点击效果),5种插件,33种组件。(8分,扣在组件过于炫酷,不太符合已有需求的交互样式,使用后可能会增加工作量)。
  • Vant: 功能比较全面,也比较通用,比容易拓展。包含5种基础组件,14种表单组件,9种反馈组件,15种展示组件,8种导航组件,9种业务组件。(10分)
  • Cube-Ui: 组件缺少顶部菜单,组件多样性偏少。包含5种基础组件,12种表单组件,11种弹出层相关组件,8种滚动相关的组件(5分)

2. 是否易于拓展

  • Mint-UI: 不支持国际化和主题定制,拓展性一般(主要是文档不够完善)(5分)
  • Vux: 不支持vue-cli3,必须配合 vux-loader 使用,less@3.x 有严重的兼容问题,文档很详细(存在什么坑以及对应解决方案,全部有给出),支持国际化(要装一个插件),支持主题颜色配置。(7分)
  • Muse-Ui: 未说明是否支持国际化或主题定制(5分)
  • Vant: 支持vue-cli3支持主题定制,颜色定制(进行样式变量的覆盖),支持国际化(多语言切换,修改默认文案),提供了一定的示例工程和适配方案。(10分)
  • Cube-Ui: 支持国际化,支持基于现有组件实现二次开发,使用后编译,编译时间缩短,支持主题定制。(9分)

3. 是否稳定,bug数量(参考GitHub issuse内容)

  • Mint-UI: 未解决issuse超200个,未解决bug偏多(5分)
  • Vux: 对话框样式有bug,708个issuse未被解决,bug有点偏多,不过作者有打算重新回来维护(6分)
  • Muse-Ui: 未解决issuse 127个 (7分)
  • Vant: 还有20个issuse在等待解决,问题解决速度很快(10分)
  • Cube-Ui: 还有30个左右的issuse未解决,解决问题速度挺好的(10分)

4. 是否依旧维护

  • Mint-UI: 未解决issuse超200个,未解决bug偏多,2两年多没有维护和更新了,凉得不行(5分)

  • Vux: 已恢复正常维护和更新,个人维护,最近一次更新为5个月前(8分,但是由于是个人维护,感觉不够靠谱,扣一些分)

  • Muse-Ui: 最近一次更新时间是7个月前 (7分)

  • Vant: 几乎每天都有在维护和更新,维护很勤快(10分)

    1
    2
    3
    4
    5
    6
    vant 发布节奏:
    修订号:每周发布,包含新特性和问题修复。
    次版本号:每隔一至二个月发布,包含新特性和较大的功能更新,向下兼容。
    主版本号:发布时间不定,包含不兼容更新,预计下一个主版本会与 Vue 3.0 同期发布。

    补充:文档信息很完善
  • Cube-Ui:最近一个月有进行更新维护(9分)

5. 仓库使用量

  • Mint-UI: 24931(10分,好像是出现的比较早)
  • Vux: 9012(9分)
  • Muse-Ui: 4106(7分)
  • Vant: 8590(现在好像变为9000多了,增长速度很快)(9分)
  • Cube-Ui: 1855(4分)

6. 综上5个方面,得出总体评分如下:

总的来说 ==》移动端基础组件库有赞vant完胜

其实感觉只有这个库比较合适了,其他库要不维护积极性偏低,或用户量偏少,要不就是不利于拓展,没得选…

参考文章

阅读全文
outline 与 clip 实现自动填满屏幕剩余空间的应用技巧 -- 解决页面底部留白问题
css | outline | clip

场景

前言:前端开发一个网站时,可能经常会遇到这么一个需求,每个页面都会添加一个底部并附上网站的信息等等。

然而,我们也经常会遇到以下问题:

问题描述:页面主内容很少时(包括底部在内不足一屏),可能会出现高度不足导致底部下面留白。

1
2
3
4
5
<div class="hello">
<header>头部</header>
<main>主体内容</main>
<footer>底部</footer>
</div>

一、常规页面底部css写法以及存在问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
header {
height: 50px;
background: #5d6156;
color: #fff;
}
main {
height: 500px;
}

footer {
background: #212020;
color: #fff;
padding: 40px;
}

效果:整体页面高度不够时,页面底部留白

所以,今天我是来推荐一个好用的底部填充的css实现方式的

二、使用 outline 与 clip 实现自动填满屏幕剩余空间,从而覆盖整个底部

解决方法:

  设置一个超大轮廓范围的outline(该属性不占据任何空间)属性,保证完整的覆盖整个屏幕。

  但由outline 无法指定方位,只能被动地四周拓展。但我们只是希望达到底部下面不留白,并不想要上面也被覆盖。所以需要使用一种方式将底部上边的隐藏或去除。除了通过改变主体内容的层叠顺序,达到覆盖的目的之外,还可以使用clip裁剪策略。同时已上边缘和左边缘为界对底部进行裁剪,就可以达到我们想要的目的。

1
2
3
4
5
6
7
8
9
10
.footer > p {
position: absolute;
left: 0;
right: 0;
text-align: center;
padding: 15px 0;
background-color: black;
outline: 9999px solid black;
clip: rect(0, 9999px, 9999px, 0);
}

效果:设置outline 为很大的值,盖满整个屏幕,再利用 clip 以上边缘和左边缘为界进行裁切

outline 兼容性

clip 兼容性

综上,除了ie 6-7, outline 与 clip 的兼容性都达到90%以上,感觉还是很不错,所以这个算是一个很不错的实现自动填满屏幕剩余空间的应用技巧

参考

  • 《css 世界》
阅读全文
前端构建踩坑 --- babel-loader 对已编译的脚本进行再编译从而导致文件执行出错

前言

问题描述: babel-loader 对已编译的脚本进行再编译从而导致文件执行出错。

  因为打算开发一个小组件库,但是要对已经编译完成的组件库的脚本进行一遍完整的测试。所以,本人就很自然的启动一个项目,引入已经编译好的组件库脚本,想着大展伸手,结果。。。

  遇到了一大堆脑瓜子疼的警告"export 'default' (imported as 'a') was not found in 'xxx' ",或乱七八糟的报错…(捂脸哭.jpeg)。

  • 原本我要引入的脚本a.umd.js是使用了ES6 模块的写法,将对应的模块export default 出来的。
  • 再将组件库发包到 npm上,并通过npm install 去将该组件库安装到node_modules对应的目录中。
  • 然后使用import a from ‘XXX’去引入,结果这个组件库是可以正常使用的。
  • 但是,当直接在本地(不是在node_modules)引入该脚本或在直接在package.json中将该组件库作为本底依赖安装也不行时,就会出现上面提示的警告(或报错)。

  原本想着只有在node_modules中才能正常使用,好,为了调试,我选择直接将该脚本(a.umd.js)作为本地依赖引入,因此,我就很兴奋去尝试了。。。步骤是这样的:

1
2
3
4
5
6
7
// 在package.json直接通过通过本地依赖的方式引入脚本a.umd.js
{
"name": "baz",
"dependencies": {
"a": "file:./config/a.umd.js"
}
}

嗯,很顺利npm i完成,然鹅。

直接通过本地依赖的方式依旧存在以上的问题。

那么为什么通过npm i发布到 npm 的脚本a.umd.js能在 node_modules 正常使用而通过本地依赖的方式安装 node_modules 以及直接引用却不行?

后来

经过网上查资料以及分析项目,终于发现了这么一个事情。。。

  嗯,是的,babel-loader 对a.umd.js这个脚本,再次进行了编译。。。导致原本编译好的可以正常使用的脚本再次进一步被编译了,所以才会报错"export 'default' (imported as 'a') was not found in 'xxx' "

因此

  为了能顺利地在本地调试组件库的脚本a.umd.js,我只能选择在引入该脚本 a.umd.js调试的项目中进行 babel-loader 的配置,将 babel-loader 对 a.umd.js 的编译进行exclude。即babel-loader 不编译名字中包含a.umd字符的文件。

  • 如果直接使用webpack配置,则配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    module: {
    rules: [
    {
    test: /\.m?js$/,
    exclude: /a.umd/,
    use: {
    loader: 'babel-loader',
    options: {
    presets: ['@babel/preset-env']
    }
    }
    }
    ]
    }
  • 如果是使用vue-cli,则vue.config.js配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    chainWebpack: (config, isServer) => {
    // config 是 ChainableConfig 的一个实例
    config.module.rule('js').use('babel-loader')
    .loader('babel-loader').tap(options => {
    options.exclude = /a.umd/
    // 修改它的选项...
    return options
    })
    },

从过以上的方式就可以避免babel-loader 对已经编译的文件进行二次编译

所以,综上所述

  • vue-cli3 中 babel-loader 的配置是不对 node_moudules 文件夹中的文件进行编译,所以当直接将脚本放在 node_modules 或直接通过 npm 远程 install 都能正常使用。
  • 而当引入的脚本不在 node_modules 中或通过本地依赖的方式安装到 node_modules 都会被babel-loader二次编译(当然设置了exclude的除外)
阅读全文
hexo简单使用教程

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

阅读全文
关于跨域与 csrf 的那些小事

前言

  在这段时间,部门前辈分享了不少干货。我学到了不少内容,并对其进行简单整理,以便更好地转化为自己的知识。

知识探讨部分

关于跨域

产生

  1. 协议,域名,端口三者其中存在不同都会形成跨域;故,当协议,端口,域名三者均相同时,浏览器就会认为是同源,允许加载该资源,否则为不同源。
  2. 跨域存在原因:浏览器的同源限制策略

  从上面列出的例子中,我们可以看到客户端和服务端是处于不同的域名下,这种情况,客户端可以正常地向服务端发出请求。但是,由于浏览器的同源限制策略,服务端响应的数据会被浏览器过滤掉,并抛出常见的跨域报错。

网上随便找了一张常见的跨域报错的图

特别需要提一下的是:IE 与其他浏览器对于同源策略的处理方式稍有点不同。主要包括以下两点:

  • 授信范围:两个相互之间高度互信的域名,不受同源策略的限制。
  • 端口:IE 未将端口号加入到同源策略的组成成分中。即两个协议,域名相同,端口不同的域名,IE 会认为两者是属于同源并不受限制的。

为什么会被过滤?

  浏览器收到响应数据之后,会判断响应回数据的源和当前页面的源是否是属于同源。针对不同源,如果后端没有对响应字段进行处理,则响应回的数据会被浏览器直接过滤掉。

发生跨域时,允许进行的操作

  1. 通常允许跨域写操作(link、redirect、表单提交)
  2. 通常允许跨域资源嵌入(script、img、video…)
  3. 通常禁止跨域读操作(ajax)
  4. 可以正常发送请求,可以携带Cookie(withCredentials),但是浏览器会限制来自于不同域的资源的接收

跨域限制的资源

  • 1.数据存储限制:Cookie, LocalStorage, IndexDB 无法读取
  • 2.脚本 API 限制:DOM 无法操作
  • 3.网络请求限制:XHR 请求无法接收响应

第1点:

(1) LocalStorage、IndexedDB 以源进行分割,每个源都拥有自己单独的存储空间,一个源中的 JavaScript 脚本不能对其它源的数据进行读写操作。

(2)cookie 的同源限制只要体现在域方面,与端口,协议无关。用户可以获取和设置当前域以及当前域对应父域下的 cookie。

第2点:

(1)脚本API限制:浏览器限制了 js 的跨站点(不同源)调用或操作。如:来源于 A 源页面的脚本,只能操作“同源”的页面,而来源于 B 源页面的脚本不能操作 A 源页面的 DOM。

(2)当然,需要特别提醒一下的是,对于一段 js 脚本来说,该脚本的“源”指的是加载该脚本页面的源,与存储该脚本的地址无关。如:A(https://www.a.com)页面下加载了两段脚本,分别为:b.js (源于http://www.b.com)和c.js(https:www.c.com)。b.js 和 c.js 被加载至A页面下,与 A 同源,所以 b 和 c 脚本都可以操作 A 页面的 DOM。

  进一步思考,我们会发现 A 页面地址与 b 和 c 脚本存储地址都处于不同源下,按道理,应该会出现跨域限制(同源限制),但结果是没有。其实这个是取决于浏览器的一个特性,浏览器的同源策略不对src属性做限制,也就是说像<script>,<img>,<link>等这些标签是可以从不同源的网站中获取到资源的。

解决方式

  跨域的解决方案有很多( jsonp,反向代理,使用 document.domain 设置为同域,跨域资源共享等等),这里就不详细说了,但特别想提一下是跨域资源共享(cors)

cors 主要是进行以下处理:

  服务端设置响应头的 access-control-allow-origin 的值为允许请求的域(客服端的)或设置为*(即匹配任意域名,任意客户端都可访问);即可获取到该服务端响应的跨域资源。

原因:

  当响应数据从服务端回到浏览器时,浏览器得知客户端和服务端属于不同的域,但同时浏览器又看到响应数据的响应头中 access-control-allow-origin 的字段值是包含当前客户端地址或*,浏览器则不会对响应的数据进行过滤。

拓展知识点:web 安全之 csrf(跨站伪造请求)

攻击成功的操作步骤如下:

csrf 特征:
  • 攻击⼀般来源于第三方域名
  • ccsrf 不能获取到 cookie,但是可以利用浏览器的特性去使用。
  • 接口的所有参数都是可以预测的(攻击网站清楚要伪造请求接口的请求参数)

  从前面提到的跨域知识点中,能了解到浏览器对于 cookie 也是存在同源限制的,也就是与 cookie(domain)处于不同源的网站,浏览器是不会让该网站获取到这个 cookie。那为什么csrf攻击还会成功呢?其实这个与浏览器使用 cookie 的方式有关。

浏览器使用 cookie 情况主要包括以下几点:

  1. 除了跨域 XHR 请求情况下,浏览器在发起请求的时候会把符合要求的 cookie 自动带上。(域名,有效期,路径,secure 属性)

  2. 跨域 XHR 的请求的情况下,也可以携带 Cookie。

  3. 浏览器允许跨域提交表单

  也就是说,浏览器中有页面或网站向某个域名发送请求时,其请求都会自动带上该域名下的所有 cookie。

csrf 防御途径

简单列出三点

1. Referer: HTTP请求完整来源路径(不完善)

1
2
3
4
5
6
7
8
9
针对通过 Referer 字段去判断请求来源是否合法是不太靠谱的,这个字段很有可能会丢失:

1.IE6、7下使用 window.location.href=url 进行界面的跳转或者 window.open,都会造成 Referer 丢失。

2.HTTPS 页面跳转到 HTTP 页面,所有浏览器 Referer 都丢失。

3.点击 Flash 上到达另外一个网站的时候,Referer 的情况就比较杂乱,不太可信。

可以附加使用于判断请求来源,但是仅通过该字段进行判断是不太靠谱的,如果请求头丢失该字段,则服务端无法判断当前请求来源,无法校验请求是否合法。

2. Origin: CORS 中的请求头,当跨域访问时,会携带此请求头(不完善)

1
2
3
4
5
6
7
在以下情况不存在此请求头:

302 重定向:
1. 在 302 重定向之后 Origin 不包含在重定向的请求中,因为 Origin 可能会被认为是其他来源的敏感信息。
2.对于 302 重定向的情况来说都是定向到新的服务器上的 URL,因此浏览器不想将 Origin 泄漏到新的服务器上。

Origin 和 Referer 存在相同的问题,同样有可能丢失该字段。

3. token 校验(常用方式)

最常用的一种是通过token去校验请求是否合法:

校验原理:
  1. 后端生成 token,并存在 session 中。
  2. 用户请求成功后,后端将 token 发送到客户端,发送方式主要是为以下两种:

(1)服务端将 token 渲染到 html 中。
也就是通过一个 dom 结点保存 token 信息,客户端就可以通过 dom 操作获取到该 token 内容。(同源策略会限制脚本 API 操作)

(2)服务端将 token 设置到 cookie 中。
客户端从 cookie 中获取(同源策略限制 cookie 操作)

  1. 客户端在获取到 token 后,在下一次进行比较关键的请求操作时,将 token 发送到服务端。

    发送 token 到服务端的方式主要包括两种:

  • 在请求头中将获取到的 token 设置到 cookie 中。
  • 将 token 放到请求参数中。
  1. 服务端在接收到请求后,会从请求头中取出 token,并和 session 中的 token 进行比较,一致则表示身份验证通过,再返回相应的信息;否则,则校验不通过。

补充:

  token 校验之所以能防御 csrf,是因为相信浏览器的同源策略。为什么这么说?因为只有在同源的情况下,页面才能进行脚本操作和使用 js 获取 cookie 的操作,才能获取到 token。也就是说第三方网站是没有办法拿到 token 的。只有真正有权限的网站或页面才有办法取到 token,并将 token 传到服务端。所以服务端默认带有相应 token 的请求都是合法的请求。

注:设置 http only,禁止通过 js 操作 cookie

参考文章

阅读全文
cron 表达式 & crontab 定时任务

前言

  因开发需要,所以研究了一番cron表达式,并将内容整理如下:

cron 是什么?

  首先在了解 cron 表达式之前,先谈谈 crontab 定时任务;日常在开发或运维中,经常遇到一些周期性执行的任务或需求,比如说,每个一段时间执行一个脚本,每周一执行一个命令或操作。而 linux 已经给我们提供了一个便捷的方式– crontab 定时任务;crontab 就是一个自定义定时器,我们可以利用 crontab 命令在固定的间隔时间执行指定的系统指令或 shell script 脚本。而这个时间间隔的写法与我们平常用到的cron 表达式相似。作用都是通过利用字符或命令去设置定时周期性地执行一些操作。

  我们可以将cron表达式看作一个以5或6个字符串空格隔开的字符串。这个5或6个空格将字符串划分为6或7个域,每个域代表着不同的含义。默认从左到右为:”秒 分 小时 日 月 星期几 年份“。

cron 内容

域 | 字段 | 含义 | 范围或通配符 | 是否必填
-|-|-|-|-|-|
秒 | Seconds | 秒 | 0-59,-*/| 是
分 | Minutes | 分钟 |0-59,-*/| 是
时 | Hours | 小时 |0-23,-*/ | 是
日 | Day-of-Month | 日期 | 1-31,-*?/LW | 是
月 | Month | 月份 | 1-12 (或 JAN-DEC)或者,- * / | 是
星期 | Day-of-Week | 每星期的周几 | 1-7(或SUNMONTUEWEDTHUFRISAT)或者, - * ? / L # | 是
年 | Year | 年份 | 1970-2099- * /| 否

特殊字符含义:

  • ,:表示列出枚举值。如在月中的值为1,3,则表示一月份和3月份都触发事件。
  • *:表示匹配该域任意值,如小时的字段为*时,表示每一小时都触发事件

  • ?:表示不指定值,用于日期和星期字段之间进行互斥。通常在日期和星期字段中的一个指定值,另外一个用?表示不指定值。个人理解就是忽略该字段的值,直接根据另外一个字段的值进行执行。比如说:日期为2,则星期应为?;

  • -:表示范围,一个连续触发的区间。如:时的值为9-12,则表示9-12小时中的每个小时都触发事件。

  • /:表示间隔时间触发事件(开始时间/时间间隔)。如:在分钟值为0/15,则表示从0分开始,每隔15分钟触发一遍事件。

  • #:表示该月第n个星期x(x#n),仅用星期域。如:星期:6#3,表示该月的第三个星期五。

  • L:表示最后(最后一天或最后一个星期几);仅出现在日和星期的域中。用在日则表示该月的最后一天,用在星期则表示该月的最后一个星期X。如:星期域上的值为5L,则表示该月最后一个星期的星期四。在使用'L'时,不要指定列表','或范围'-',否则易导致出现意料之外的结果。

  • W:仅用在日的域中,表示距离当月给定日期最近的工作日(周一到周五)。

    如:"4W"表示距离4号最近的工作日(当月的)触发事件;
    (1)当4号就是工作日时,则表示当天触发;当4号为周六时,则表示3号(周五)触发;
    (2)当4号为周日时,则表示在5号(周一)触发;
    再如:"1W"表示距离1号最近的工作日触发事件,但是,该工作日只算当月的。假如当月1号是周六,则”1W“表示在当月3号(周一)触发事件。就算上个月的最后一天是工作日,也不会触发事件。

  • LW‘L’'W'可以一起组合在日字段使用。表示当月的最后一个工作日触发事件。

使用示例

1
2
3
4
5
6
7
8
9
10
11
// 从左往右: 秒 分 时 日 月 星期 年

"30 * * * * ? *" // 表示半分钟触发一次事件
"0 0 12 ? * WED" // 表示每个星期三中午12点
"0 0,15 8-11 * * 2" // 每周一上午8点至11点(8,9,10,11)的第0和第15分钟都触发一次事件
"0 0/5 15 * * ?" // 在每天下午3点到下午3:55期间的每5分钟触发
"0 0 12 L * ?" // 每月最后一日的中午12:00触发事件
"0 0 12 4W * ?" // 每月距离4号最近的工作日的中午12:00触发事件
"0 0 12 LW * ?" // 每月最后一个工作日的中午12:00触发事件
"0 0 12 ? * 6#3" // 每月第3个星期五中午12:00触发事件
"0 11 11 11 11 ? 2019" // 2019年的11月11号 11点11分触发(光棍节)

参考文章

阅读全文
vue-router踩坑之NavigationDuplicated error

前言

  因业务需求重新开发了一个项目,但是在使用vue-router,偶然发现vue-router会报下面这个错误。

后来网上查询,给出了很多解决方案,很多都说直接删除node_modules,重新安装依赖就好。同时也有很多网友说这个方案无效。其实会出现这种错误的情况,是因为

1
[Bug Report] 升级vue-router至3.1以后版本,导航组件重复点击报错 NavigationDuplicated

也就是说这是vue-router3.1版本之后,对于航组件重复点击的一个错误处理方式。

因此,要解决这个报错有两种方案:
  1. vue-router版本锁在3.1版本以下
1
2
3
4
// 卸载原来的vue-router
npm un vue-router
// 安装指定版本(3.1以下)的vue-router,我选择装3.0.6
npm i vue-router@3.0.6
  1. 使用router.push时,请进行catch处理,将这个错误捕获。

原讨论贴

地址:No stacktrace on NavigationDuplicated error #2881

阅读全文
mac常用手势以及快捷键

常用手势

鼠标点击效果——单指点击

鼠标右键效果——双指点击一次

滚动上下文——两指上下滑动

显示所有程序——四指靠拢

显示桌面——四指散开

切换全屏打开的应用——三指左右滑动

网页前进或后退(微信图片上一张或下一张)——两指左滑或右滑

显示正在执行的任务——三指上滑

智能缩放——双指轻触触摸板两次

常用快捷键

在当前应用的多个窗口中相互切换——command + `

后退(文件夹可用)——command + [

前进(文件夹可用)——command + ]

放大——command + +

缩小——command + -

在应用程序中的窗口进行切换——command + ~

在当前已打开的多个应用间进行切换——command + tab

隐藏窗口——command + h

最小化窗口——command + m

最小化窗口——command + m

新建——command + n

删除——command + delete

清空回收站——command + shift + delete

当前选中的文字生成便签——command + shift + y

切换输入法——command + 空格

另存为——command + shift + s

显示当前应用的多个窗口——ctrl + ​ ⬇️

显示正在执行的任务——ctrl + ⬆️

关闭当前标签页——command + w

直接退出当前应用——command + q

打开聚焦搜索(MacOS最爽功能)——command + 空格

打开Siri——command + 长按空格

Safari阅读模式——shift + command + r

补充

截全屏——shift + command + 3

截部分屏——shift + command + 4 + 单指点击选择区域

参考文章

常用的Mac快捷键及手势

Mac触控板常用的手势操作,让你告别Windows鼠标!

[技巧] Mac 触控板手势和部分快捷键

阅读全文
常用的Linux命令

以下仅列出常用Linux命令

常用磁盘操作

  1. cd [dirName] 切换当前当前工作路径到dirName(目标路径)
  1. mkdir [-p] dirName 建立名称为dirName的子目录(在当前工作目录下创建子目录,无需加p;而在其他目录下,需添加p用于确保目录名称存在,)
  1. pwd用于显示当前工作目录
  1. rmdir [-p] dirName 删除空目录(-p 是当子目录被删除后使它也成为空目录的话,则顺便一并删除)
  1. ls命令用于显示指定工作目录下之内容(列出目前工作目录所含之文件及子目录)
  1. rm 用于删除一个文件和目录
  • 文件一旦被删除则无法恢复
  1. cp [options] source dest/directory 命令对文件进行复制
  • 特别点:
  • 复制目录时,需携带选项-r
  • 示例:
  • 使用指令cp将当前目录test/下的所有文件复制到新目录newtest下,输入如下命令:
    1
    $ cp –r test/ newtest
  1. mv 源文件(或源目录) 目标文件(或目标目录) 命令对文件或文件夹进行移动,如果文件或文件夹存在于当前工作目录,还可以对文件或文件夹进行重命名。
命令格式 执行结果
mv 文件名 文件名 将源文件名改为目标文件名
mv 文件名 目录名 将文件移动到目标目录
mv 目录名 目录名 目标目录已存在,将源目录移动到目标目录;目标目录不存在则改名
mv 目录名 文件名 出错

文件操作

vi 相关

正在更新。。。

参考文章

阅读全文
(转载)雅虎团队经验:网站页面性能优化的34条黄金守则

网上看到这篇针对‘雅虎团队经验:网站页面性能优化的34条黄金守则’进行翻译的文章,感觉挺好的,因此将其保存到自己的博客上;原链接

1、尽量减少HTTP请求次数

终端用户响应的时间中,有80%用于下载各项内容。这部分时间包括下载页面中的图像、样式表、脚本、Flash等。通过减少页面中的元素可以减少HTTP请求的次数。这是提高网页速度的关键步骤。 
减少页面组件的方法其实就是简化页面设计。那么有没有一种方法既能保持页面内容的丰富性又能达到加快响应时间的目的呢?这里有几条减少HTTP请求次数同时又可能保持页面内容丰富的技术。

合并文件是通过把所有的脚本放到一个文件中来减少HTTP请求的方法,如可以简单地把所有的CSS文件都放入一个样式表中。当脚本或者样式表在不同页面中使用时需要做不同的修改,这可能会相对麻烦点,但即便如此也要把这个方法作为改善页面性能的重要一步。

CSS Sprites是减少图像请求的有效方法。把所有的背景图像都放到一个图片文件中,然后通过CSS的background-image和background-position属性来显示图片的不同部分;

图片地图是把多张图片整合到一张图片中。虽然文件的总体大小不会改变,但是可以减少HTTP请求次数。图片地图只有在图片的所有组成部分在页面中是紧挨在一起的时候才能使用,如导航栏。确定图片的坐标和可能会比较繁琐且容易出错,同时使用图片地图导航也不具有可读性,因此不推荐这种方法;

内联图像是使用data:URL scheme的方法把图像数据加载页面中。这可能会增加页面的大小。把内联图像放到样式表(可缓存)中可以减少HTTP请求同时又避免增加页面文件的大小。但是内联图像现在还没有得到主流浏览器的支持。

减少页面的HTTP请求次数是你首先要做的一步。这是改进首次访问用户等待时间的最重要的方法。如同Tenni Theurer的他的博客Browser Cahe Usage - Exposed!中所说,HTTP请求在无缓存情况下占去了40%到60%的响应时间。让那些初次访问你网站的人获得更加快速的体验吧!

2、减少DNS查找次数

  域名系统(DNS)提供了域名和IP的对应关系,就像电话本中人名和他们的电话号码的关系一样。当你在浏览器地址栏中输入www.dudo.org时,DNS解析服务器就会返回这个域名对应的IP地址。DNS解析的过程同样也是需要时间的。一般情况下返回给定域名对应的IP地址会花费20到120毫秒的时间。而且在这个过程中浏览器什么都不会做直到DNS查找完毕。

 缓存DNS查找可以改善页面性能。这种缓存需要一个特定的缓存服务器,这种服务器一般属于用户的ISP提供商或者本地局域网控制,但是它同样会在用户使用的计算机上产生缓存。DNS信息会保留在操作系统的DNS缓存中(微软Windows系统中DNS Client Service)。大多数浏览器有独立于操作系统以外的自己的缓存。由于浏览器有自己的缓存记录,因此在一次请求中它不会受到操作系统的影响。

Internet Explorer默认情况下对DNS查找记录的缓存时间为30分钟,它在注册表中的键值为DnsCacheTimeout。Firefox对DNS的查找记录缓存时间为1分钟,它在配置文件中的选项为network.dnsCacheExpiration(Fasterfox把这个选项改为了1小时)。

当客户端中的DNS缓存都为空时(浏览器和操作系统都为空),DNS查找的次数和页面中主机名的数量相同。这其中包括页面中URL、图片、脚本文件、样式表、Flash对象等包含的主机名。减少主机名的数量可以减少DNS查找次数。

减少主机名的数量还可以减少页面中并行下载的数量。减少DNS查找次数可以节省响应时间,但是减少并行下载却会增加响应时间。我的指导原则是把这些页面中的内容分割成至少两部分但不超过四部分。这种结果就是在减少DNS查找次数和保持较高程度并行下载两者之间的权衡了。

3、避免跳转
跳转是使用301和302代码实现的。下面是一个响应代码为301的HTTP头:
HTTP/1.1 301 Moved Permanently
Location: http://example.com/newuri
Content-Type: text/html
浏览器会把用户指向到Location中指定的URL。头文件中的所有信息在一次跳转中都是必需的,内容部分可以为空。不管他们的名称,301和302响应都不会被缓存除非增加一个额外的头选项,如Expires或者Cache-Control来指定它缓存。元素的刷新标签和JavaScript也可以实现URL的跳转,但是如果你必须要跳转的时候,最好的方法就是使用标准的3XXHTTP状态代码,这主要是为了确保“后退”按钮可以正确地使用。

但是要记住跳转会降低用户体验。在用户和HTML文档中间增加一个跳转,会拖延页面中所有元素的显示,因为在HTML文件被加载前任何文件(图像、Flash等)都不会被下载。

有一种经常被网页开发者忽略却往往十分浪费响应时间的跳转现象。这种现象发生在当URL本该有斜杠(/)却被忽略掉时。例如,当我们要访问http://astrology.yahoo.com/astrology 时,实际上返回的是一个包含301代码的跳转,它指向的是http://astrology.yahoo.com/astrology/  (注意末尾的斜杠)。在Apache服务器中可以使用Alias 或者 mod_rewrite或者the DirectorySlash来避免。

连接新网站和旧网站是跳转功能经常被用到的另一种情况。这种情况下往往要连接网站的不同内容然后根据用户的不同类型(如浏览器类型、用户账号所属类型)来进行跳转。使用跳转来实现两个网站的切换十分简单,需要的代码量也不多。尽管使用这种方法对于开发者来说可以降低复杂程度,但是它同样降低用户体验。一个可替代方法就是如果两者在同一台服务器上时使用Alias和mod_rewrite和实现。如果是因为域名的不同而采用跳转,那么可以通过使用Alias或者mod_rewirte建立CNAME(保存一个域名和另外一个域名之间关系的DNS记录)来替代。

4、可缓存的AJAX
Ajax经常被提及的一个好处就是由于其从后台服务器传输信息的异步性而为用户带来的反馈的即时性。但是,使用Ajax并不能保证用户不会在等待异步的JavaScript和XML响应上花费时间。在很多应用中,用户是否需要等待响应取决于Ajax如何来使用。例如,在一个基于Web的Email客户端中,用户必须等待Ajax返回符合他们条件的邮件查询结果。记住一点,“异步”并不异味着“即时”,这很重要。

为了提高性能,优化Ajax响应是很重要的。提高Ajxa性能的措施中最重要的方法就是使响应具有可缓存性,具体的讨论可以查看Add an Expires or a Cache-Control Header。其它的几条规则也同样适用于Ajax: 

Gizp压缩文件
减少DNS查找次数
精简JavaScript
避免跳转
配置ETags

让我们来看一个例子:一个Web2.0的Email客户端会使用Ajax来自动完成对用户地址薄的下载。如果用户在上次使用过Email web应用程序后没有对地址薄作任何的修改,而且Ajax响应通过Expire或者Cacke-Control头来实现缓存,那么就可以直接从上一次的缓存中读取地址薄了。必须告知浏览器是使用缓存中的地址薄还是发送一个新的请求。这可以通过为读取地址薄的Ajax URL增加一个含有上次编辑时间的时间戳来实现,例如,&t=11900241612等。如果地址薄在上次下载后没有被编辑过,时间戳就不变,则从浏览器的缓存中加载从而减少了一次HTTP请求过程。如果用户修改过地址薄,时间戳就会用来确定新的URL和缓存响应并不匹配,浏览器就会重要请求更新地址薄。 
   即使你的Ajxa响应是动态生成的,哪怕它只适用于一个用户,那么它也应该被缓存起来。这样做可以使你的Web2.0应用程序更加快捷。

5、推迟加载内容
你可以仔细看一下你的网页,问问自己“哪些内容是页面呈现时所必需首先加载的?哪些内容和结构可以稍后再加载?
把整个过程按照onload事件分隔成两部分,JavaScript是一个理想的选择。例如,如果你有用于实现拖放和动画的JavaScript,那么它就以等待稍后加载,因为页面上的拖放元素是在初始化呈现之后才发生的。其它的例如隐藏部分的内容(用户操作之后才显现的内容)和处于折叠部分的图像也可以推迟加载
工具可以节省你的工作量:YUI Image Loader可以帮你推迟加载折叠部分的图片,YUI Get utility是包含JS和 CSS的便捷方法。比如你可以打开Firebug的Net选项卡看一下Yahoo的首页。
当性能目标和其它网站开发实践一致时就会相得益彰。这种情况下,通过程序提高网站性能的方法告诉我们,在支持JavaScript的情况下,可以先去除用户体验,不过这要保证你的网站在没有JavaScript也可以正常运行。在确定页面运行正常后,再加载脚本来实现如拖放和动画等更加花哨的效果。

6、预加载
预加载和后加载看起来似乎恰恰相反,但实际上预加载是为了实现另外一种目标。预加载是在浏览器空闲时请求将来可能会用到的页面内容(如图像、样式表和脚本)。使用这种方法,当用户要访问下一个页面时,页面中的内容大部分已经加载到缓存中了,因此可以大大改善访问速度。

下面提供了几种预加载方法:
无条件加载:触发onload事件时,直接加载额外的页面内容。以Google.com为例,你可以看一下它的spirit image图像是怎样在onload中加载的。这个spirit image图像在google.com主页中是不需要的,但是却可以在搜索结果页面中用到它。
有条件加载:根据用户的操作来有根据地判断用户下面可能去往的页面并相应的预加载页面内容。在search.yahoo.com中你可以看到如何在你输入内容时加载额外的页面内容。
有预期的加载:载入重新设计过的页面时使用预加载。这种情况经常出现在页面经过重新设计后用户抱怨“新的页面看起来很酷,但是却比以前慢”。问题可能出在用户对于你的旧站点建立了完整的缓存,而对于新站点却没有任何缓存内容。因此你可以在访问新站之前就加载一部内容来避免这种结果的出现。在你的旧站中利用浏览器的空余时间加载新站中用到的图像的和脚本来提高访问速度。

7、减少DOM元素数量
一个复杂的页面意味着需要下载更多数据,同时也意味着JavaScript遍历DOM的效率越慢。比如当你增加一个事件句柄时在500和5000个DOM元素中循环效果肯定是不一样的。
大量的DOM元素的存在意味着页面中有可以不用移除内容只需要替换元素标签就可以精简的部分。你在页面布局中使用表格了吗?你有没有仅仅为了布局而引入更多的

元素呢?也许会存在一个适合或者在语意是更贴切的标签可以供你使用。
YUI CSS utilities可以给你的布局带来巨大帮助:grids.css可以帮你实现整体布局,font.css和reset.css可以帮助你移除浏览器默认格式。它提供了一个重新审视你页面中标签的机会,比如只有在语意上有意义时才使用
,而不是因为它具有换行效果才使用它。
DOM元素数量很容易计算出来,只需要在Firebug的控制台内输入:
document.getElementsByTagName(‘*’).length
那么多少个DOM元素算是多呢?这可以对照有很好标记使用的类似页面。比如Yahoo!主页是一个内容非常多的页面,但是它只使用了700个元素(HTML标签)。

8、根据域名划分页面内容
把页面内容划分成若干部分可以使你最大限度地实现平行下载。由于DNS查找带来的影响你首先要确保你使用的域名数量在2个到4个之间。例如,你可以把用到的HTML内容和动态内容放在www.example.org上,而把页面各种组件(图片、脚本、CSS)分别存放在statics1.example.org和statics.example.org上。
你可在Tenni Theurer和Patty Chi合写的文章Maximizing Parallel Downloads in the Carpool Lane找到更多相关信息。

9、使iframe的数量最小
ifrmae元素可以在父文档中插入一个新的HTML文档。了解iframe的工作理然后才能更加有效地使用它,这一点很重要。

阅读全文