I Try Do


  • 首页

  • 归档

  • 分类

  • 标签

  • 搜索
close
I Try Do

内置Promise的使用

发表于 2017-02-18 | 分类于 node.js | | 阅读次数

引入方法

高版本node已经内嵌了Promise机制

1
var Promise = require('promise');

简单使用

new Promise依赖关系顺序执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function testPromise(begin) {
return new Promise(function (resolve, reject) {
// 在这里写异步方法, resolve是then的第一个参数, reject是then的第二个参数
if (begin <= 3){
resolve(begin);
}
reject('begin 不允许 > 3');
}).then(function (begin) {
console.log(begin);
}, function(err){
console.log(err);
});
}
// 调用测试
testPromise(0); // 0
testPromise(4); // begin 不允许 > 3

高级使用

new Promise.all非依赖同时执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function onePromise(begin) {
return new Promise(function (resolve, reject) {
if (begin <= 3){
resolve(begin);
}
reject('begin = '+ begin +' 不允许 > 3');
});
}
function testPromise2(begin){
return new Promise.all([onePromise(begin), onePromise(begin+1), onePromise(begin+2)]).then(function(datas){
console.log(datas);
}, function(err){
console.log(err);
})
}
// 调用测试
testPromise2(1); // [ 1, 2, 3 ]
testPromise2(2); // begin = 4 不允许 > 3


其他Promise 第三方库

如果node版本较低,可以使用其他实现Promise标准的库

  • bluebird github
  • Q github
  • Deferredgithub
  • thengithub
  • whengithub
  • asyncgithub
  • eventproxy(事件驱动)github
I Try Do

flex布局资料

发表于 2017-02-18 | 分类于 css | | 阅读次数
  • Flex 布局教程:语法篇

  • http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool


flex

Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为Flex布局。

1
2
3
.box{
display: flex;
}

行内元素也可以使用Flex布局。

1
2
3
.box{
display: inline-flex;
}

Webkit内核的浏览器,必须加上-webkit前缀。

1
2
3
4
.box{
display: -webkit-flex; /* Safari */
display: flex;
}

注意,设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。


flex属性

容器的属性

flex-direction

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。

flex-wrap

  • nowrap(默认):不换行。
  • wrap:换行,第一行在上方。
  • wrap:wrap-reverse:换行,第一行在下方。

flex-flow

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap

1
2
3
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}

justify-content

justify-content属性定义了项目在主轴上的对齐方式。

1
2
3
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
}

  • flex-start(默认值):左对齐
  • flex-end:右对齐
  • center: 居中
  • space-between:两端对齐,项目之间的间隔都相等。
  • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

align-items

align-items属性定义项目在交叉轴上如何对齐。

1
2
3
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • baseline: 项目的第一行文字的基线对齐。
  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。

align-content

align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用

1
2
3
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
  • flex-start:与交叉轴的起点对齐。
  • flex-end:与交叉轴的终点对齐。
  • center:与交叉轴的中点对齐。
  • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
  • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
  • stretch(默认值):轴线占满整个交叉轴。

项目的属性

order

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

1
2
3
.item {
order: <integer>;
}

flex-grow

flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

1
2
3
.item {
flex-grow: <number>; /* default 0 */
}

如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

flex-shrink

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

1
2
3
.item {
flex-shrink: <number>; /* default 1 */
}

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

flex-basis

flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

1
2
3
.item {
flex-basis: <length> | auto; /* default auto */
}

它可以设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。

flex

flex属性是flex-grow,flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

1
2
3
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

align-self

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

1
2
3
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

I Try Do

node的http模块

发表于 2017-02-18 | 分类于 node.js | | 阅读次数

创建简单服务器

参考

1
2
3
4
5
6
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

根据url下载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var http = require('http');
var fs = require('fs');
var url = 'http://www.baidu.com/dd2.jpg';
var downloadFilePath = '/c/abc.png';
var file = fs.createWriteStream(downloadFilePath, {flags: 'w'});
var req = http.get(url, function (res) {
res.pipe(file, {end: 'false'});
res.on('end', function () {
file.end();
console.log('download success');
}).on('error', function(e) {
console.log('error:', e);
});
});
req.on('error', function(err){
//错误处理,处理res无法处理到的错误
console.error('download file error out:', url);
});
I Try Do

软件注册码

发表于 2017-02-18 | 分类于 工具 | | 阅读次数

sublime3

