zhongxia245 / blog Goto Github PK
View Code? Open in Web Editor NEW这是一个Blog, 如果喜欢可以订阅,是Watch, 不是 Star 哈。。。
Home Page: https://zhongxia245.github.io/blog/
这是一个Blog, 如果喜欢可以订阅,是Watch, 不是 Star 哈。。。
Home Page: https://zhongxia245.github.io/blog/
时间:2016-09-09 14:15:41
作者:zhongxia
源码地址:https://github.com/ajaxorg/ace
Ace.js是一款开源的 web编辑器,内置强大的代码提示,快捷键功能。具体了解看官网介绍。
由于在产品中,需要用到 输入 数据库名.
弹出数据库下所有表的提示框, 方便用户的使用。
如图:
在ACE.js上进行扩展,异步获取到表名数据,然后使用ACE 自带的提示框,提示, 这个是一个比较好的解决方案,但是需要去了解下ACE自定义提示是如何实现的,然后进行扩展。 目前还没有研究透。
参考文章
如果遇到
xxx.
这种情况,就把关键字xxx
取出,然后去Ajax获取表名列表。
自己实现一个提示框的插件,然后在指定的位置弹出。
//获取当前焦点的位置(提示框使用 position:fixed)
let renderer = editor.renderer;
var pos = renderer.$cursorLayer.getPixelPosition(this.base, true);
var rect = editor.container.getBoundingClientRect();
pos.top += rect.top - renderer.layerConfig.offset;
pos.left += rect.left - editor.renderer.scrollLeft;
pos.left += renderer.gutterWidth;
时间:2016-11-01 17:33:19
作者:zhongxia
原文地址:#41
故事是这样的,有一个auth 的认证接口, validate_auth 的接口。 后端使用 go语言写的。 正确的接口地址是 127.0.0.1:3000/api/auth/validate_token/
【注意,完成的接口地址有 / 】,至于为什么要多一个 /
这个就是后端的疏忽的。
多一个 / 到底会引发什么问题呢?
注意 http://localhost:3000/api/auth/validate_token 中的 validate_token 是一个目录, / 才是接口名称。
var authHeaders = JSON.parse(localStorage.authHeaders)
fetch("http://localhost:3000/api/auth/validate_token", {
method: "GET",
headers: {
"authorization": "Bearer "+authHeaders.access_token,
}
})
.then(function (res) {
if (res.ok) {
alert("Perfect! Your settings are saved.");
console.log(res.json())
} else if (res.status == 401) {
alert("Oops! You are not authorized.");
}
区别就是, safari 不会 访问的时候,不会做一个跳转,但是 chrome 会做一次跳转。
如果是 auth 认证, 在 chrome 认证就可以通过,但是在 safari 认证就通不过。
后端接口需要写完善一点,否则引发一些这种坑爹的BUG, 很难定位。
做前端的知道跨域这个问题,现在前后端开发分离了,然后开发联调的时候,我们本地的前端项目访问后端的接口时,就报跨域问题。 跨域问题 有多种解决方案,比如 CORS跨域,JSONP,HTML5 的 postMessage 等。
当遇到以下情况,则可以简单的使用 关闭Chrome 安全策略跨域
只有开发时用这个,其他时候,就不要使用这种方式了
切记切记,使用这个打开之前,判断下chrome是否都关闭掉了。
mac 下 , command+q 就退出了
window下,如果不确定是否全部退出,打开任务管理器, 找下 chrome 是否还有打开的。有时候window下,明明感觉已经全部关闭了,可是打开之后,发现居然居然居然没有用。然后打开任务管理器一看,原来还有未关闭的。 只是图标没有在任务栏。
直接用命令行打开,目前使用该命令打开还没有遇到啥问题,百试百灵。 safari 也一样
//chrome 浏览器 open -a "Google Chrome" --args --disable-web-security --user-data-dir //safari 浏览器 open -a '/Applications/Safari.app' --args --disable-web-security --user-data-dir
这里的chrome.exe 地址根据自己安装路径来, 测试过 chrome45,48,53版本。
45版本 只需要--disable-web-security
48,53版本需要 额外添加--user-data-dir
"C:\Users\UserName\AppData\Local\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir
//不知道chrome.exe 地址的话
右键chrome图标-->属性-->如下图-->图中 目标 就是文件的位置了,直接复制出来即可
chrome53 版本,设置这样好像不起作用。【操作系统 window7,64位】,只能用命令行
注意:chrome48,版本需要添加上 --user-data-dir
//快捷方式后面 空一格,再加上
--disable-web-security --user-data-dir
chromium-browser --disable-web-security
作者:Pete Hunt
作者:题叶
作者:ruanyf
作者:VaJoy Larn
作者:zhouweicsu
译者:前端外刊评论
译者:前端外刊评论
作者:alloyteam
作者:alloyteam
译者:CSS魔法
作者:小凡哥
作者:chemdemo
作者:chemdemo
作者:icepy
作者:icepy
作者:wyvernnot
作者:紅白
来源:ACGTOFE
作者:hsw
译者:cssmagic
来源:知乎
来源:Medium
作者:erikras
作者:chemdemo
作者:大额_skylar
来源:开源**
作者:lhc
来源:Modus Create
作者:Drew Machat
来源:preboot
来源:preboot
来源:AngularClass
作者:yang_j_j
作者:Cheng_Gu
作者:王伟嘉
来源:vue官方
作者:Coffcer
作者:guowenfh
作者:JsAaron
作者:离尘不理人
作者:vingojw
作者:djyde
时间:2016-10-15 12:48:54
作者:zhongxia
也就两三天没有关注前端新技术,FaceBook 就开源了一个新的包管理器,叫做Yarn。 (搞不懂为什么叫这个名字,和大数据的yarn 重名了)
Yarn 开源后,(10.12~10.15 3天)没有多少天就已经有了 13817 star 了。 看来还是很火爆的。
yarn 是一个包管理器, 和npm的作用是一样的,但是解决了一些npm的痛点。
在还没包管理器的时候,JS工程师常常依赖于存储在他们项目中或者放在CDN上面的少量代码段。第一个主要的JS包管理器 npm 在Node.js被引用后不久就搭建起来了,并且迅速成为世界上最受欢迎的包管理器之一。上千个新的开源项目被建立了,工程师们也比以往分享了更多的代码。
那 yarn 解决了上面这些问题了吗?
小改进
如果有了npm, 那么安装很简单【有安装nodejs,就会有npm, 所以目前直接使用 npm 安装问题不大】
//使用 npm 来安装
npm install -g yarn
//如果显示了yarn 版本,代表安装成功
yarn --version
//和 npm init 使用一样
yarn init
yarn add jquery
yarn add [email protected]
yarn upgrade jquery
yarn remove jquery
测试了 --save --save-dev 会报错, 已经已经没有了这两个参数
如果之前下载过了,则会缓存起来,缓存起来的可以使用离线安装
yarn add jquery --offline
//查看安装的依赖包
yarn ls
//告诉你,为什么一个依赖被安装到项目中
//yarn why [name]
yarn.lock 是使用 yarn 安装依赖的时候,自动生成的文件,不要去编辑它。
这个是用来依赖的正确性,快速可靠安装的;是执行cli的时候自动生成的,在项目的根目录下,需要保留!!!!不要编辑它,这是自动生成的
在其他电脑初始化,必须记得把package.json和yarn.lock复制过去,简直就是秒下载【缓存机制】
时间:2016-09-14 09:41:53
作者:zhongxia
背景:需要在页面上实现多点触控,但是在PC端上的Chrome上,模拟设备,目前没有找到实现多点触控的方法。因此只能找一下是否有远程调试真机页面的功能。 这里就整理以下,如何使用用Chrome远程调试真机访问的页面
要开始远程调试,你需要:
说白了,android机子一部(微信不行),PC端chrome浏览器,USB线
请按照以下说明来设置安卓设备:
不同的手机,打开开发者模式的方式不一样。
这边以小米手机为例,默认情况下,开发者模式是隐藏的。
将你的安卓设备和电脑用 USB 线连接起来。
注意:如果你在 Windows 下进行开发,那么你需要为你的安卓设备安装驱动。具体可以参考安卓开发者网站上的 OEM USB Drivers
在 Chrome 中找到设备
在安卓设备上设置好远程调试后,在 Chrome 中找到你的设备。
在电脑端的 Chrome 里,在地址栏输入 chrome://inspect
。进入后确认 Discover USB devices
已经勾选了:
提示:你也可以从 Chrome menu > More tools > Inspect Devices 来进入 chrome://inspect
在你的设备上,会跳出一个警告,告诉你是否要允许在电脑端进行 USB 调试。选择 OK。注意:在远程调试时, Chrome 会阻止你的设备进入休眠状态。该特性对于调试相当有用,但在安全性上有所欠缺。所以在调试的时候要注意看好你的手机!
在电脑端,打开选项卡并启用 WebViews 调试后,chrome://inspect 页面会显示全部已连接的设备。
从 chrome://inspect 也卖弄查看已连接的设备
如果从 chrome://inspect 页面查找设备时遇到了问题,请参考 Troubleshooting 章节。
在页面 chrome://inspect 上,你可以加载 DevTools 并且调试你的远程浏览器。
要开始调试,请点击你希望调试的浏览器选项卡下面的 inspect。
接着你的电脑会加载新的 DevTools。在新的 DevTools 上,你可以在你的安卓设备上和选中的浏览器实时交互。
左边是手机上页面的实时情况,右边是Chrome开发工具,调试按照PC端怎么调试就怎么来。
注意:你设备的 Chrome 版本将会决定远程调试中 DevTools 的版本。由于这个原因,你在远程调试时使用的 DevTools 可能和你平常使用的不大一样。
下面是使用远程调试功能的一些提示:
pull request 是 开源协作是一个必须品, 是非常重要的。 要为开源库做贡献,就要需要使用该功能。 下面是从知乎上找到的一些资料,方便大家理解 pull request.
作者:beepony
链接:https://www.zhihu.com/question/21682976/answer/79489643
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
我尝试用类比的方法来解释一下 pull reqeust。想想我们中学考试,老师改卷的场景吧。
理解了 pull request 的含义和流程,具体操作也就简单了。以 Github 排名最高的 https://github.com/twbs/bootstrap 为例说明。
~ git clone https://github.com/beepony/bootstrap.git
~ cd bootstrap
~ git checkout -b test-pr
~ git add . && git commit -m "test-pr"
~ git push origin test-pr
以上就是 pull reqesut 的整个流程,希望对你有帮助~
记录下需要阅读学习的文章,阅读整理成自己理解的后,放到每日文章里面
请求某一个接口,然后后期可能换接口了。 如何转发接口呢?
解决该问题呢,可以用服务端来进行请求该接口,然后把返回值原封不动的返回即可。
下面是使用 NodeJs + Express 来实现转发Ajax请求的代码
var express = require('express');
var router = express.Router();
var request = require('request');
/**
* NodeJs 转发 接口请求
* 使用方式:127.0.0.1:23018/request?url=完整的接口地址
*/
router.get('/', function (req, res, next) {
req.pipe(request.get(req.query.url, {
query: req.query,
form: req.body
})).pipe(res);
});
module.exports = router;
收集一些优秀的模板源码,方便如何要从头实现一个项目,可以直接从模板里面直接进行快速开发,省去搭建框架的时间。
收集的总类可能包含 Jquery类的模板, BootStrap,React, Vue, Ng , Rn 等等, 不局限于前端。
提供一个效果图,然后源码保存在百度云,这里放一个分享链接。
时间:2016-09-05 15:23:30
作者:zhongxia
webpack文档地址:http://webpack.github.io/docs/build-performance.html#sourcemaps
在开发环境,或者生产环境中,如果出现错误了,在浏览器中,因为代码从被Babel从JSX变成ES5的,代码调试起来很痛苦,因此webpack有了一个代码映射,把转换后的代码映射到之前自己写的代码。
英语水平有限,下面翻译可能存在问题,请帮忙指出。
devtool可选值:
module.exports = {
devtool: 'eval',
...
}
越好的源码映射,越慢
devtool: "source-map
" cannot cache SourceMaps for modules and need to regenerate complete SourceMap for the chunk. It’s something for production.
source-map
不能为 模块和需要重新生成的代码块 缓存SourceMaps,它适用于 生产环境。
devtool: "eval-source-map
" is really as good as devtool: "source-map", but can cache SourceMaps for modules. It’s much faster for rebuilds.
eval-source-map
和source-map
差不多,但是 可以为模块 缓存它可以更快的重建SourceMaps,它可以更快的重建SourceMaps
devtool: "eval-cheap-module-source-map
" offers SourceMaps that only maps lines (no column mappings) and are much faster.
eval-cheap-module-source-map
只为行(没有列映射)提供SourceMaps 并且 速度更快(相对于 source-map, eval-source-map)
devtool: "eval-cheap-source-map
" is similar but doesn’t generate SourceMaps for modules (i.e., jsx to js mappings).
eval-cheap-source-map
和eval-cheap-module-source-map
相似,但是不为模块 生成 SourceMaps(eg:jsx 到 js 的映射)
devtool: "eval
" has the best performance, but it only maps to compiled source code per module. In many cases this is good enough. (Hint: combine it with output.pathinfo: true.)
eval
有最好的性能,但是它只映射到每个模块编译源代码,在更多情况下是足够用的(提示:与output.pathinfo:true
结合使用)
相关知识
output.pathinfo
Include comments with information about the modules.
require(/* ./test */23)
Do not use this in production.
Default: false
The UglifyJsPlugin use SourceMaps to map errors to source code. And SourceMaps are slow. As you should only use this in production, this is fine. If your production build is really slow (or doesn’t finish at all) you can disable it with new UglifyJsPlugin({ sourceMap: false }).
UglifyJsPlugin会让 SourceMaps 映射到源码出现错误,速度变慢。所以把UglifyJsPlugin用于生产环境,这是很好的。
如果你生产环境构建很慢(或者玩不成),可以用new UglifyJsPlugin({ sourceMap: false }).
来禁用sourceMap。
时间:2016-09-04 00:03:30
转载:http://imweb.io/topic/560a6015c2317a8c3e086207
文章来自腾讯 imweb社区的文章, 阅读请移步原文: 【video标签在不同平台上的事件表现差异分析】
CreateTime:2016-09-06 20:07:17
Author:zhongxia
浏览器输入URL之后,发生了什么? 针对前端来说,最重要的是 http 和 浏览器渲染。底层硬件,网络通讯,后端的相关知识,这里就大概一概而过了。 这一篇主要讲解一下http相关方面的。
用户输入URL地址,浏览器会去解析URL地址,得到请求服务器地址,请求页面文件路径,以及请求参数
根据域名解析服务器的IP地址, ip地址是一串数据,不方便记忆,因此有了域名。
浏览器发出一个 HTTP协议的请求,组织了一个请求的数据包(走OSI七层模型,从应用层 到 最低层的数据链路层 的数据包层层封装,然后传到服务器在 层层解开)
请求头 和 请求正文之间有 一个空行,空行是 HTTP规定的消息头和消息体的分界线
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
三层架构(浏览器,web服务器,数据库),http 是用在 浏览器 和 web服务器之间通讯
两个核心(浏览器发出request请求, Web服务器response返回数据(text,xml,流等))
一个记住(HTTP是无状态的)
无状态是指_协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态_。即我们给服务器发送 HTTP 请求之后,服务器根据请求,会给我们发送数据过来,但是,发送完,不会记录任何信息。
keep-alive 也无法改变这个无状态
1、请求头:
我们现在通过谷歌浏览器来查看一下请求头:
以打开百度首页为例,然后在谷歌浏览器中打开“工具-开发者工具”,切换到network标签, 然后刷新页面:
上图中的Request Headers就是我们所需要的请求头。里面的内容全部是键值对。服务器拿到这些键值对后会对其进行分析。
我们再来重复一下常见请求头键值对的含义:
注:上面的这些指的是get请求的请求头。
2、响应头:
常见的响应头键值对的含义:
注: 之所以三个头是一个功能,是因为历史原因。不同的浏览器对这三个头支持的不同,一般来说这三个头要同时使用,以确保不同的浏览器都能实现控制缓存的功能
打开 boot2docker
可能报 docker@localhost's password: 的问题
解决方案:
boot2docker delete
rm -rf ~/.boot2docker/ ~/.ssh/id_boot2docker*
boot2docker init
boot2docker up
docker run ubuntu echo hello world
Javascript regular expression password validation having special characters
var regularExpression = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{6,16}$/;
说明
必须拥有数字和特殊字符,并且在6~16位之间
Without it, your current regex only matches that you have 6 to 16 valid characters, it doesn't validate that it has at least a number, and at least a special character. That's what the lookahead above is for.
(?=.*[0-9])
- Assert a string has at least one number;
(?=.*[!@#$%^&*])
- Assert a string has at least one special character.
时间:2016-10-17 14:59:38
作者:zhongxia
文章数据来源于网络,可能存在变动,但是原理是一样的。
大家都知道http 中 存在 GET 和 POST 这两种最常用的请求方式。(PUT,DELETE不在本文讨论范围之内)
误解:HTTP 协议下的 Get 请求参数长度是有大小限制的,最大不能超过XX,而 Post 是无限制的。
1、首先即使有长度限制,也是限制的是整个 URI 长度,而不仅仅是你的参数值数据长度。
2、HTTP 协议从未规定 GET/POST 的请求长度限制是多少。
*以下内容摘自 《关于 HTTP GET/POST 请求参数长度最大值的一个理解误区》, 文章时间为 2013年的。可能以当前最新的浏览器有出入 *
The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET-based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).
Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.
3、所谓的请求长度限制是由浏览器和 web 服务器决定和设置的,各种浏览器和 web 服务器的设定
均不一样,这依赖于各个浏览器厂家的规定或者可以根据 web 服务器的处理能力来设定。
The limit is in MSIE and Safari about 2KB, in Opera about 4KB and in Firefox about 8KB, (255 bytes if we count very old browsers) . We may thus assume that 8KB is the maximum possible length and that 2KB is a more affordable length to rely on at the server side and that 255 bytes is the safest length to assume that the entire URL will come in.
If the limit is exceeded in either the browser or the server, most will just truncate the characters outside the limit without any warning. Some servers however may send a HTTP 414 error. If you need to send large data, then better use POST instead of GET. Its limit is much higher, but more dependent on the server used than the client. Usually up to around 2GB is allowed by the average webserver. This is also configureable somewhere in the server settings. The average server will display a server-specific error/exception when the POST limit is exceeded, usually as HTTP 500 error.
IE 和 Safari 浏览器 限制 2k
Opera 限制4k
Firefox 限制 8k(非常老的版本 256byte)
如果超出了最大长度,大部分的服务器直接截断,也有一些服务器会报414错误。
HTTP 1.1 defines Status Code 414 Request-URI Too Long for the cases where a server-defined limit is reached. You can see further details on RFC 2616. For the case of client-defined limits, there is no sense on the server returning something, because the server won't receive the request at all.
The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret. This rare condition is only likely to occur when a client has improperly converted a POST request to a GET request with long query information, when the client has descended into a URI "black hole" of redirection (e.g., a redirected URI prefix that points to a suffix of itself), or when the server is under attack by a client attempting to exploit security holes present in some servers using fixed-length buffers for reading or manipulating the Request-URI.
** 以下内容摘自《GET请求中URL的最大长度限制总结》, 文章内容是 2016年9月,相对比较符合当前的最新现状。 **
在网上查询之后,浏览器和服务器对url长度都有限制,现总结如下。
1、IE
IE浏览器(Microsoft Internet Explorer) 对url长度限制是2083(2K+53),超过这个限制,则自动截断(若是form提交则提交按钮不起作用)。
2、firefox
firefox(火狐浏览器)的url长度限制为 65 536字符,但实际上有效的URL最大长度不少于100,000个字符。
3、chrome
chrome(谷歌)的url长度限制超过8182个字符返回本文开头时列出的错误。
4、Safari
Safari的url长度限制至少为 80 000 字符。
5、Opera
Opera 浏览器的url长度限制为190 000 字符。Opera 9 地址栏中输入190 000字符时依然能正常编辑。
1、Apache
Apache能接受url长度限制为8 192 字符
2、IIS
Microsoft Internet Information Server(IIS)能接受url长度限制为16 384个字符。
这个是可以通过修改的(IIS7)
configuration/system.webServer/security/requestFiltering/requestLimits@maxQueryStringsetting.<requestLimits maxQueryString="length"/>
3、Perl HTTP::Daemon
Perl HTTP::Daemon 至少可以接受url长度限制为8000字符。Perl HTTP::Daemon中限制HTTP request headers的总长度不超过16 384字节(不包括post,file uploads等)。但当url超过8000字符时会返回413错误。
这个限制可以被修改,在Daemon.pm查找16×1024并更改成更大的值。
4、ngnix
可以通过修改配置来改变url请求串的url长度限制。
client_header_buffer_size 默认值:client_header_buffer_size 1k
large_client_header_buffers默认值 :large_client_header_buffers 4 4k/8k
由于jsonp跨域请求只能通过get请求,url长度根据浏览器及服务器的不同而有不同限制。
若要支持IE的话,url长度限制为2083字符,若是中文字符的话只有2083/9=231个字符。
若是Chrome浏览器支持的最大中文字符只有8182/9=909个。
CreateTime:2016-09-07 07:43:45
收集一些优秀的面试题,汇总在这里,方便以后阅读, 没有特别说明,即有自带答案!
原文地址:#22 欢迎star
本教程,使用Mac电脑进行演示。 常规的Chrome打印文件会比较大。 只有一个A4页面的内容,打印出来居然有7M,吓死了。 下面介绍如何不用第三方工具来缩放PDF大小。
可以采用 black & white 和 reduce size 这两种选一种模式, black & white 会造成一部分外观会没掉。 reduce size 就是压缩大小
PDF大小大大的减少了。
fetch(url, {method: 'GET', header: {'Content-Type': 'text/plain'}})
.then(res=> res.json())
.then(data=> {
console.log("data", data)
data = data || {}
that.setState({articleList: data || []})
})
.catch(function (err) {
console.log("err", err)
that.setState({articleList: []})
});
TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:28193:8)
at XMLHttpRequest.dispatchEvent (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:14591:15)
at XMLHttpRequest.setReadyState (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:29573:6)
at XMLHttpRequest.__didCompleteResponse (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:29431:6)
at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:29506:52
at RCTDeviceEventEmitter.emit (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:13428:23)
at MessageQueue.__callFunction (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:11999:23)
at http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:11906:8
at guard (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:11857:1)
at MessageQueue.callFunctionReturnFlushedQueue (http://localhost:8081/index.ios.bundle?platform=ios&dev=true&hot=true:11905:1)
CreateTime:2016-05-17 11:55
UpdateTime:2016-09-02 16:35
由于这篇文章只写了如何把CSS打包成一个CSS文件,没有讲解如何打包成多个CSS文件,经简友提点,这里添加上了 打包成多个CSS文件的方法。
webpack 把所有的资源都当成了一个模块, CSS,Image, JS 字体文件 都是资源, 都可以打包到一个 bundle.js 文件中.
但是有时候需要把样式 单独的打包成一个文件, 然后放到 CND上, 然后缓存到浏览器客户端中
这个操作很简单的,只需要一个插件就好了,就是extract-text-webpack-plugin
npm install extract-text-webpack-plugin --save-dev
首先require一下
var ExtractTextPlugin = require("extract-text-webpack-plugin");
plugins里面添加
new ExtractTextPlugin("styles.css"),
实例:
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new ExtractTextPlugin("styles.css"),
],
modules里面对css的处理修改为
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader","css-loader")
},
千万不要重复了,不然会不起作用的
我这里如下:
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader","css-loader")
},
{
test: /\.scss$/,
loader: "style!css!sass"
},
{
test: /\.less$/,
loader: "style!css!less"
},
]
},
require('../less/app.less');
require('./bower_components/bootstrap-select/dist/css/bootstrap-select.min.css');
require('./bower_components/fancybox/source/jquery.fancybox.css');
打包一个文件,只需要常规的在入口的js文件引用 css文件即可, 打包成多个CSS文件,可以设置多个CSS入口,让webpack用 loader去打包。 和分割单独打包js文件一样。下面有两个例子。【例子来源】
// 使用webpack 打包单独的postcss语法的css文件
/* webpack.config.js */
var precss = require('precss');
var cssnext = require('cssnext');
var autoprefixer = require('autoprefixer');
var cssnano = require('cssnano');
var Ex = require('extract-text-webpack-plugin');
module.exports = {
entry: './【path】/index.js',
/* index.js 里 require('./【name】.css');就好 我在看看文档是不是直接不用引入js文件 */
output: {
filename: 'index.js'
},
module: {
loaders: [{
test: /\.css$/,
loader: Ex.extract('style-loader', 'css-loader!postcss-loader') /*这里的写法注意下 */
}]
},
postcss: function() {
return [autoprefixer, cssnext, precss, cssnano]
},
plugins: [
new Ex("【name】.css")
]
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// 使用webpack 打包单独的多个postcss语法的css文件
var precss = require('precss');
var cssnext = require('cssnext');
var autoprefixer = require('autoprefixer');
var cssnano = require('cssnano');
var Ex = require('extract-text-webpack-plugin');
var webpack = require('webpack');
module.exports = {
entry: {
ac1: './src/actother.css',
ac2: './src/index.css'
},
output: {
filename: "[name].css"
},
module: {
loaders: [{
test: /\.css$/,
loader: Ex.extract('style-loader', 'css-loader!postcss-loader')
}]
},
postcss: function() {
return [autoprefixer, precss, cssnano, cssnext]
},
plugins: [
new Ex('[name].css')
]
}
时间:2016-11-02 15:06:18
在目前的时间节点上, 前端主流的框架有 React, Angular, Vue 这三个。 个人主要使用 React, 但是也需要理解下 Vue的使用 。 这里收藏一个通用的脚手架,以及常见的类库。
时间:2016-09-23 16:52:22
nginx -c nginx配置文件地址
ps -ef | grep nginx
//从容停止Nginx:
kill -QUIT 主进程号
//快速停止Nginx:
kill -TERM 主进程号
//强制停止Nginx:
pkill -9 nginx
nginx -s reload
修改了nginx的配置文件, 需要重启下 nginx服务。
如果更改了配置就要重启Nginx,要先关闭Nginx再打开?不是的,可以向Nginx 发送信号,平滑重启。 平滑重启命令:kill -HUP 主进称号或进程号文件路径 或者使用/usr/nginx/sbin/nginx -s reload
注意:修改了配置文件后最好先检查一下修改过的配置文件是否正 确,以免重启后Nginx出现错误影响服务器稳定运行。判断Nginx配置是否正确命令如下:
//检查指定的nginx配置文件,是否正确
nginx -t -c /usr/nginx/conf/nginx.conf
//检查默认的nginx配置文件
/usr/nginx/sbin/nginx -t
时间:2016-11-18 10:33:40
原文地址:《再谈 CSS 预处理器》
这个是目前看过文章中,最完整详细的介绍了 less, sass ,stylus 三者的异同点,因此在此记录下。
Less, Sass, Stylus 功能上 大体相同, 具体喜欢用哪一个,或者一个都不用, 这个看个人喜好。
CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题:
所以这就决定了 CSS 预处理器的主要目标:提供 CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性。这不是锦上添花,而恰恰是雪中送炭。
目前最主流的三个预处理器 Less、Sass 和 Stylus(按字母顺序排名)
我(原文作者)个人认为,Less 从语言特性的设计到功能的健壮程度和另外两者相比都有一些缺陷,但因为 Bootstrap 引入了 Less,导致 Less 在今天还是有很多用户。用 Less 可以满足大多数场景的需求,但相比另外两者,基于 Less 开发类库会复杂得多,实现的代码会比较脏,能实现的功能也会受到 DSL 的制约。比 Stylus 语义更清晰、比 Sass 更接近 CSS 语法,使得刚刚转用 CSS 预编译的开发者能够更平滑地进行切换。当初 Sass 并不支持 SCSS 语法,使得转投 Sass 成本较高,所以 Alexis Sellier 才萌生开发一个更「CSS」的预处理器的念头。大获成功以后反过来影响到了 Sass,迫使其也支持类似 CSS 语法的 SCSS。另外,Less 支持浏览器端编译,这无疑降低了开发门槛,使得很多非专业的开发者能够更快地上手(对于一些个人项目来说,能让项目跑起来就行,对前端的性能并没有专业工程师那么高的要求)。
Sass 在三者之中历史最久,也吸收了其他两者的一些优点。从功能上来说 Sass 大而全,语义明晰但是代码很容易显得累赘。主项目基于 Ruby 可能也是一部分人不选择它的理由(Less 开始也是基于 Ruby 开发,后来逐渐转到 less.js 项目中)。 Sass 有一个「事实标准」库——Compass,于是对于很多开发者而言省去了选择类库的烦恼,对于提升开发效率也有不小的帮助。
Stylus 的语法非常灵活,很多语义都是根据上下文隐含的。基于 Stylus 可以写出非常简洁的代码,但对使用团队的开发素养要求也更高,更需要有良好的开发规范或约定。Stylus 是前 Node.js 圈第一大神 TJ Holowaychuk 的作品,虽然他已经弃坑了,但是仍然有不小的号召力。和 Sass 有 Compass 类似,Stylus 有一个官方开发的样式库 nib,同样提供了不少好用的 mixin。对于比较有经验的开发者,用 Stylus 可能更会有一种畅快的感觉。总的来说用一个词形容 Stylus 的话,我会用「sexy」。
总的来说,三种预处理器百分之七八十的功能是类似的。Less 适合帮助团队更快地上手预处理代码的开发,而 Sass 和 Stylus 的差异更在于口味。比如有的人喜欢 jQuery 用一个 $ 做大部分的事,而另一些人觉得不一样的功能就该有明确的语义上的差别。在这里我不会做具体的推荐。当然,再次声明一下由于我个人接触 Less 开发比较多,所以可能遇到的坑也多一些,文中没有列出 Sass 和 Stylus 的问题并不代表他们没有。
有一些JavaScript的写法必须要规避。 开发尽量使用严格模式。IE10 以下不支持严格模式
"use strict";
两个 name 会被提升到 作用域的最前面 ,在严格模式下, 重复定义一个变量名会报错。
var testObj = {
prop1: 10,
prop2: 15,
prop1: 20
};
这里有两个 prop1 属性, 在严格模式下报错
工欲善其事,必先利其器。
webstrom作为前端的神器,了解webstrom如何使用是很有必要的,有一些快捷键可以大大加快我们编码的效率,以及舒适度。
常用的快捷键有
有了快捷键,能使各种常用操作刷刷刷的快速完成。但是在一字一字的敲代码的时候,并没有起到什么很大的作用。
那么是否支持自定义一些常用的代码片段,我输入几个字母,就可以直接生成一大串代码呢?
事实告诉我,这个是有的。
至于要定义什么代码片段呢?可以自己考虑。
我个人呢, 因为主要用 react 进行开发, 当然要各种创建react类啦, 生命周期啦。
比如我想创建一个 react 组件,手写效率太低,而且懒人是不会去记代码的。
因此。
/***************************************************
* 时间: $DATE$ $TIME$
* 作者: $AUTHOR$
* 说明:
*
***************************************************/
import React, { PropTypes } from 'react'
import classnames from 'classnames'
class $NAME$ extends React.Component {
constructor(prop){
super(prop);
this.state = {};
}
render(){
return (
<div>
</div>
);
}
}
$NAME$.propTypes = {
name: PropTypes.string
}
$NAME$.defaultProps = {
name: '基本信息'
}
export default $NAME$
这样我输入 rclass
就生成以下内容了
/***************************************************
* 时间: 10/10/16 16:18
* 作者: zhongxia
* 说明:
*
***************************************************/
import React, { PropTypes } from 'react'
import classnames from 'classnames'
class index extends React.Component {
constructor(prop){
super(prop);
this.state = {};
}
render(){
return (
<div>
</div>
);
}
}
index.propTypes = {
name: PropTypes.string
}
index.defaultProps = {
name: '基本信息'
}
export default index
时间:2016-09-01 23:25:04
这是一道经典的面试题,没有明确的答案,因为往某个方面深入讲解下去,都可以说好多好多。当然面试不同的岗位,可以侧重讲不同的方面。
_这里挖一个大坑,后期慢慢补上。_
有一些是移动端页面的文章
常规的给td 设置样式
table td{
overflow:hidden;
text-overflow:ellipsis;
}
表格该换行还是继续换行, 该占多大宽度还是占多大。 这个很坑爹,为什么不起作用呢?
CSS控制文本超出指定宽度后用省略号代替,CSS控制文本不换行。
一般的文字截断(适用于内联与块):
.text-overflow {
display:block;/*内联对象需加*/
width:31em;
word-break:keep-all;/* 不换行 */
white-space:nowrap;/* 不换行 */
overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
}
对于表格文字溢出的定义:
对于表格超出范围显示省略号
table{
width:30em;
table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用。 */
}
td{
width:100%;
word-break:keep-all;/* 不换行 */
white-space:nowrap;/* 不换行 */
overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
}
值 | 描述 |
---|---|
automatic | 默认。列宽度由单元格内容设定。 |
fixed | 列宽由表格宽度和列宽度设定。 |
inherit | 规定应该从父元素继承 table-layout 属性的值。 |
需要你注意的是,这个CSS样式只对单行的文字的效,如果你想把它用在多行上,也只有第一行有作用的。 这个写法只有IE会有“...”,
其它的浏览器文本超出指定宽度时会隐藏。
创建时间:2016-09-05 00:07:17
原文地址:http://fex.baidu.com/blog/2014/05/what-happen/阅读请出门左转 原文地址
这一篇文章写的知识基本都是很底层的东西,权当增长见识, 因为单纯的前端,这里的内容就需要花费很大的精力, 才有可能『搞懂』。
【这两天偷懒,没有自己自己去整理出文章,转载一些优秀的文章,放到这里】
为了编写方便,前面的介绍中将很多底层细节实现忽略了,比如:
内存相关
各种缓存
各种监控
微信的录音文件上传到微信服务器上,只能保存三天。 因此需要做一个转存到自己服务器,或者七牛云的操作。
...
/**
* 开始录音[省略了一部分代码]
*/
startRecord: function() {
var that = this;
if (!that._startRecordFlag) {
typeof wx !== "undefined" && wx.startRecord({
success: function(res) {
Logger.log("res", res)
if (res.errMsg == 'startRecord:ok') {
Logger.log("正在开始录音....")
that._startTime = new Date().getTime();
}
}
});
}
},
/**
* 结束录音,并上传
*/
stopRecord: function() {
that._startRecordFlag = false;
typeof wx !== "undefined" && wx.stopRecord({
success: function(res) {
//上传录音
wx.uploadVoice({
localId: res.localId,
isShowProgressTips: 1,
success: function(resUpload) {
//下载录音文件到服务器,转存起来
Model.downloadRecordAudio(resUpload.serverId, function(result) {
console.log(resUpload.serverId, result.path)
that.attachment = result.path;
// that.attachment = resUpload.serverId;
that.stopRecordCallback && that.stopRecordCallback();
})
}
});
}
});
},
...
<?php
//处理方法,
upload();
//media_id为微信jssdk接口上传后返回的媒体id
function upload(){
$media_id = $_POST["media_id"];
$access_token = getAccessToken();
$path = "./weixinrecord/"; //保存路径,相对当前文件的路径
$outPath = "./php/weixinrecord/"; //输出路径,给show.php 文件用,上一级
if(!is_dir($path)){
mkdir($path);
}
//微信上传下载媒体文件
$url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token={$access_token}&media_id={$media_id}";
$fileName = "wxupload_".time().rand(1111,9999);
$mp3Path = $path."/".$fileName.".mp3";
$amrPath = $path."/".$fileName.".amr";
//下载微信录音文件
downAndSaveFile($url,$amrPath);
//转换成mp3文件,TODO:一直没有转换成mp3,麻烦定位下
if(file_exists($mp3Path) != true){
// $command = "ffmpeg -i $amrPath $mp3Path & rm $mp3Path";
$command = "ffmpeg -i $amrPath $mp3Path";
system($command,$error);
}
$data["path"] = $outPath.$filename;
$data["msg"] = "download record audio success!";
// $data["url"] = $url;
echo json_encode($data);
}
//获取Token
function getAccessToken() {
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
$data = json_decode(file_get_contents("./access_token.json"));
if ($data->expire_time < time()) {
$appid = "youappid"; //自己的appid
$appsecret = "youappsecret"; //自己的appsecret
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
$res = json_decode(httpGet($url));
$access_token = $res->access_token;
if ($access_token) {
$data->expire_time = time() + 7000;
$data->access_token = $access_token;
$fp = fopen("./access_token.json", "w");
fwrite($fp, json_encode($data));
fclose($fp);
}
}
else {
$access_token = $data->access_token;
}
return $access_token;
}
//HTTP get 请求
function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
//根据URL地址,下载文件
function downAndSaveFile($url,$savePath){
ob_start();
readfile($url);
$img = ob_get_contents();
ob_end_clean();
$size = strlen($img);
$fp = fopen($savePath, 'a');
fwrite($fp, $img);
fclose($fp);
}
?>
目前没有使用七牛云,因此该部分代码,参考七牛云官网
时间:2016-11-02 21:01:33
早期的公司,代码版本管理,都是使用 svn, 提交上的代码也没有 review 才能merge 到主干上做法。
新公司采用 gitlab 来保存代码, 修改呢, 先 fork 出来,然后进行修改,修改完自己先提交到本地仓库,然后推送到gitlab 上,然后上 gitlab 上 刷新页面, 最上角会有一个 Merge Request 的按钮,点击按照提示创建 Merge Request。
Fork 过来之后,在要修改某个问题时, 创建一个分支出来
常规的 git 操作。
比如:
git clone 地址(fork过来后的地址)
touch test.txt
git add test.txt
git commit test.txt -m 'add test'
git push
时间:2016-11-10 14:22:03
地址:#49
由于接收同事的项目,项目中使用 PostgreSql, 记录下 常用的一些命令
psql -h 127.0.0.1 -p 54323 -U userName -d DbName
在 psql 中,切换数据库
\c dbname username serverIP port
mysql: show databases
psql: \l或\list
mysql: use dbname
psql: \c dbname
mysql: show tables
psql: \d
mysql: show columns from table name
psql: \d tablename
mysql: describe tablename
psql: \d+ tablename
mysql: quit 或者\q
psql:\q
时间:2016-09-24 22:56:12
作者:zhongxia
这里就不讲解Sass的安装以及语法了,因为参考文章中,阮一峰老师写的很详细,另外一篇也写的很不错,直接学习即可。 这里主要写下自己的看法,或者不懂的地方。
常规的CSS是不支持变量,函数,以及一些简单的判断,计算等。只有单纯的描述,如果多个地方使用同一个颜色,或者字体大小,要修改起来比较麻烦。
因此,就有人给CSS加入了一些编程元素,这被叫做 "CSS预处理器"(css preprocessor)
常见的 CSS预处理器,有Less, Sass , Stylus
- sass不是css的替代品,它只是让css变得更加高效、可维护
- 永远不要修改生成后的css
- 部署到线上的是生成的css文件,不是sass文件
Sass 有两种文件格式
.sass文件是缩进式的写法,对格式要求比较严谨,末尾不能有分号, 属性和值之间有一个空格
.test
margin: 5px 10px
font-size: 14px
color: #333
.scss文件 和 css 一致
.test {
margin: 5px 10px;
font-size: 14px;
color: #333;
}
css有一个不太常用的特性,即@import导入功能,它允许在一个css文件中导入其他css文件。然而,结果是只有执行到@import规则时,浏览器才会去下载其他css文件,这会导致页面样式加载特别慢,从而容易出现页面闪的问题。
但是 sass中,使用 import则可以规避这个问题, 因为sass最终会生成一个CSS文件,在生成的时候,会把导入的CSS 给合并到CSS文件里面。
在使用@import导入sass文件时,可以省略sass文件的后缀名.sass或.scss,例如:
//a.scss
body {
background-color: #f00;
}
//style.scss
@import "a";
div {
color: #333;
}
编译后的style.css文件内容如下:
body {
background-color: #f00;
}
div {
color: #333;
}
CreateTime:2016-08-31 14:11:49
JavaScript 实现继承的几种方式,有通过原型继承的, 有通过复制父类值继承的。
有动物类【父类】和猫类【子类】
function Animal(){
this.species = "动物";
}
function Cat(name,color){
this.name = name;
this.color = color;
}
把子类的this对象传到Animal的方法里面,然后把父类的属性绑定到 子类的 this 上
Animal.apply(this,arguments)
function Cat(name,color){
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
Cat.prototype = new Animal();
把 Cat 类的 prototype 指向 父类的实例。
Cat.prototype.constructor = Cat;
是因为每个 prototype 都有一个 constructor 属性,它指向构造函数。 并且每一个类实例也有一个 constructor 属性, 默认指向 prototype.constructor 。
如果没有添加上这句代码的话
cat1.constructor === Animal //true
虽然功能上使用没有出现什么问题,但是如果有使用到 cat.constructor 去做一些判断还是其他的操作, 会出现隐患。
cat1 明明是 从 Cat 类实例化出来的, 但是 cat.constructor却指向 Animal, 这个会造成继承紊乱。因此需要手动纠正,也就是这句代码的作用。
只继承 父类的 prototype 上的属性和方法
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype。
所以,上面这一段代码其实是有问题的。请看第二行
Cat.prototype.constructor = Cat;
这一句实际上把Animal.prototype对象的constructor属性也改掉了!
alert(Animal.prototype.constructor); // Cat
由于"直接继承prototype"存在上述的缺点,所以就有第四种方法,利用一个空对象作为中介。
var F = function(){};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
F是空对象,所以几乎不占内存。这时,修改Cat的prototype对象,就不会影响到Animal的prototype对象。
alert(Animal.prototype.constructor); // Animal
封装一个方法来实现继承
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype; //备用性质,也可不加
}
使用如下
extend(Cat,Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
上面是采用prototype对象,实现继承。我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?这样我们就有了第五种方法。
首先,还是把Animal的所有不变属性,都放到它的prototype对象上。
function Animal(){}
Animal.prototype.species = "动物";
然后,再写一个函数,实现属性拷贝的目的。
function extend2(Child, Parent) {
var p = Parent.prototype;
var c = Child.prototype;
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
}
这个函数的作用,就是将父对象的prototype对象中的属性,一一拷贝给Child对象的prototype对象。
使用的时候,这样写:
extend2(Cat, Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物
时间:2016-08-30 13:39:33
作者:zhongxia
概念:
闭包:能够读取其他函数内部变量的函数,在JavaScript中,一个函数return它内部的一个函数。
原理:通过引用变量从而阻止该变量被垃圾回收的机制
优:
缺:
要理解闭包,首先必须理解 JavaScript 特殊的变量作用域。
变量的作用域无非就是两种: 全局变量 和 局部变量
JavaScript语言的特殊之处,就在于 函数内部可以直接读取全局变量。
不使用 var 声明的变量,则为全局变量。 b = 100;
function fn(){
var a = b = 1;
// ==> var a = window.b = 1; // a 是局部变量 b 是全局变量
}
fn();
console.log("b = ",b); // 1
console.log("a = ",a); //VM783:1 Uncaught ReferenceError: a is not defined
函数外部无法访问局部变量。 因此在外部,访问 a 变量 报错。 而 b 变量是 全局变量,因此可以访问到。
闭包是概念?
闭包是指某种程序语言中的代码块允许一级函数存在并且在一级函数中所定义的自由变量能不被释放,直到一级函数被释放前,一级函数外也能应用这些未释放的自由变量。我的理解就是:闭包就是能够读取其他函数内部变量的函数
由于在JavaScript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单的理解成 『定义在一个函数内部的函数』
本质上: 闭包就是将函数内部和外部链接起来的一座桥梁。
//eg: example
function a(x){
var tmp = 10;
return function(y){
return (x+y)+(++tmp);
}
}
var b = a(10);
b(5); //26, 每执行一次 tmp 加 1
因为 a() 执行后,返回 的 方法 b, 内部引用了 tmp 变量, 导致 tmp 变量的标记+1, 垃圾回收机制就不会清除 tmp这个变量。
然后外部就可以继续访问到 tmp 变量。
var jQuery = (function(){
var jQuery = function(){
//TODO
}
return (window.$ = window.jQuery = jQuery);
});
实际使用的时候,闭包可以创建出非常优雅的设计,允许对funarg上定义的多种计算方式进行定制。如下就是数组排序的例子,它接受一个排序条件函数作为参数:
[1, 2, 3].sort(function (a, b) {
... // 排序条件
});
同样的例子还有,数组的map方法是根据函数中定义的条件将原数组映射到一个新的数组中:
[1, 2, 3].map(function (element) {
return element * 2;
}); // [2, 4, 6]
使用函数式参数,可以很方便的实现一个搜索方法,并且可以支持无限制的搜索条件:
someCollection.find(function (element) {
return element.someProperty == 'searchCondition';
});
还有应用函数,比如常见的forEach方法,将函数应用到每个数组元素:
[1, 2, 3].forEach(function (element) {
if (element % 2 != 0) {
alert(element);
}
}); // 1, 3
顺便提下,函数对象的 apply 和 call方法,在函数式编程中也可以用作应用函数。 apply和call已经在讨论“this”的时候介绍过了;这里,我们将它们看作是应用函数 —— 应用到参数中的函数(在apply中是参数列表,在call中是独立的参数):
(function () {
alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);
闭包还有另外一个非常重要的应用 —— 延迟调用:
var a = 10;
setTimeout(function () {
alert(a); // 10, after one second
}, 1000);
//...
var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
// 当数据就绪的时候,才会调用;
// 这里,不论是在哪个上下文中创建
// 此时变量“x”的值已经存在了
alert(x); // 10
};
//...
var foo = {};
// 初始化
(function (object) {
var x = 10;
object.getX = function _getX() {
return x;
};
})(foo);
alert(foo.getX()); // 获得闭包 "x" – 10
npm 安装包,如何使用 github 的地址
npm install <https://github.com/username/projectName/tarball/v0.0.1
tarball 需要固定,版本看自己情况。
//eg
npm install https://github.com/indexzero/forever/tarball/v0.5.6
时间:2016-10-26 15:52:04
作者:zhongxia
网站静态化,看产品或者网站的需求,不要为了静态化而静态化。
这里主要讲一些原理,没有具体的实例。
当然有好处,也有不足?
参考文章:《分享常见的几种页面静态化的方法》
PHP静态化的简单理解就是使网站生成页面以静态HTML的形式展现在访客面前,PHP静态化分纯静态化和伪静态化,两者的区别在于PHP生成静态页面的处理机制不同。
纯静态化:PHP生成HTML文件
伪静态化:把内容存放在nosql内存(memcached),然后访问页面的时候,直接从内存里面读取。
参考文章:《大型网站的静态化处理》
大型网站(高访问量,高并发量),如果是静态网站,可以通过扩展足够多的 web服务器,然后支持超大规模的并发访问。
如果是一个动态的网站,特别是使用到了数据库的网站是很难做到通过增加web服务器数量的方式来有效的增加网站并发访问能力的。比如淘宝,京东。
大型静态网站之所以能够快速响应高并发,因为他们尽量把动态网站静态化。
时间:2016-09-23 16:42:37
nginx 是一个高性能的 Web 服务器,之前也写过一些关于 nginx 的文章。为了提高博客的响应速度,可以从设置 nginx 的 gzip 和缓存这2方面入手。为字体开启 gzip 和缓存能大大减少带宽的消耗。
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
从图中可以看出,压缩等级在 1 之后的压缩效果都不是很明显,因此设置的时候,设置 1 或者 2即可。
开启成功,则请求资源如下
配置
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
access_log off;
expires 30d;
}
location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
access_log off;
expires 24h;
}
location ~* ^.+\.(html|htm)$ {
expires 1h;
}
其中的缓存时间可以自己根据需要修改。
为静态资源开启缓存能够较少服务器带宽的消耗,特别是在css中使用字体时,同时配合gzip压缩能够大大减少下载字体造成的带宽影响。
需要注意的是,字体有很多格式,为所有字体格式设置缓存是很有必要的。
location ~* ^.+\.(eot|ttf|otf|woff|svg)$ {
access_log off;
expires max;
}
只需要为 ttf、otf 和 svg 字体启用 gzip,对其他字体格式进行 gzip 压缩时效果不明显。
gzip_types font/ttf font/otf image/svg+xml
各种字体类型压缩效果可以参考以下测试结果:
可以看到对 woff 和 eot 进行 gzip 压缩效果不好。
扩展名 | 是否压缩 | Content-type |
---|---|---|
.eot | 否 | application/vnd.ms-fontobject |
.ttf | 是 | font/ttf |
.otf | 是 | font/opentype |
.woff | 否 | font/x-woff |
.svg | 是 | image/svg+xml |
createTime:2016-09-28 16:30:55
原文地址,欢迎star!
总结下项目的问题,收获,不足。
产品功能:可以查看 http://www.baifendian.com/pro/subject-67.html
简单的讲,该系统提供一整套的大数据解决方案。 客户拥有大量的数据,然后如何从这大量数据中,清洗出有价值的数据。
5个前端,10个后端,1个运维, 开发调试用时3个月, 测试用时1.5个月。
前端技术:React全家桶 + webpack + gulp + ES6 + babel + less (react0.14)
代码版本控制使用:SVN
后端技术:Java + 大数据相关 【略】
大数据操作系统,由多个模块组成,每个模块可以理解成一个Project, 可以单独运行,不依赖其他模块。 然后由web桌面集成在一起。
- BFD-UI 公共组件库
- CommonComponent 公共样式,Ajax处理,正则,针对产品定制组件部分
- DataFactoryModel 项目应用的工作流框架
- ConfigCenter 项目
- DataFactory 项目
- FilaManage 项目
- SecurityCenter 项目
- node_modules
- common 项目间公共代码
- container 项目布局
- modules 一级模块目录
- ide 一级模块
- components 页面
- css 样式
- enum 枚举
- model Ajax相关操作
- util 工具
- index.js react-router 路由
...
- workflow 一级模块
项目中考虑的问题和遇到问题的解决思路
相对刚开始,前后端还搞在一起,前端开发还需要搭建后端环境,然后后端改配置,前端居然跑不起来了,要抱着电脑去请教后端,这个坑啊。模块化开发好很好,只需要关注自己的模块。
前后端分离, 项目采用模块化,每个人负责几个模块,模块内包含该模块的所有内容,除了公共的部分,保证直接删掉该代码,并去掉路由,直接可以去掉该模块,添加模块等同。
这样模块解耦,方便应对需求变动,权限控制。
这一块还好,没有遇到啥大问题。
组件需要分为:公共基础组件,公共定制组件,具体业务组件
公共基础组件:建议采用第三方组件库,本项目使用公司的组件库,公司组件库刚开始研发,过程中各种BUG,版本迭代间,高版本用于与低版本用法不一样,很多坑爹的问题。
公共定制组件:在公共基础组件的基础上,封装成各个项目中,可以快速使用的方式,方便项目间统一维护,快速方便使用。 比如(表格数据处理,翻页处理,全选逻辑。。。)
具体业务组件:具体页面模块,但具体页面中,也有共用的部分。 最常见的就是编辑页面和创建页面可以共用。
覆盖组件样式是一个坑,因为公司组件也在研发中,作为第一个吃螃蟹的团队,就。。。。
组件库的样式,刚开始使用模块化+嵌套的方式, 后面组件库丰富了,发现有一些命名重复啦,重复啦。然后大改版,使用BEM命名方式。如果只修改命名方式也就还好,最主要还是修改了DOM结构,然后之间的覆盖样式都废了。
切记,切记,切记,使用稳定的组件库组件库地址:https://github.com/baifendian/bfd-ui
已经提供第一个稳定版本,赞一个,一路过来不容易。
引用第三方的reset.css,比如(normalize.css),处理浏览器之间的小差异
公共基础组件已经有自带的样式,需要覆盖,换成UI设置的风格,覆盖公共组件的样式都放在一个文件中。比如 bfd-ui.less , 也可以放多个文件,然后放在同一个文件夹中。
整体布局的样式,单独抽离成 layout.less 文件
样式命名需要统一规范,否则容易造成样式名冲突。可以使用 BEM的命名方式,虽然命名长了点,但是为了命名冲突,也值了。
less 的变量也可以单独抽取出来,放在一个 文件中。 方便后期统一修改。比如:global.less
//其他使用变量的地方引入
@import "global.less";
注意less 、 sass 的 import 和 css 自带的区别。
刚开始coding,Ajax还没有封装,大家写到业务逻辑里面,这样代码很乱,一个JS中,有页面,业务逻辑,混在一起。
还好及时提出了解决方案, 抽离Ajax这一层,先封装Ajax操作,然后每个模块各自抽离出Ajax操作,模块中调用,就是一个方法的调用。
跨域: : 关闭浏览器安全策略
开发的时候,前后端是分离的,因此前端访问后端接口的时候是跨域的。考虑到最终上线的时候,是部署在一起。 因此,上线后是没有跨域问题的。 因此可以使用关闭浏览器安全策略来解决跨域问题。
Ajax接口地址: 可配置
开发的时候,可能要连接后端人员机子的IP地址,访问接口,调试完成可能要访问开发环境地址,上线需要访问上线部署的地址。 经常需要变动。 因此 接口的 基本路径 做成 配置。然后直需要改动配置,就替换了整个项目接口的访问地址。
Session过期,错误处理? 提供默认处理,并扩展接口自定义
项目开发,必须给Ajax封装一层,写统一的错误处理,错误提示,Loading效果,超时提示,Session过期等通用操作。
Ajax请求到一半,跳转页面,需要在 componentWillUnmount 中断Ajax请求。否则会报 组件已经卸载,不能使用 this.setState操作的错误。
每个程序员都有自己的代码风格,但是,但是,但是团队开发就需要共同遵守一个代码规范。
这一块React生命周期,大家都按照顺序写,还行。其他方面由于赶时间,基本是 一个 格式化功能搞定。
JS代码规范只能口头上说说,因为实际上会不会执行,还得要比较大的Review力度。因此可以使用 eslint 来进行验证,在提交前要验证下。【验证的比较粗糙】
还有一些则需要团队之间遵守,比如使用React, 编写生命周期的时候,请按照顺序来。
constructor
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUnmount
...
其他自定义方法
...
render
创建React组件,统一使用 ES6。加 autobind 方法
模块功能复杂的情况下,最好先理清整体流程,操作事件,然后在coding。
写IDE模块的时候,刚开始认为这个很简单,然后直接啪啪啪开始coding了,后面发现都是坑,非常多的细节问题。各种事件,各种交互。导致后面Review做了很大改动,切记切记,理清需求,不要看起来简单。
小模块内部,使用 prop或者 context 传递方法进行通讯, 模块之间使用 事件派发。
这一块,公共样式,和布局方面做还行,但是公共组件方面有很大的问题,有时候更新组件忘记通知大家,导致跑起来报错。还有必须注意的是,进入测试阶段就不要更新整个组件库了,有BUG自己打补丁修复。因为更新组件引入新的BUG,被测试一直说。
公共样式在整个项目中,各个页面都用到,因此修改公共样式需要慎重。尽量不要使用一些奇淫技巧,写一些稳妥的。
后台类型的管理系统,需要有很多的表单,有很多表单就有很多表单验证。
可以抽离出正则表达式统一放在一个文件中,其他各个地方都使用该文件里面的正则,文件中没有,则添加上。
在项目中,除了抽离正则,还封装了有验证功能的表单组件,然后直接配置正则,和错误信息(也可以动态生成错误信息),即可使用。
这一块在该项目中,做的还不错。
测试阶段,尽可能减少修改BUG而引发新的BUG。因此必须写清楚每次提交代码的作用。
研发阶段还好一点,做好一个就可以提交一个,并且稍微注明下 上传什么模块代码就行了。
测试阶段,修改BUG,就必须遵守SVN提交规范
这一块分为两种,按钮控制,模块控制
在项目刚加载的时候,同步请求,权限数据,然后判断 data-code是否有权限,没有的话, 则 不 render 到页面上
按钮的权限控制,在最初的预想是,渲染到DOM后,在remove DOM 节点,后面发现这个想法是不可行的。
React 的 componentDidMount 回调里面, 不可以remove DOM节点,否则报错。
最终封装了一个组件,替换页面上所有需要控制按钮 , 图标按钮,超链接,下拉框选项,右键菜单。
renderType 属性执行渲染成什么类型组件(按钮,下拉。。。)
data-code 核心: 按钮标识,和后端匹配上
<AuthButton style={{marginLeft: 2,marginRight:20}}
data-code="1021002" renderType="icon" type="plus-square"
onClick={this.addScript.bind(this)}>新增</AuthButton>
模块控制,则控制导航菜单即可。 过滤掉没有权限导航选项,然后把有权限的渲染出来。
每个模块的代码,是按需加载的, 也就是刚进入项目页面的时候,没有加载 模块的JS代码,这样减少了进入系统的时间很长。
【关掉第二个选项卡,可接口是关闭第三个选项卡】
主要问题是:对 React 的 key 和 render原理 的相关知识支持了解不够。
tabs 的内容是 存放在 数组中,循环渲染出来的,新增一个 tab,会往数组中添加一个tab,
然后react就会 重新 render,渲染出 tabs 组件。
修改前使用 index 做为key
<TabList>
{this.renderTool()}
{this.state.tabs.map((tab,index) => {
return (
<Tab key={index} activeKey={index}>
{this.renderTabTitle(tab)}
</Tab>)
})}
</TabList>
修改前使用一个唯一标识作为key,就搞定了。
<Tab key={tab.uuid} activeKey={tab.uuid}>
一句话就是:想要更新组件内容,请保证当前组件的key与上一状态组件的key不同。
具体可以看《ReactJS 组件的key作用》
虽然没有使用redux进行state管理,但是整体开发过程中,没有体会到状态难管理。
FormData对象,是可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单"。
在 Mozilla Developer 网站 《使用FormData对象》 有详尽的FormData对象使用说明。
但上传文件部分只有底层的XMLHttpRequest对象发送上传请求,那么怎么通过jQuery的Ajax上传呢?
本文将介绍通过jQuery使用FormData对象上传文件。
使用 <form>
表单初始化FormData对象方式上传文件
HTML代码
<form id="uploadForm" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
<button id="upload" type="button">upload</button>
</form>
javascript代码
$.ajax({
url: '/upload',
type: 'POST',
cache: false,
data: new FormData($('#uploadForm')[0]),
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false // 告诉jQuery不要去设置Content-Type请求头
}).done(function(res) {
}).fail(function(res) {
});
这里要注意几点:
<form>
标签添加enctype="multipart/form-data"属性。<form>
表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。<input>
中声明的是name="file"。如果不是用<form>
表单构造FormData对象又该怎么做呢?
使用FormData对象添加字段方式上传文件
HTML代码
<div id="uploadForm">
<input id="file" type="file"/>
<button id="upload" type="button">upload</button>
</div>
这里没有<form>
标签,也没有enctype="multipart/form-data"属性。
javascript代码
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
url: '/upload',
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function(res) {
}).fail(function(res) {
});
这里有几处不一样:
append()的第二个参数应是文件对象,即$('#file')[0].files[0]。
contentType也要设置为‘false’。
从代码$('#file')[0].files[0]中可以看到一个<input type="file">
标签能够上传多个文件,
只需要在<input type="file">
里添加multiple或multiple="multiple"属性。
从Servlet 3.0 开始,可以通过 request.getPart()
或request.getPars()
两个接口获取上传的文件。
这里不多说,详细请参考官网教程 Uploading Files with Java Servlet Technology 以及示例 The fileupload Example Application
时间:2016-09-10 01:31:22
作者:zhongxia
本文章,以Mac Os 系统为例子。
1. 下载安装包 官网下载 nw.app 的安装包
把安装包放到 Application 的文件夹里面, 可以双击 nwjs.app ,打开应用。
设置别名,方便使用
//1. 打开设置别名的文件
vim ~/.bash_profile
//2.在文件里面添加 上下面这一句
alias nw="/Applications/nwjs.app/Contents/MacOS/nwjs"
//3.使别名生效
source ~/.bash_profile
此时,在命令行输入 nw , 等同双击打开应用
[如果使用了zsh, 可以在 vim ~/.zshrc 里面添加别名 【本人Mac上,别名需要在这里设置才起作用】]
如何使用 nw 打开 项目
nw . //当前目录下的 package.json
nw ./xxx/package.json //其他目录下的package.json
2. sudo npm install -g nw
由于下载nw,迟迟下载不下来,并且执行 nw 的时候, 一直报错。 后面采用第一种方式。 理论上来讲, npm 上安装好之后, 输入 nw 就可以用了。 【具体需要测试下】
2016-09-10 10:58:36
今天测试了一下是可以用的, 但是推荐使用 npm 包, nwjs 来管理 nw 的版本
npm install -g nwjs
//列出已安装的 nw 版本
nw ls
//安装指定版本的 nw
nw install 0.17.0
//使用指定版本的nw
nw use 0.17.0
在Mac 下打包 应用为一个 demo.app 很简单。
//1. 把nwjs.app 复制到你记得住的地方,比如项目的根目录,或者其他
cp -R /Applications/nwjs.app ./test.app
//2. 把项目的代码打包成 一个 nw 文件 【在项目文件夹里面执行这一句,路径自己根据情况修改】
zip -r ../test.app/Contents/Resources/app.nw *
完成, 双击 test.app 即可打开程序
CreateTime: 2016-09-07 11:14:32
Author: zhongxiaCSS3的动画效果是一个很有用的功能,可以很方便的实现了早期只能用JS来实现的动画效果。这里主要讲解CSS3的动画
在没有出现transition之前,CSS是没有时间轴的,状态变化是即时完成的。
最简单的使用方法
/*==================最基本用法=====================*/
img{
width:20px;
height:20px;
transition: 1s; /*设置CSS属性变化过度的时间*/
}
img:hover{
width:200px;
height:200px;
}
/*==================完整例子=====================*/
img{
transition: 2s 1s height ease;
}
img{
transition-property: height; /*CSS状态值需要过度的属性*/
transition-duration: 2s; /*过度时间*/
transition-delay: 1s; /*延迟时间*/
transition-timing-function: ease;
/*状态变化速度(ease 逐渐放慢、linear 匀速、ease-in 加速、ease-out 减速、cubic-bezier函数:自定义速度模式)*/
}
cubic-bezier 可以使用工具网站来实现 工具网站
transition的优点在于简单易用,但是它有几个很大的局限。
/*定义一个动画效果*/
@-webkit-keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
@keyframes rainbow {
0% { background: #c00; }
50% { background: orange; }
100% { background: yellowgreen; }
}
div {
width: 200px;
height: 200px;
border: 1px solid black;
}
/*hover 使用这个动画效果*/
div:hover{
-webkit-animation: 1s rainbow;
animation: 1s rainbow; /*默认播放一次*/
}
/*==================animation简写======================*/
animation: 1s rainbow infinite; /*无限次播放*/
animation: 1s rainbow 10; /*播放10次*/
div:hover {
animation: 2s 1s rainbow linear 3 forwards normal;
}
div:hover {
animation-name: rainbow;
animation-duration: 2s;
animation-timing-function: linear;
animation-delay: 1s;
animation-fill-mode:forwards;
animation-direction: normal;
animation-iteration-count: 3;
}
animation-fill-mode: 动画结束以后,会立即从结束状态跳回到起始状态。如果想让动画保持在结束状态,需要使用animation-fill-mode属性。
animation-direction:动画循环播放后,每次播放完都是回到开始的状态,这个属性可以修改
简单说,animation-direction指定了动画播放的方向,最常用的值是normal和reverse。浏览器对其他值的支持情况不佳,应该慎用。
chrome 不支持没有前缀的 @Keyframes ,因此需要加上 @-webkit-keyframes, IE10+ 和 Firefox16+ 支持不加前缀的@Keyframes
/*from=0% to=100%*/
@keyframes rainbow {
from { background: #c00 }
50% { background: orange }
to { background: yellowgreen }
}
/* 上面的 等于 下面这个写法*/
@keyframes rainbow {
0% { background: #c00 }
50% { background: orange }
100% { background: yellowgreen }
}
@keyframes pound {
from,to { transform: none; }
50% { transform: scale(1.2); }
}
//另外一点需要注意的是,浏览器从一个状态向另一个状态过渡,是平滑过渡。steps函数可以实现分步过渡。
div:hover {
animation: 1s rainbow infinite steps(10);
}
动画播放结束之后,默认回到初始状态,这个时候就需要使用到 animation-play-state
div {
animation: spin 1s linear infinite;
animation-play-state: paused;
}
div:hover {
animation-play-state: running;
}
时间:2016-11-02 10:35:09
目前已经 有一份脚手架,不过由于babel 还是采用5.x 的, 想要替换成 6.x,并且要集成进 redux, 还有react 换成 15.x
TODO:待整理
git clone 仓库地址
git pull
//本地修改的内容,先存放起来
git stash
//更新
git pull
//把刚才本地修改内容,合并进来
git stash pop stash@{0}
git reset --hard
git remote set-url origin 新地址
Redux看了很多教程,很多文章,知道具体怎么使用,但是对于里面的原理,以及如何串起来不是很了解。后面看了 阮一峰阮老师的 《redux 入门教程》,茅塞顿开。
这里只描述一下,简单的跨域形式,不需要修改前后端代码,只需要做配置就行了。
一、Chrome浏览器关闭安全策略
开发时存在跨域,上线后部署在 一起,没有跨域问题
参照28 Chrome关闭安全策略
最近在研究RESTful API接口设计,使用的是Nginx,
要实现本地 http://127.0.0.1
跨域访问服务器端 http://api.zlzkj.com
,
并且要支持DELETE PUT等请求。
只需要在Nginx配置文件里加入以下配置,即可开启跨域
add_header Access-Control-Allow-Origin *;
*代表任何域都可以访问,可以改成只允许某个域访问,如Access-Control-Allow-Origin: http://www.zlzkj.com
。
这样的配置虽然开启了跨域请求,但只支持GET HEAD POST OPTIONS请求,使用DELETE发起跨域请求时,浏览器出于安全考虑会先发起OPTIONS请求,服务器端接收到的请求方式就变成了OPTIONS,所以引起了服务器的405 Method Not Allowed。
所以要对OPTIONS请求进行处理
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
#其他头部信息配置,省略...
return 204;
}
当请求方式为OPTIONS时,设置Allow的响应头,重新处理这次请求。
配置好并重启Nginx,刷新页面重新发起请求,在控制台里你会发现,出现了二次请求,
第一次是OPTIONS请求,第二次才是DELETE请求,这就是对OPTIONS请求进行处理的结果,到这里总算完成了一次DELETE跨域请求了。
add_header Access-Control-Allow-Origin *;
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
return 204;
}
index index.php;
try_files $uri @rewriteapp;
}
放到配置文件的server {}里
虽然最终配置代码没有几行,过程还是比较折腾的。
一开始不断地去翻墙,查阅相关文章,好不容易找到了跨域配置方法,却发现不支持DELETE等请求方式,于是又重新去翻墙,把原来的相关文章再次翻了一遍,才查到了些蛛丝马迹,又通过论坛提问,最终才找到了相应的解决方法,多折腾总有收获。
时间:2016-11-03 10:50:54
地址:#45
下面最重要的是两个地方
webpack入口文件,加上 'webpack-dev-server/client'
【必选】 , 'webpack/hot/only-dev-server',
【可选】
loader加载器, js|jsx 需要加上 react-loader 在最前面
{
test: /\.(js|jsx)$/,
loader: 'react-hot-loader!babel-loader',
exclude: /node_modules/
},
//热更新的关键一句
app.use(require('webpack-hot-middleware')(compiler))
'use strict';
var path = require('path')
var webpack = require('webpack')
module.exports = {
devtool: 'source-map',
cache: true,
entry: {
app: [
'webpack-dev-server/client',
'webpack/hot/only-dev-server',
path.join(__dirname, 'src/index')
],
common: path.join(__dirname, 'src/common')
},
output: {
path: path.join(__dirname, 'static'),
filename: '[name].bundle.js',
chunkFilename: 'chunk/[chunkhash:8].chunk.js',
publicPath: '/FileManage/static/'
},
plugins: [
new webpack.DefinePlugin({
__DEV__: String(true)
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.optimize.CommonsChunkPlugin('vender.js')
],
module: {
loaders: [{
test: /\.(js|jsx)$/,
loader: 'react-hot-loader!babel-loader',
exclude: /node_modules/
}, {
test: /\.css$/,
loader: 'style-loader!css-loader'
}, {
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)(\?v=[\d\.]+)?$/,
loader: 'file-loader?name=files/[hash:8].[ext]'
}, {
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.less$/,
loader: 'style!css!less'
}]
},
resolve: {
//自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
extensions: ['', '.js', '.jsx'],
root: [
path.join(__dirname, '/src'),
path.join(__dirname, '/'),
path.join(__dirname, '../CommonComponent'),
path.resolve(__dirname, '../BFD-UI')
],
alias: {
Loading: 'common/components/Loading/index.js',
}
}
}
server.js
const express = require('express')
const debug = require('debug')('app:server')
const webpack = require('webpack')
const webpackConfig = require('../build/webpack.config')
const config = require('../config')
const app = express()
const paths = config.utils_paths
app.use(require('connect-history-api-fallback')())
// ------------------------------------
// Apply Webpack HMR Middleware
// ------------------------------------
if (config.env === 'development') {
const compiler = webpack(webpackConfig)
app.use(require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
contentBase: paths.client(),
hot: true,
quiet: config.compiler_quiet,
noInfo: config.compiler_quiet,
lazy: false,
stats: config.compiler_stats
}))
app.use(require('webpack-hot-middleware')(compiler))
app.use(express.static(paths.client('static')))
} else {
app.use(express.static(paths.dist()))
}
module.exports = app
时间:2016-11-04 20:04:53
原文地址:#48
挺早就听说过BEM了,也大概的知道怎么用,但是具体 BEM 指啥,具体有啥要求,还不是很清楚,然后今天就学习了下。
BEM的意思就是块(block)、元素(element)、修饰符(modifier),是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其他开发者来说更加透明而且更有意义。BEM命名约定更加严格,而且包含更多的信息,它们用于一个团队开发一个耗时的大项目。
重要的是要注意,我使用的基于BEM的命名方式是经过Nicolas Gallagher修改过的。这篇文章中介绍的这种命名技术并不是原始的BEM,但却是一个我更喜欢的改进版。无论实际使用了什么样的符号,它们其实都是基于同样的BEM原则。
命名约定的模式如下:
.block{}
.block__element{}
.block--modifier{}
.site-search{} /* 块 */
.site-search__field{} /* 元素 */
.site-search--full{} /* 修饰符 */
B:header-tabs //名字随便
E:header-tabs__item //多个tab选项
M:header-tabs__item--active //选中状态
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.