Git Product home page Git Product logo

blog's People

Contributors

terryzwei avatar

Stargazers

 avatar

Watchers

 avatar  avatar

blog's Issues

前端构建工具

前端构建工具

​ 早期提到构建工具,历史最为悠久的是Make,由于Node的出现逐渐发展出一批自动化构建工具,像Grunt,Gulp,,fis, Webpack,browserify(本质上并不是构建工具,开发的初衷是为了前端引用npm引入的commonjs模块)。

grunt 与 gulp

​ grunt与gulp都是前端构建的工具,与fis,webpack,browerify这一类构建工具(构建工程化方案)不太类似,它们更偏向于工具类。一下说说grunt和gulp各自的特点。

  1. grunt特点:

    • 易学简单,只需要安装对应的模块就配置它们就可以实现对应的功能
    • 插件丰富,现在大概有5800+插件
    • 不需要先进的理念和任何经验
    /**
     * 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']);
    };
  2. gulp的特点:

    • 写法与grunt的配置不同,是普通代码的写法
    • 易于学习,构建工作就跟通过一系列流管道一样
    • 一个插件只实现一个对应的功能
    • 通过利用nodejs的流-stream,不需要再磁盘生成中间文件,便可以完成构建
    /**
     * 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

​ webpack是一个解决引用模块和打包的工具。说起模块,不得不说这两个库requirejs(AMD)和seajs(CMD),这两个库都是前端模块化开发的库。现在的nodejs就是采用与seajs一样的CMD规范。但对于wepack这种强大的引用模块工具来说,已经兼容AMD和CMD两种规范模式。接下来说说webpack的特点吧。

webapck的特点:

  1. 任何东西都是模块,包括图片,样式等,都可以使用require的方式引入
  2. 同时支持AMD和CMD规范的模块,这使得前后端(nodejs)对模块的共同使用成为可能。
  3. 内置的插件丰富,支持ES6,CoffeeScript。
  4. 使用webpack-dev-server做测试服务器,调试方便。
  5. 支持对css、图片等资源进行打包,代替gulp和grunt的工作。
  6. 内存完成打包工作,效率高。

browserify

​ browserify本质上是为了实现在前端也能使用npm中的CMD的模块,并不是一个专门打包的前端工具。但现在nodejs社区对它贡献了很多transform模块,所以现在与webpack同样是构建工程化的其中一种选择。

fis

移动端(H5)优化指南

参考:移动H5前端性能优化指南

加载优化

减少HTTP请求

手机浏览器同时支持最大连接数为4(安卓为4,iOS5以后为6;主机和域名相同的前提下的最大连接数,不过有时候是达不到这个连接数的),所以尽量减少HTTP的请求。
1.合并css、js文件;
2.合并图片(css sprite),小图片可以使用dataURL;

缓存

缓存可以减少请求服务器的次数,节约加载时间。
1.外联js、css文件;
2.缓存一切可以缓存的资源;

压缩HTML、CSS、JS文件

减少文件大小提高加载速度和显示速度,对HTML、CSS、JS进行压缩,并在服务器端设置Gzip
1.压缩html、css、js文件;
2.服务器开启GZip(服务器进行压缩,浏览器接收后解压)

无阻塞

写在头部的js文件(非异步),和嵌入在HTML标签中的style会阻塞页面渲染。因此js文件应该放到底部或使用异步加载方式(async或者defer),样式用外联的CSS文件放在头部使用link加载。

按需加载

将不影响用户的资源和用户暂时没有用到的资源放到用户需要的时候再加载;
1.lazyload
2.滚动加载

预加载

如果网站加载内容比较大,可以提前给用户一个loading显示,但是不能等待太久;

压缩图片

减少cookie

cookie会影响加载速度,所以对于静态资源应该不使用cookie

异步加载第三方资源

javascript algorithms

1.排序

1.1冒泡排序

冒泡排序,有时被称为沉没排序,是一个简单的排序算法,通过反复步骤对列表进行排序,比较每一对相邻位置上的数字和互换他们错乱的排序。通过对列表重复直到不需要互换位置,这表明列表排序完成。

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²)

1.2选择排序

选择排序是一个排序算法,明确地用一个值去作比较排序,时间复杂度是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

angular学习笔记

1.什么是双向绑定?

简单的说,就是页面上操作能实时反映到数据上,数据的改变能及时展示在页面上。

2.脏检测机制是怎么样的?手动触发和自带指令触发

脏检测机制就是检测作用域上的所有数据是否有所变动,最后再一次性更新变动的数据。可以通过$digest和$apply两种方式手动触发脏检测机制,$apply方法是从根作用域$rootScope开始检测,而digest只会检测它当前所在作用域下的数据,所以这里如果自己清楚需要更新当前作用域下的数据则使用$digest,而如果使用一些第三方插件时,建议还是使用$apply。

3.在ng-click里面调用digest为什么会报错呢?

这是因为ng-click里面虽然封装了click方法,而且最后还执行了apply()方法,把数据的变更展示到页面上去。在angular中,同一时间只允许有一个digest方法,所以如果在ng-click方法里面再调用digest会报错。
脏检测机制有利有弊,对于整个页面大部分数据都改变的,脏检测还是高效的,但是对于页面只改变一两个值,这时候脏检测就有点不太合适了。

ES6 学习笔记

字符串扩展

字符串遍历器接口

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提供了includesstartsWithendsWith三个方法

  • includes 接受一个字符串参数,判断字符串是否包含在其中,返回boolean值;
  • startsWith 两个参数,第一个字符串,第二个开始位置下标,判断是否以此字符串开始,返回boolean值;
  • endsWith 两个参数,第一个字符串,第二个是距离尾部的长度,判断是否以此字符串结尾,返回boolean值;

javascript中的原型

js中的原型

  1. 构造函数包含一个指向它原型的属性prototype,公开的属性和方法写在prototype里面,私有属性和方法在构造函数里面;实例化的对象(new构造函数)的constructor属性指向他的构造函数,但是实例对象没有prototype属性,但是部分浏览器实现了一个__proto__属性,这个属性跟构造函数的原型属性是基本一致的。
  2. 构造函数的原型有一个isPrototypeOf方法可以检测出实例对象是否与该原型存在关系;Object.getPrototypeOf用于获取实例对象的__proto__属性。
  3. hasOwnProperty可以判断当前对象拥有的属性,不会向原型链上继续获取。

《JavaScript设计模式和开发实践》读书笔记

javascript的原型继承

  • 所有的数据都是对象(应该是绝大部分数据都是对象);
  • 要得到一个对象,并不是实例化一个对象,而是要找到一个对象的原型并克隆它;
  • 对象会记住它的原型;
  • 如果对象无法响应请求,它会把请求委托给它的原型。(对象会把请求委托给自己的构造函数的原型)

理解new的过程

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

30 Seconds of CSS

Bouncing loader

创建跳动加载动画

html

<div class="bouncing-loader">
  <div></div>
  <div></div>
  <div></div>
</div>

css

@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.

  1. @keyframes定义了一个动画的两种状态,当元素改变opacity和使用tansform: translateY()属性在2D平面上跳动.
  2. .bouncing-loader是跳动循环的父级容器和使用display: flexjustify-content: center把它们定位到中间位置上.
  3. .bouncing-loader > div设置父级元素下三个div的样式.div设置宽和高1rem,使用border-radius: 50%去将它们从方形变成原型.
  4. margin: 3rem 0.2rem表明每一个原型元素的顶部/底部都有3rem的边距和左右两边有0.2rem的边距,以便它们相互之间不会黏在一起,给予它们喘息的空间.
  5. animation是各种各样动画属性的简写属性: animation-name,animation-duration,animation-iteration-count,animation-direction在这里使用了这几个属性.
  6. nth-child(n)定位到父元素下的第n个子元素.
  7. animation-delay分别使用在第二第三个div元素上,是因为每一个元素不会在相同的时间点开始动画.

Box-sizing 重置

重置盒子模型以便于widthheight都不会受到自身的border或者padding的影响.

css

html {
  box-sizing: border-box;
}
*,
*::before,
*::after {
  box-sizing: inherit;
}

解释

  1. box-sizing: border-box使padding或者border不会影响到元素的width或者height.
  2. box-sizing: inherit 使元素遵循父级元素的box-sizing规则.

浏览器支持

IE8或IE8以上.

Circle

利用纯CSS方式创建一个圆形.

HTML

<div class="circle"></div>

CSS

.circle {
  border-radius: 50%;
  width: 2rem;
  height: 2rem;
  background: #333;
}

解释

border-radius: 50%通过弯曲元素的边去创建一个圆.

js继承

先定义两个构造函数

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模式

使用构造函数的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 

Prototype直接继承

对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也会跟着变化。

Prototype使用空对象实现继承

这是为了解决上面的直接继承的问题才出现的继承方法。

// 先定义一个空的构造方法
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};

如果不是构造函数要实现继承的话,可以使用以下三种方式:

object()方法

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]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.