1
2
3
4
5
6
7
8
9
10
11
12
13
—– BEGIN LICENSE —–
Michael Barnes
Single User License
EA7E-821385
8A353C41 872A0D5C DF9B2950 AFF6F667
C458EA6D 8EA3C286 98D1D650 131A97AB
AA919AEC EF20E143 B361B1E7 4C8B7F04
B085E65E 2F5F5360 8489D422 FB8FC1AA
93F6323C FD7F7544 3F39C318 D95E6480
FCCC7561 8A4A1741 68FA4223 ADCEDE07
200C25BE DBBC4855 C4CFB774 C5EC138C
0FEC1CEF D9DCECEC D3A5DAD1 01316C36
—— END LICENSE ——
1
2
3
4
5
6
7
8
9
10
11
12
13
—– BEGIN LICENSE —–
Alexey Plutalov
Single User License
EA7E-860776
3DC19CC1 134CDF23 504DC871 2DE5CE55
585DC8A6 253BB0D9 637C87A2 D8D0BA85
AAE574AD BA7D6DA9 2B9773F2 324C5DEF
17830A4E FBCF9D1D 182406E9 F883EA87
E585BBA1 2538C270 E2E857C2 194283CA
7234FF9E D0392F93 1D16E021 F1914917
63909E12 203C0169 3F08FFC8 86D06EA8
73DDAEF0 AC559F30 A6A67947 B60104C6
—— END LICENSE ——

webstorm

online get:

1
http://idea.lanyus.com/

I Try Do

事件对象(event)

发表于 2017-02-18 | 分类于 javascript | | 阅读次数
  • onabort 图像加载被中断
  • onblur 元素失去焦点
  • onchange 用户改变域的内容
  • onclick 鼠标点击某个对象
  • ondblclick 鼠标双击某个对象
  • onerror 当加载文档或图像时发生某个错误
  • onfocus 元素获得焦点
  • onkeydown 某个键盘的键被按下
  • onkeypress 某个键盘的键被按下或按住
  • onkeyup 某个键盘的键被松开
  • onload 某个页面或图像被完成加载
  • onmousedown 某个鼠标按键被按下
  • onmousemove 鼠标被移动
  • onmouseout 鼠标从某元素移开
  • onmouseover 鼠标被移到某元素之上
  • onmouseup 某个鼠标按键被松开
  • onreset 重置按钮被点击
  • onresize 窗口或框架被调整尺寸
  • onselect 文本被选定
  • onsubmit 提交按钮被点击
  • onunload 用户退出页面

event对象有哪些属性或者方法

  • type:事件类型。用来描述这个事件是什么类型的,比如onclick的事件类型为click。
  • srcElement/target:事件源,就是发生事件的元素; FF下是target,IE下是srcElement
  • cancelBubble:一个布尔属性,把它设置为true的时候,将停止事件进一步起泡到包容层次的元素;(e.cancelBubble = true; 相当于 e.stopPropagation();) 。FF下是后者。
  • keyCode: 这个不陌生了吧。也非常的常用,用来判断你按下了哪个键
  • attachEvent(), detachEvent()/addEventListener(), removeEventListener:为指定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型,第二个是事件处理函数。在 attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素;

当然还有其他的一些属性,我这里列出来的都是最常用的。比如还有:
button、 clientX,clientY、offsetX,offsetY layerX,layerY、x,y pageX,pageY、altKey,ctrlKey,shiftKey、fromElement,toElement、screenX、screenY。


Event altKey、ctrlKey、shiftKey属性

  • event.altKey
    • 功能:检测事件发生时Alt键是否被按住了。
    • 语法:event.altKey
    • 取值:true | false
    • 说明:
      altKey属性为true表示事件发生时Alt键被按下并保持,为false则Alt键没有按下。
    • altKey属性可结合鼠标或键盘使用,多用于制作一些快捷操作方式。
  • event.ctrlKey
    • 功能:检测事件发生时Ctrl键是否被按住了。
    • 语法:event.ctrlKey
    • 取值:true | false
    • 说明: ctrlKey属性为true表示事件发生时Ctrl键被按下并保持,为false则Ctrl键没有按下。
    • ctrlKey属性可结合鼠标或键盘使用,多用于制作一些快捷操作方式。
  • event.shiftKey
    • 功能:检测事件发生时Shift键是否被按住了。
    • 语法:event.shiftKey
    • 取值:true | false
    • 说明: shiftKey属性为true表示事件发生时Shift键被按下并保持,为false则Shift键没有按下。
    • shiftKey属性可结合鼠标或键盘使用,多用于制作一些快捷操作方式。
