terryzwei / blog Goto Github PK
View Code? Open in Web Editor NEWpersonal github
personal github
早期提到构建工具,历史最为悠久的是Make,由于Node的出现逐渐发展出一批自动化构建工具,像Grunt,Gulp,,fis, Webpack,browserify(本质上并不是构建工具,开发的初衷是为了前端引用npm引入的commonjs模块)。
grunt与gulp都是前端构建的工具,与fis,webpack,browerify这一类构建工具(构建工程化方案)不太类似,它们更偏向于工具类。一下说说grunt和gulp各自的特点。
grunt特点:
/**
* create by Terry on 16/7/24.
*/
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),//读取配置文件
//合并
concat: {
build: {
files: [{
'dest/scripts/app.js': ['dest/scripts/page/a.min.js','dest/scripts/page/b.min.js']
}]
},
},
//清除
clean: {
build: ['dest/**']
},
//压缩
uglify: {
build: {
files:[{
expand: true, //
cwd: 'dest/scripts', //要压缩的目录路径
src: '**/*.js', //要压缩的对应的js文件
dest: 'dest/scripts',//压缩后目标文件生成位置
ext: '.min.js' //生成目标文件的扩展名称
}]
}
},
//拷贝
copy: {
dev: {
files:[{
expand: true,
cwd: 'src/',
src: ['**'],
dest: 'dest/'
}]
}
}
});
//加载相对应的插件
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-copy');
// 默认运行的任务,
grunt.registerTask('default',['clean','copy','uglify','concat']);
};
gulp的特点:
/**
* create by Terry on 16/7/24
*/
var gulp = require('gulp');
var uglify = require('gulp-uglify'); //压缩代码
var util = require('gulp-util'); //工具
var watchPath = require('gulp-watch-path'); //文件变化所在的位置
var combiner = require('stream-combiner2'); //捕获流处理过程中的错误
var sourcemaps = require('gulp-sourcemaps'); //使用sourcemap帮助开发调式
var less = require('gulp-less'); //编译less
var minifycss = require('gulp-minify-css'); //压缩css
// 错误输出错误信息
var handleErr = function(err){
var colors = util.colors;
console.log('\n');
util.log(colors.red('Error!'));
util.log('fileName: ' + colors.red(err.fileName))
util.log('lineNumber: ' + colors.red(err.lineNumber))
util.log('message: ' + err.message)
util.log('plugin: ' + colors.yellow(err.plugin))
};
// 压缩js
gulp.task('uglify',function(){
var combined = combiner.obj([
gulp.src('src/scripts/**/*.js'), //需要压缩的js文件路径
sourcemaps.init(),
uglify(), //压缩js
sourcemaps.write('./'),
gulp.dest('dest/scripts') //生成的js文件的目录
]);
// gulp.src('src/scripts/**/*.js')
// .pipe(uglify())
// .pipe(gulp.dest('dest/scripts'));
});
// 监听js文件变化,进行压缩和生成对应的sourcemap
gulp.task('watchjs',function(){
gulp.watch('src/scripts/**/*.js', function(event){
var paths = watchPath(event, 'src/', 'dest/'); //watchPath(回调函数的 event, 需要被替换的起始字符串, 第三个参数是新的的字符串, 扩展名(非必填))
util.log(util.colors.green(event.type)+' '+paths.srcPath); //输出改变的文件原路径
util.log('Dist:' + paths.distPath); //处理后的文件路径
var combined = combiner.obj([
gulp.src(paths.srcPath),
sourcemaps.init(),
uglify(),
sourcemaps.write('./'),
gulp.dest(paths.distDir)
]);
combined.on('error', handleErr);
});
});
// 监听less文件的变化
gulp.task('watchless', function(){
gulp.watch('src/styles/**/*.less', function(event){
var paths = watchPath(event, 'src/', 'dest/');
util.log(util.colors.green(event.type)+' '+paths.srcPath); //输出改变的文件原路径
util.log('Dist:' + paths.distPath); //处理后的文件路径
var combined = combiner.obj([
gulp.src(paths.srcPath),
sourcemaps.init(),
less(),//编译less
minifycss(),//压缩css
sourcemaps.write('./'),
gulp.dest(paths.distDir)
]);
combined.on('error', handleErr);
});
});
// less生成对应的css文件
gulp.task('lesscss', function(){
var combined = combiner.obj([
gulp.src('src/styles/**/*.less'),
sourcemaps.init(),
less(),
minifycss(),
sourcemaps.write('./'),
gulp.dest('dest/styles')
]);
combined.on('error',handleErr);
});
//默认任务
gulp.task('default',['uglify','lesscss','watchjs','watchless']);
webpack是一个解决引用模块和打包的工具。说起模块,不得不说这两个库requirejs(AMD)和seajs(CMD),这两个库都是前端模块化开发的库。现在的nodejs就是采用与seajs一样的CMD规范。但对于wepack这种强大的引用模块工具来说,已经兼容AMD和CMD两种规范模式。接下来说说webpack的特点吧。
webapck的特点:
browserify本质上是为了实现在前端也能使用npm中的CMD的模块,并不是一个专门打包的前端工具。但现在nodejs社区对它贡献了很多transform模块,所以现在与webpack同样是构建工程化的其中一种选择。
参考:移动H5前端性能优化指南
手机浏览器同时支持最大连接数为4(安卓为4,iOS5以后为6;主机和域名相同的前提下的最大连接数,不过有时候是达不到这个连接数的),所以尽量减少HTTP的请求。
1.合并css、js文件;
2.合并图片(css sprite),小图片可以使用dataURL;
缓存可以减少请求服务器的次数,节约加载时间。
1.外联js、css文件;
2.缓存一切可以缓存的资源;
减少文件大小提高加载速度和显示速度,对HTML、CSS、JS进行压缩,并在服务器端设置Gzip
1.压缩html、css、js文件;
2.服务器开启GZip(服务器进行压缩,浏览器接收后解压)
写在头部的js文件(非异步),和嵌入在HTML标签中的style会阻塞页面渲染。因此js文件应该放到底部或使用异步加载方式(async或者defer),样式用外联的CSS文件放在头部使用link加载。
将不影响用户的资源和用户暂时没有用到的资源放到用户需要的时候再加载;
1.lazyload
2.滚动加载
如果网站加载内容比较大,可以提前给用户一个loading显示,但是不能等待太久;
cookie会影响加载速度,所以对于静态资源应该不使用cookie
冒泡排序,有时被称为沉没排序,是一个简单的排序算法,通过反复步骤对列表进行排序,比较每一对相邻位置上的数字和互换他们错乱的排序。通过对列表重复直到不需要互换位置,这表明列表排序完成。
for (var i = 1; i < a.length; i++) {
for (var j = 0; j < a.length-i; j++) {
if (a[j] > a[j+1]) {
var tem = a[j]
a[j] = a[j+1]
a[j+1] = tem
}
}
}
console.log(a) //[1,3,3,4,5,6,7,9,9,10,22,55]
冒泡排序时间复杂度:对于有n位数的数组,循环的次数就是(n-1)+(n-2)+...+1 = n(n-1)/2
,所以时间复杂度简化后为O(n²)
选择排序是一个排序算法,明确地用一个值去作比较排序,时间复杂度是O(n²),在处理大数组的时候效率时分低下,一般情况下比插入排序效率更差。选择排序以简洁著称,在某些情况下它比更复杂的算法具有性能优势,特别是在内存有限情况下。
var a = [9,3,5,7,1,4,10,55,22,3,6,9]
for (var i = 0; i < a.length-1; i++) {
for (var j = i+1; j < a.length; j++) {
if (a[i] > a[j]) {
var tem = a[j]
a[j] = a[i]
a[i] = tem
}
}
}
console.log(a) //[1,3,3,4,5,6,7,9,9,10,22,55]
选择排序时间复杂度:对于有n位数的数组,循环的次数就是(n-1)+(n-2)+...+1 = n(n-1)/2
,所以时间复杂度简化后为O(n²)
选择排序的时间复杂度虽然和冒泡的一样,但是实际上选择排序交换操作次数少,最多是n-1
次
简单的说,就是页面上操作能实时反映到数据上,数据的改变能及时展示在页面上。
脏检测机制就是检测作用域上的所有数据是否有所变动,最后再一次性更新变动的数据。可以通过$digest和$apply两种方式手动触发脏检测机制,$apply方法是从根作用域$rootScope开始检测,而digest只会检测它当前所在作用域下的数据,所以这里如果自己清楚需要更新当前作用域下的数据则使用$digest,而如果使用一些第三方插件时,建议还是使用$apply。
这是因为ng-click里面虽然封装了click方法,而且最后还执行了apply()方法,把数据的变更展示到页面上去。在angular中,同一时间只允许有一个digest方法,所以如果在ng-click方法里面再调用digest会报错。
脏检测机制有利有弊,对于整个页面大部分数据都改变的,脏检测还是高效的,但是对于页面只改变一两个值,这时候脏检测就有点不太合适了。
ES6为字符串添加了遍历器接口,所以可以通过for of去遍历字符串,for of相对于for循环的好处在于能够识别大于0xFFFF
的码点
var text = '𠮷';
for (let i = 0; i < text.length; i++) {
console.log(text[i]);
}
// " "
// " "
for (let i of text) {
console.log(i);
}
// "𠮷"
除了indexOf方法外,ES6提供了includes
、startsWith
、endsWith
三个方法
function Person (name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
var objectFactory = function () {
var obj = new Object(); //实例化一个空对象;
var Constructor = Array.shift.apply(arguments); //获取构造函数;
obj.__proto__ = Constructor.prototype; //将空对象原型指向传入的构造函数原型;
var ret = Constructor.apply(obj, arguments); //执行构造函数,将内部的this指向obj对象;
return typeof ret === 'object'? ret: obj; //返回对象;
}
var a = objectFactory(Person, 'terry');
console.log(a.name); //'terry'
console.log(a.getName()) //'terry'
console.log(Object.getPrototypeOf(a) === Person.prototype); //true
整理一下自己经常忘记的前端知识点
创建跳动加载动画
<div class="bouncing-loader">
<div></div>
<div></div>
<div></div>
</div>
@keyframes bouncing-loader {
from {
opacity: 1;
transform: translateY(0);
}
to {
opacity: 0.1;
transform: translateY(-1rem);
}
}
.bouncing-loader {
display: flex;
justify-content: center;
}
.bouncing-loader > div {
width: 1rem;
height: 1rem;
margin: 3rem 0.2rem;
background: #8385aa;
border-radius: 50%;
animation: bouncing-loader 0.6s infinite alternate;
}
.bouncing-loader > div:nth-child(2) {
animation-delay: 0.2s;
}
.bouncing-loader > div:nth-child(3) {
animation-delay: 0.4s;
}
注意:1rem
一般是 16px
.
@keyframes
定义了一个动画的两种状态,当元素改变opacity
和使用tansform: translateY()
属性在2D平面上跳动..bouncing-loader
是跳动循环的父级容器和使用display: flex
和justify-content: center
把它们定位到中间位置上..bouncing-loader > div
设置父级元素下三个div
的样式.div
设置宽和高1rem
,使用border-radius: 50%
去将它们从方形变成原型.margin: 3rem 0.2rem
表明每一个原型元素的顶部/底部都有3rem
的边距和左右两边有0.2rem
的边距,以便它们相互之间不会黏在一起,给予它们喘息的空间.animation
是各种各样动画属性的简写属性: animation-name
,animation-duration
,animation-iteration-count
,animation-direction
在这里使用了这几个属性.nth-child(n)
定位到父元素下的第n个子元素.animation-delay
分别使用在第二第三个div元素上,是因为每一个元素不会在相同的时间点开始动画.重置盒子模型以便于width
和height
都不会受到自身的border
或者padding
的影响.
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
box-sizing: border-box
使padding
或者border
不会影响到元素的width
或者height
.box-sizing: inherit
使元素遵循父级元素的box-sizing
规则.IE8或IE8以上.
利用纯CSS方式创建一个圆形.
<div class="circle"></div>
.circle {
border-radius: 50%;
width: 2rem;
height: 2rem;
background: #333;
}
border-radius: 50%
通过弯曲元素的边去创建一个圆.
先定义两个构造函数
function Parent() {
this.age=50;
}
function Child(name, height) {
this.name = name;
this.height = height;
}
实现构造函数的时候直接调用apply或者call,实现继承
function Child(name, height) {
Parent.apply(this, arguments);
this.name = name;
this.height = height;
}
var c = new Child('小明', '175');
c.age; // 50
使用构造函数的prototype实现继承
// 设置Child的prototype指向Parent的实例,这样就Child就能实现继承
Child.prototype = new Parent();
// prototype里面有一个constructor的属性,constructor属性指的就是它的构造函数,因为上面把prototype重现赋值了,所以现在指向的是Parent,如果不重新指向Child的话就会出现继承链紊乱了。
Child.prototype.constructor = Child;
var c = new Child('小明', '175');
c.age; // 50
对Parent方法进行重写
function Parent(){ }
Parent.prototype.age = 50;
这是对Prototype模式的改进,不用实例化Parent。
Child.prototype = Parent.prototype;
Child.prototype.constructor = Child;
var c = new Child('小明', '175');
c.age; // 50
不过这里会出现一个问题,就是Parent的prototype上的属性发生改变,Child也会跟着变化。
这是为了解决上面的直接继承的问题才出现的继承方法。
// 先定义一个空的构造方法
function T() {};
// 把空对象的原型prototype指向了Parent的prototype
T.prototype = Parent.prototype;
// 实例化一个T对象,赋值给Child的prototype属性,实现继承
Child.prototype = new T();
Child.prototype.constructor = Child;
var c = new Child('小明', '175');
c.age; // 50
var Parent = {sex: 1};
如果不是构造函数要实现继承的话,可以使用以下三种方式:
function object(o) {
var F = function () {};
F.prototype = o;
return new F();
}
var Child = object(Parent);
Child.age = 10;
Child.sex; // 1
function copy(o) {
var c = {};
for (var i in o) {
c[i] = o[i]
}
return c;
}
var Child =copy(Parent);
Child.sex; // 1
var Parent = {sex: 1, arr: [1, 2, 3]};
function deepCopy(o, c) {
var c = c || {};
for (var i in o) {
if (typeof o[i] === 'object') {
c[i] = (o[i].constructor === Array)? [] : {};
deepCopy(o[i], c[i]);
} else {
c[i] = o[i]
}
}
return c;
}
var Child = deepCopy(Parent);
Child.arr.push(4);
Child.arr; // [1, 2, 3, 4]
Parent.arr; // [1, 2, 3]
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.