I Try Do

pm2部署服务器

发表于 2017-02-18 | 分类于 node.js | | 阅读次数

基本使用

  • 本地和服务器安装pm2

    1
    $ npm install -g pm2
  • 使用pm2启动应用

    1
    $ pm2 start xxx.js
  • 开发中启动,代码变更后自动重启应用

    1
    $ pm2 start xxx.js --watch

cluster模式

默认情况下pm2是以fork模式启动应用的,如果以cluster模式启动的话,则可以使用pm2自带的负载均衡、零间断重启等功能。

1
$ pm2 start xxx.js -i 4

上面的命令会以cluster模式启动4个应用进程,并自动为它们提供负载均衡,并且可以使用gracefulReload达到更新应用时不中断服务的效果。

升级pm2

1
2
$ npm install -g pm2@latest
$ pm2 updatePM2

部署

接下来需要建立一个部署的配置文件,这个文件在本机(操作发布的机器)和服务器上都需要有,因此最好放入Git版本管理中,并且推送到远程代码库(Git服务器)。

切换到项目目录下,然后执行

1
$ pm2 ecosystem

即可得到一个示例json文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"apps" : [{
"name" : "API",
"script" : "app.js",
"env": {
"COMMON_VARIABLE": "true"
},
"env_production" : {
"NODE_ENV": "production"
}
},{ //没有这个环境可以删除掉
"name" : "WEB",
"script" : "web.js"
}],
"deploy" : {
"production" : {
"user" : "node",//登录账号
"host" : "212.83.163.1",//服务器地址
"ref" : "origin/master",//git 分支
"repo" : "git@github.com:wuyuedefeng/node-china.club.git",//git地址
"path" : "/var/www/production",//服务器项目目录
"post-deploy" : "pm2 startOrRestart ecosystem.json5 --env production"
},
"dev" : {
"user" : "node",
"host" : "212.83.163.1",
"ref" : "origin/master",
"repo" : "git@github.com:repo.git",
"path" : "/var/www/development",
"post-deploy" : "pm2 startOrRestart ecosystem.json5 --env dev",
"env" : {
"NODE_ENV": "dev"
}
}
}
}

  • apps.name和apps.script应该与PM2识别应用有关,后续执行pm2 restart的时候可以对应到进程(未证实)
  • deploy中可以含有多个环境,需要能够通过SSH(公钥认证)登录服务器
  • web目录并不是真正的放版本库文件的目录,PM2会再建立一个source子目录,这个才是真正放代码的目录
  • post-deploy是指代码部署完之后执行的命令,这里以Node.js为例子,执行依赖安装,然后重启PM2中的进程 然后就可以使用了

首先需要安装一下

1
$ pm2 deploy ecosystem.json production setup

如果已经安装可以运行下面这个命令进行部署(需要添加服务器的ssh key到github上)

1
$ pm2 deploy ecosystem.json production

大功告成!

I Try Do

服务器环境安装nginx: Ubuntu14.04

发表于 2017-02-17 | 分类于 nginx | | 阅读次数

安装

服务器环境: Ubuntu14.04

apt-get 安装

1
2
$ [sudo] apt-get update  
$ [sudo] apt-get install nginx

配置文件: (配置文件所在目录:/etc/ngnix/sites-enabled/)

1
2
$ cd /etc/nginx/nginx.conf
$ vim nodeChinaClub.conf

写入:

1
2
3
4
5
6
7
8
9
10
server {
server_name itrydo.com;
location / {
proxy_pass http://localhost:8088;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}

使配置生效:

1
service nginx reload

nginx location模块–匹配规则

Location语法语法:location [=|~|~*|^~] /uri/ { … }

  • = –> 开头表示精确匹配
  • ^~ –> 开头表示uri以某个常规字符串开头,理解为匹配url路径即可。 nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。
  • ~ –> 开头表示区分大小写的正则匹配
  • ~* –> 开头表示不区分大小写的正则匹配
  • !~和!~* –> 分别为区分大小写不匹配及不区分大小写不匹配的正则
  • / –> 通用匹配,任何请求都会匹配到。

多个location配置的情况下匹配顺序为:

首先匹配=,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

例子,有如下匹配规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
location = / {
#http://localhost/ 访问根目录/
#规则A
}


location = /login {
#http://localhost/login
#规则B
}



location ^~ /static/ {
#http://localhost/static/a.html
#http://localhost/static/c.png 则优先匹配到 规则C
#规则C
}

#http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,
location ~ \.(gif|jpg|png|js|css)$ {

#规则D
}


location ~* \.png$ {
#http://localhost/a.PNG 则匹配规则E,而不会匹配规则D,因为规则E不区分大小写。
#规则E
}


http://localhost/a.xhtml 不会匹配规则F和规则G,
http://localhost/a.XHTML 不会匹配规则G,因为不区分大小写。
规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
location !~ \.xhtml$ {
#规则F
}


location !~* \.xhtml$ {
#规则G
}

访问http://localhost/category/id/1111 最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,
比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。
location / {
#http://localhost/register
#规则H
}

所以实际使用中,个人觉得至少有三个匹配规则定义,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}

# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}

#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080/
}

对于以上基础推荐配置,有一个补充,就是关于转发有一点需要注意。例如下面配置,对一个目录转发:

1
2
3
4
5
6
location ^~ /outer/ {
#case A: url最后以/结尾
proxy_pass http://tomcat:8080/
#case B: url最后没有/
#proxy_pass http://tomcat:8080
}

关键在于最后的/,访问localhost/outer/in.html,其中case A会转发到tomcat:8080/in.html, 而case B会转发到tomcat:8080/outer/in.html,所以务必注意了。

参考自:http://www.cnblogs.com/linjiqin/p/5532119.html

nginx upstream模块–负载均衡

upstream模块相关说明

  1. upstream模块应放于nginx.conf配置的http{}标签内
  2. upstream模块默认算法是wrr (权重轮询 weighted round-robin)

一、分配方式 Nginx的upstream支持5种分配方式,下面将会详细介绍,其中前三种为Nginx原生支持的分配方式,后两种为第三方支持的分配方式。

1. 轮询

轮询是upstream的默认分配方式,即每个请求按照时间顺序轮流分配到不同的后端服务器,如果某个后端服务器down掉后,能自动剔除。

1
2
3
4
5
upstream backend {
server 192.168.1.101:8888;
server 192.168.1.102:8888;
server 192.168.1.103:8888;
}

2. weight

轮询的加强版,即可以指定轮询比率,weight和访问几率成正比,主要应用于后端服务器异质的场景下。

1
2
3
4
5
upstream backend {
server 192.168.1.101 weight=1;
server 192.168.1.102 weight=2;
server 192.168.1.103 weight=3;
}

3. ip_hash

每个请求按照访问ip(即Nginx的前置服务器或者客户端IP)的hash结果分配,这样每个访客会固定访问一个后端服务器,可以解决session一致问题。

1
2
3
4
5
6
upstream backend {
ip_hash;
server 192.168.1.101:7777;
server 192.168.1.102:8888;
server 192.168.1.103:9999;
}

注意:

  1. 当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。
  2. 导致负载不均衡。

4. fair

fair顾名思义,公平地按照后端服务器的响应时间(rt)来分配请求,响应时间短即rt小的后端服务器优先分配请求。如果需要使用这种调度算法,必须下载Nginx的upstr_fair模块。

1
2
3
4
5
6
upstream backend {
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
fair;
}

5. url_hash,目前用consistent_hash替代url_hash

与ip_hash类似,但是按照访问url的hash结果来分配请求,使得每个url定向到同一个后端服务器,主要应用于后端服务器为缓存时的场景下。

1
2
3
4
5
6
7
upstream backend {
server 192.168.1.101;
server 192.168.1.102;
server 192.168.1.103;
hash $request_uri;
hash_method crc32;
}

其中,hash_method为使用的hash算法,需要注意的是:此时,server语句中不能加weight等参数。

提示:url_hash用途cache服务业务,memcached,squid,varnish。特点:每个rs都是不同的。


设备状态

从上面实例不难看出upstream中server指令语法如下:server address [parameters]

参数说明:

  • server:关键字,必选。
  • address:主机名、域名、ip或unix socket,也可以指定端口号,必选。
  • parameters:可选参数,可选参数如下:

    1. down:表示当前server已停用
    2. backup:表示当前server是备用服务器,只有其它非backup后端服务器都挂掉了或者很忙才会分配到请求。
    3. weight:表示当前server负载权重,权重越大被请求几率越大。默认是1.
    4. max_fails和fail_timeout一般会关联使用,如果某台server在fail_timeout时间内出现了max_fails次连接失败,那么Nginx会认为其已经挂掉了,从而在fail_timeout时间内不再去请求它,fail_timeout默认是10s,max_fails默认是1,即默认情况是只要发生错误就认为服务器挂掉了,如果将max_fails设置为0,则表示取消这项检查。

参考自:http://www.cnblogs.com/linjiqin/p/5494783.html

80端口部署多个静态网页

https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-virtual-hosts-on-ubuntu-14-04-lts

I Try Do

使用vue-cli初始化vue项目

发表于 2017-02-17 | 分类于 vue | | 阅读次数

init

1
2
3
4
$ npm install -g vue-cli
$ vue init webpack demo
$ cd demo
$ npm install

demo 是这个示例项目的名字

现在看到目录结构如下

  • build 目录是一些webpack的文件,配置参数什么的,一般不用动
  • src 源码文件夹,基本上文件都应该放在这里。
  • static 生成好的文件会放在这个目录下。
  • test 测试文件夹,测试都写在这里
  • .babelrc babel编译参数,vue开发需要babel编译
  • .editorconfig 看名字是编辑器配置文件,不晓得是哪款编辑器,没有使用过。
  • .eslintrc.js eslint配置文件,用以规范团队开发编码规范,大中型项目很有用
  • .gitignore 用来过滤一些版本控制的文件,比如node_modules文件夹
  • index.html 主页
  • package.json 项目文件,记载着一些命令和依赖还有简要的项目描述信息
  • README.md 介绍自己这个项目的,想怎么写怎么写。

添加支持 sass

  • 安装依赖包
    1
    2
    npm install node-sass --save-dev
    npm install sass-loader --save-dev
  • style中添加lang="scss"
    1
    2
    3
    // 添加scoped用来生成唯一样式 指定内部样式只对当前组件生效, 不添加scoped样式将作用于全局
    <style lang="scss" scoped>
    </style>

使用 vue-router 实现单页路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

const router = new Router({
routes: [
{
path: '/login',
name: 'login',
meta: { Auth: false },
component: function (resolve) {
require(['views/profiles/Login.vue'], resolve)
},
beforeEnter: (to, from, next) => {
next();
}
},
{
path: '/',
name: 'main',
meta: { Auth: true },
component: function (resolve) {
require(['components/Main'], resolve)
},
children: [
{
path: '',
name: 'index',
component: function (resolve) {
require(['views/Index'], resolve)
}
},
// 用户管理
{
// 以 / 开头的嵌套路径会被当作根路径
path: '/users',
name: 'users',
component: function (resolve) {
require(['views/users'], resolve)
}
},
{
path: '/users/:userId/edit',
name: 'userEdit',
component: function (resolve) {
require(['views/users/userEdit'], resolve)
}
}
]
},
{ path: '*', redirect: '/' },
]
});

router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.Auth) /* && is not login */) {
next({
path: '/login',
query: {redirect: to.fullPath}
})
} else{
next();
}
})

export default router;

文件: 按需加载

用 vuex 管理我们的数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 导入vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

//导入modules
import users from './modules/users'
var store = new Vuex.Store({
state: {
},
actions: {
},
mutations: {
},
modules: {
users
}
})

集成axios到项目中

创建http.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import axios from 'axios'
var store = null;

const instance = axios.create();

instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

// Add a request interceptor
instance.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});

// Add a response interceptor
instance.interceptors.response.use(function (response) {
// Do something with response data
if(response.data.code != 10000){
var error = new Error(response.data && response.data.msg);
// alert(error);
if(response.data.code == '50007' || response.data.code == '50004'){
// store && store.commit('logout');
}
throw error;
}
return response;
}, function (error) {
// Do something with response error
// alert(error);
return Promise.reject(error);
});

instance.install = function (Vue, options) {
if(options.store) {
store = options.store
}
Vue.prototype.$http = instance;
Vue.$http = instance;
};

export default instance;

usage:

eg: in main.js

1
2
3
import $http from './api/http'

Vue.use($http, {store});

then you can use in components

1
this.$http.get() //equal call axios instanse get

or in vuex

1
Vue.$http.get()

细节,编写自定义插件 请自行参考官方文档


main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './vuex/store'
import $http from './http'

Vue.use($http, {store});

/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})

图片路径问题

参考

配置alias

1
2
3
4
5
6
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'assets': path.resolve(__dirname, '../src/assets')
}
}

使用:

1
<img src="~asset/pic.png"></img>

如果配置了 vue html root

1
2
3
4
5
vue: {
html: {
root: path.resolve(__dirname, '../src/assets')
}
}

则可以在任何子目录中直接写

1
<img src="/pic.png"></img>

动态渲染的图片

如果是有规律的重复出现的组件通常通过 v-for 来渲染,通过数组或对象来插入数据。
比如

1
2
3
4
5
6
7
8
9
10
11
const  data = [{
title: 'title1',
img: '../assets/pic01.png'
}, {
title: 'title2',
img: '../assets/pic02.png'
}]

<my-compo v-for="item in data">
<img :src="item.img"></img>
</my-compo>

这样的问题是 webpack 不会对 src 做任何操作,会原样输出导致 404 错误

1
<img src="../assets/pic01.png"></img>

这是因为渲染操作是在浏览器完成的。
解决办法是使用 require 引入图片让 webpack 在 build 的时候就知道要处理它们

1
2
3
4
5
6
7
const  data = [{
title: 'title1',
img: require('../assets/pic01.png')
}, {
title: 'title2',
img: require('../assets/pic02.png')
}]

生成dist相对路径[默认绝对路径]

修改 /config/index.js

build config

1
assetsPublicPath: '/'

改为

1
assetsPublicPath: './'

dev 和 pro 配置不同的变量

比如 api host
首先,我们分别找到下面的文件:

1
2
/config/dev.env.js
/config/prod.env.js

dev.en.js文件。代码如下:

1
2
3
4
5
6
7
var merge = require('webpack-merge')
var prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
API_ROOT: '"http://test.itrydo.com/api"'
})

prod.env.js文件:

1
2
3
4
module.exports = {
NODE_ENV: '"production"',
API_ROOT: '"http://www.baidu.com/api"'
}

在代码中调用设置好的参数:

1
2
// 配置API接口地址
var root = process.env.API_ROOT

在经过这样的配置之后,我们在运行

1
npm run dev

的时候,跑的就是测试接口。而我们运行

1
npm run build

打包项目的时候,打包的是服务器正式接口,我们就不用调来调去得了。

asset img path

参考

build/webpack.base.conf.js 如果配置了 alias

1
2
3
4
5
6
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
'assets': path.resolve(__dirname, '../src/assets')
}
}

则可以在任何子目录中直接写

1
<img src="~assets/pic.png"></img>

动态渲染的图片

如果是有规律的重复出现的组件通常通过 v-for 来渲染,通过数组或对象来插入数据。
比如

1
2
3
4
5
6
7
8
9
10
11
const  data = [{
title: 'title1',
img: '../assets/pic01.png'
}, {
title: 'title2',
img: '../assets/pic02.png'
}]

<my-compo v-for="item in data">
<img :src="item.img"></img>
</my-compo>

这样的问题是 webpack 不会对 src 做任何操作,会原样输出导致 404 错误

1
<img src="../assets/pic01.png"></img>

这是因为渲染操作是在浏览器完成的。
解决办法是使用 require 引入图片让 webpack 在 build 的时候就知道要处理它们

1
2
3
4
5
6
7
const  data = [{
title: 'title1',
img: require('../assets/pic01.png')
}, {
title: 'title2',
img: require('../assets/pic02.png')
}]

css自动加前缀

https://github.com/MoOx/postcss-cssnext

压缩支持gzip

编辑config/index

1
productionGzip: true

webpack忽略某个文件夹的编译

编辑build中的webpack.base.conf.js

1
2
3
4
5
6
7
8
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {}
},
module: {
noParse: [/videojs-contrib-hls/], // 添加该行
rules: []
}


问题列表

  • vue-cli build后 Webfonts字体路径引用出错的问题
    找到 webpack.base.conf.js替换

    1
    2
    3
    4
    5
    6
    7
    8
    {
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    query: {
    limit: 10000,
    name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
    }
    }

    替换为

    1
    2
    3
    4
    {
    test: /\.(woff|woff2|eot|ttf|svg)(\?.*$|$)/,
    loader: 'url-loader?importLoaders=1&limit=100000'
    }

解决方法参考自 github

1…34
wsen

wsen

不积跬步无以至千里

38 日志
19 分类
20 标签
© 2019 wsen
由 Hexo 强力驱动
主题 - NexT.Pisces