Giter Club home page Giter Club logo

cuf_meeting_knowledge_share's Introduction

CUF_meeting_knowledge_share

目的:

这是一个记录CUF团队每周知识分享的项目,为的是将所分享的知识进行整理,以便日后复习和分享。

记录方式:

通过New issue方式记录, issue name为日期 + 主题,例如2014-7-29: CSS Sprite , 由于issue是通过markdown方式书写,如果对markdown不熟悉的同学,可以使用stackedit.io在线编辑再粘贴。 项目中对应的日期文件夹,可以放置Example,文档或其他你想放置的东西。(更多markdown资源)

PPTs

如果分享含有PPT,请将它存放于CUF_PPTs项目。

CUF团队成员:

cuf_meeting_knowledge_share's People

Contributors

clyang82 avatar hjzheng avatar qiaojun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cuf_meeting_knowledge_share's Issues

2015-12-18 ng-conf 精彩视频 Dave Smith - Deep Dive into Custom Directives

PPT: http://slides.com/djsmith/deep-dive-into-custom-directives#/
Youtube: https://www.youtube.com/watch?v=UMkd0nYmLzY&index=3&list=PLw5h0DiJ-9PB-vLe3vaNFLG-cTw0Wo7fw

指令是 Angular 1.x 让人最喜欢的几个特性之一,同时也是让人最讨厌的特性之一,之所以指令让人喜欢,因为其易于被重用和使用,之所以讨厌它,是因为概念和配置过于复杂。

所以推荐大家观看 Dave Smith 的《Deep Dive into Custom Directives》,相信你会有不一样的收获。

关于作者PPT最后一页问题:

- Multiple directives on the same element
- How directives drive scope creation
- transclude:'element'
- Element directives for standard attributes e.g., "placeholder"

答案

  • 参见我在segmentfault上的回答
  • ?

2014-9-17 响应式设计

响应式设计(responsive web design)

什么是响应式设计?

随着用户浏览网页的设备越来越复杂(手机,平板,电脑), 之前只针对大尺寸屏幕的web设计,已经不太适合了,我们的设计需在不同设备上,做出不同响应,保证用户良好的体验,这就是响应式设计。

响应式设计的真实例子

http://colly.com
http://foodsense.is
http://www.sony.com/
https://ace.ng.bluemix.net/
http://www.ccdi.gov.cn/
https://github.com/

你可以通过改变浏览器窗口的大小或chrome dev tools的模拟器,去模拟不同设备尺寸,体验什么是响应式设计。

viewport

可视窗口, 是在meta元素中定义的,其主要作用是设置Web页面适应移动设备的屏幕大小。
移动设备通常会提供viewport默认设置, 为没有针对移动设备的网站显示看起来不错,但是响应式设计需要重新定义viewport.

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0" /> 
width指定虚拟窗口的屏幕宽度大小。
height指定虚拟窗口的屏幕高度大小。
initial-scale指定初始缩放比例。
maximum-scale指定允许用户缩放的最大比例。
minimum-scale指定允许用户缩放的最小比例。
user-scalable指定是否允许手动缩放。

像素密度(resolution)

屏幕像素密度,在一个物理尺寸上所能显示的像素数量,一般使用dpi(dots per inch)来表示,每英寸像素数。
iphone3G 162dpi 320px * 480px
iphone4 326dpi 640px * 960px
CSS pixel是一个相对值, 例如 如果10X10 pixel div 在iphone3G显示为10X10 pixel,那么在iphone4上显示为20X20 pixel, 因为为了保持一致,高密度屏对CSS pixel进行了放大, 苹果设备默认放大倍数(device pixel ratio)为2。

https://github.com/h5bp/mobile-boilerplate/wiki/Mobile-Matrices
http://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/

媒体查询(Media Queries)

媒体查询的添加方法:

  <link rel="stylesheet" media="(max-width:480px)" href="mobile.css"> 
 @media (max-width:480px) {
 ... ... 
 }

媒体类型(Media Type)

类型 说明
all 所有类型设备
tv 电视设备
print 打印设备
screen 电脑手机平板等彩色屏幕
projection 投影设备

https://developer.mozilla.org/en-US/docs/Web/CSS/@media

媒体特性(Media Feature)

media_feature: width | min-width | max-width 
  | height | min-height | max-height
  | device-width | min-device-width | max-device-width
  | device-height | min-device-height | max-device-height
  | aspect-ratio | min-aspect-ratio | max-aspect-ratio
  | device-aspect-ratio | min-device-aspect-ratio | max-device-aspect-ratio
  | color | min-color | max-color
  | color-index | min-color-index | max-color-index
  | monochrome | min-monochrome | max-monochrome 
  | resolution | min-resolution | max-resolution
  | scan | grid
  | orientation

http://www.w3.org/TR/css3-mediaqueries/#media1

操作符(and, or, not)

用于连接媒体特性和媒体特性表达式

/* and */
@media screen and (min-width: 480px) and (max-width: 767px) {
  body{
    background: #ce33eb;
  }
}

/* , 相当于or */
@media screen and ( orientation: landscape ), screen and ( min-width: 700px ) {
  body{
    background: #c0392b;
  }
}

/* 否定后面所有的条件 */
@media not screen and ( max-width:959px ){
  body{
    background: #ccc;
  }
}

响应式布局

@media ( min-width: 1200px ){
  .container{
    width: 1170px;
  }
  #mainbody{
    width: 770px;
    margin-right: 30px;
  }
  #sidebar{
    width: 370px;
  }
}

@media ( max-width: 959px){
  .container{
    width: 100%;
  }
  #mainbody{
    width: 67%;
  }
  #sidebar{
    width: 30%;
    float: right;
  }
}

@media ( max-width: 767px ){
  #mainbody, #sidebar{
    float: none;
    width: 100%;
  }
}

响应式导航菜单

响应式图片设计

响应式框架

bootstrap (http://www.bootcss.com/)
foundation (http://foundation.zurb.com/)

响应式设计资源

http://mediaqueri.es
http://responsive.cn

了解更多:

http://book.51cto.com/art/201204/328360.htm
http://www.ruanyifeng.com/blog/2012/05/responsive_web_design.html
http://www.yiiyaa.net/?p=1451

2015-6-8 使用ngModel.NgModelController

使用ngModel.NgModelController

在书写Angular指令的时候,经常需要和model进行交互, 你可以自己处理,可以使用ngModel的NgModelController进行处理。

引入NgModelController

参看 bootstrap-ui button.js Code Snapshot:

两个关键点:
require

require: 'ngModel'

link函数

link: function (scope, element, attrs, ngModelController) {
}
.directive('btnRadio', function () {
  return {
    require: ['btnRadio', 'ngModel'],
    controller: 'ButtonsController',
    link: function (scope, element, attrs, ctrls) {
     ... ...
    }
  };
})

四个value

  1. real model value, 例如 $scope.num = 100
  2. ngModelCtrl.$modelValue, 是#1的一个copy
  3. ngModelCtrl.$ViewValue, 是#4的一个copy
  4. real view value,例如 视图上真正的值, 例如input元素的value值

NgModelController的工作就是控制着四个值之间的变化,例如 如果#1发生改变,那么#4也会发生变化,反之#4变化的话,#1也会变

Value Circle

<$modelValue> → ngModelCtrl.$formatters(realModel) → $viewValue
                                                       ↓
↑                                                  $render()
                                                       ↓
↑                                                  UI changed
                                                       ↓
ngModelCtrl.$parsers(newViewValue) ← $setViewValue(newViewValue)

$render方法

当UI需要更新时,该方法会被调用,一般需要用户自己去实现该方法

$render() method 在以下的情况会被调用:

$rollbackViewValue() is called. If we are rolling back the view value to the last committed value then $render() is called to update the input control.
The value referenced by ng-model is changed programmatically and both the $modelValue and the $viewValue are different from last time.

$setViewValue方法

当UI发生变化(事件的触发等),将得到变化的值,设置给$viewValue

$formatters

一组管道, 从$modelValue$viewValue

function formatter(value) {
  if (value) {
    return value.toUpperCase();
  }
}
ngModel.$formatters.push(formatter);
$parsers

一组管道, 从$viewValue$modelValue

Example

angular-ui boostrap button.js
angular-ui bootstrap tooltip.js
Time转换 你可以使用BootCDN 引入需要的库

相关资料

ngModelController文档
Jason Aden - Using ngModelController to Make Sexy Custom Components - NG-Conf 2014
using-ngmodelcontroller-with-custom-directives

2015-7-16 7 个必不可少的 JavaScript 函数 (渣译)

7 个必不可少的 JavaScript 函数

原文地址:http://davidwalsh.name/essential-javascript-functions

我记得,早期的 JavaScript ,一个简单的功能,需要知道关于它的一切,因为不同的的浏览器厂商对特性(feature)的实现是不同的,不仅是边缘特性(feature),一些基本特性(feature)也是如此,比如 addEventListenerattachEvent。随着时间的改变,仍然有些函数是每个开发者必须放在他们的武器库里,因为它们具有更好的性能和功能。

debounce

Debounce 函数被称为变革者,当它带来性能提升时候。如果你不和 scroll, resize, key* 等事件一起使用 debounce 函数,那你可能做错了。这里的 debounce 函数会保持你代码的效率:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

// Usage
var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);
window.addEventListener('resize', myEfficientFn);

Debounce 函数在每个给定的时间里不允许回调函数被调用超过一次。这是特别重要的,当你给频繁发生的事件注册一个回调函数时。

Poll

正如我提到的 debounce 函数(译者注:前面这句不明白)。有时,你不能接收表示期望状态的结果 -- 如果这个结果不存在,你需要在一段时间内检查你的期望状态:

function poll(fn, callback, errback, timeout, interval) {
    var endTime = Number(new Date()) + (timeout || 2000);
    interval = interval || 100;

    (function p() {
            // If the condition is met, we're done! 
            if(fn()) {
                callback();
            }
            // If the condition isn't met but the timeout hasn't elapsed, go again
            else if (Number(new Date()) < endTime) {
                setTimeout(p, interval);
            }
            // Didn't match and too much time, reject!
            else {
                errback(new Error('timed out for ' + fn + ': ' + arguments));
            }
    })();
}

// Usage:  ensure element is visible
poll(
    function() {
        return document.getElementById('lightbox').offsetWidth > 0;
    },
    function() {
        // Done, success callback
    },
    function() {
        // Error, failure callback
    }
);

Polling 早已在 web 上使用,并将在未来继续发光发热!

once

有些时候,你希望给定的函数仅执行一次,类似你使用 onload 事件的方式,下面的代码提供了你所说的功能:

function once(fn, context) { 
    var result;

    return function() { 
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }

        return result;
    };
}

// Usage
var canOnlyFireOnce = once(function() {
    console.log('Fired!');
});

canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // undefined

Once 函数确保一个给定的函数仅被调用一次,因而,可以防止重复初始化!

getAbsoluteUrl

从一个字符串变量得到一个绝对路径的 URL 并不像你想的那么容易。有个 URl 构造函数但是如果你不能提供必要的参数的话(有时候,你确实不能提供参数),它不能正常工作。这里有一个取得绝对路径的奇淫巧计。

译者注: URL 构造函数 参考 MDN URL

var getAbsoluteUrl = (function() {
    var a;

    return function(url) {
        if(!a) a = document.createElement('a');
        a.href = url;

        return a.href;
    };
})();

// Usage
getAbsoluteUrl('/something'); // http://davidwalsh.name/something

isNative

如果你想覆盖一个给定的函数,需要知道它是否原生的,下面的代码可以给你答案:

;(function() {

  // Used to resolve the internal `[[Class]]` of values
  var toString = Object.prototype.toString;

  // Used to resolve the decompiled source of functions
  var fnToString = Function.prototype.toString;

  // Used to detect host constructors (Safari > 4; really typed array specific)
  var reHostCtor = /^\[object .+?Constructor\]$/;

  // Compile a regexp using a common native method as a template.
  // We chose `Object#toString` because there's a good chance it is not being mucked with.
  var reNative = RegExp('^' +
    // Coerce `Object#toString` to a string
    String(toString)
    // Escape any special regexp characters
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // Replace mentions of `toString` with `.*?` to keep the template generic.
    // Replace thing like `for ...` to support environments like Rhino which add extra info
    // such as method arity.
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );

  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // Use `Function#toString` to bypass the value's own `toString` method
      // and avoid being faked out.
      ? reNative.test(fnToString.call(value))
      // Fallback to a host object check because some environments will represent
      // things like typed arrays as DOM methods which may not conform to the
      // normal native pattern.
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }

  // export however you want
  module.exports = isNative;
}());

// Usage
isNative(alert); // true
isNative(myCustomFunction); // false

这个函数不是很漂亮,但是它能够完成任务!

insertRule

我们都知道我们可以通过一个选择器抓取 NodeList (通过 document.querySelectorAll ) 并为它们添加样式,但是更高效的方式是对选择器直接设置样式:

var sheet = (function() {
    // Create the <style> tag
    var style = document.createElement('style');

    // Add a media (and/or media query) here if you'd like!
    // style.setAttribute('media', 'screen')
    // style.setAttribute('media', 'only screen and (max-width : 1024px)')

    // WebKit hack :(
    style.appendChild(document.createTextNode(''));

    // Add the <style> element to the page
    document.head.appendChild(style);

    return style.sheet;
})();

// Usage
sheet.insertRule("header { float: left; opacity: 0.8; }", 1);

这个函数特别有用,当你工作在一个动态的,重度使用AJAX的网站时。如果你对一个选择器直接设置样式,你就不必为每个匹配该选择器的元素设置样式。

matchesSelector

通常情况下,在进行下一步之前,我们需要验证输入;确保是一个真值,确保表单数据有效。但是我们是否经常确定一个元素合格再进行下一步?你可以使用 matchesSelector 方法去校验一个元素是否与给定的选择器匹配:

function matchesSelector(el, selector) {
    var p = Element.prototype;
    var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
        return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
    };
    return f.call(el, selector);
}

// Usage
matchesSelector(document.getElementById('myDiv'), 'div.someSelector[some-attribute=true]')

每个开发者都应该将这7个JavaScript函数放入他们的工具箱中。如果我漏掉一个函数?请分享它!

2015-2-4 grunt 第一次尝试 | AngularJS 资料收集

grunt 第一次尝试

起因

最近写了一个angular-cuf-nav的项目,项目中的指令需要和其相应的模板build成一个js文件,以减少http请求。

什么是grunt

Grunt 是一个基于任务的JavaScript工程命令行构建工具。

grunt入门

grunt方法

  • grunt.initConfig方法

    用于模块配置,它接受一个对象作为参数。该对象的成员与使用的同名模块一一对应。
    每个目标的具体设置,需要参考该模板的文档。就cssmin来讲,minify目标的参数具体 含义如下:
    expand:如果设为true,就表示下面文件名的占位符(即*号)都要扩展成具体的文件名。
    cwd:需要处理的文件(input)所在的目录。
    src:表示需要处理的文件。如果采用数组形式,数组的每一项就是一个文件名,可以使用通配符。
    dest:表示处理后的文件名或所在目录。
    ext:表示处理后的文件后缀名。

  • grunt常用函数说明:

    • grunt.initConfig:定义各种模块的参数,每一个成员项对应一个同名模块。
    • grunt.loadNpmTasks:加载完成任务所需的模块。
    • grunt.registerTask:定义具体的任务。第一个参数为任务名,第二个参数是一个数组, 表示该任务需要依次使用的模块。
  • grunt常用模块:

    • grunt-contrib-clean:删除文件。
    • grunt-contrib-compass:使用compass编译sass文件。
    • grunt-contrib-concat:合并文件。
    • grunt-contrib-copy:复制文件。
    • grunt-contrib-cssmin:压缩以及合并CSS文件。
    • grunt-contrib-imagemin:图像压缩模块。
    • grunt-contrib-jshint:检查JavaScript语法。
    • grunt-contrib-uglify:压缩以及合并JavaScript文件。
    • grunt-contrib-watch:监视文件变动,做出相应动作。

Example (以angular-cuf-nav项目为例)

package.json

{
  "name": "angular-cuf-nav",
  "version": "0.0.0",
  "description": "Angular Navigation Menu",
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "bower": "^1.3.12",
    "grunt": "^0.4.5",
    "grunt-contrib-clean": "^0.6.0",
    "grunt-contrib-concat": "^0.5.0",
    "grunt-contrib-copy": "^0.7.0",
    "grunt-contrib-cssmin": "^0.11.0",
    "grunt-contrib-htmlmin": "^0.3.0",
    "grunt-contrib-uglify": "^0.7.0",
    "grunt-html2js": "^0.3.0",
    "grunt-ngmin": "0.0.3",
    "load-grunt-tasks": "^3.1.0",
    "time-grunt": "^1.0.0"
  }
}

Gruntfile.js

module.exports = function(grunt) {

  // Load grunt tasks automatically 读取你的packagejson自动加载grunt task
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

 // Project configuration.
 // 注意 <%= pkg.name %> 替换变量
 // 定义grunt task的配置
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    banner: '/*! <%= pkg.name %> by hjzheng <%= grunt.template.today("yyyy-mm-dd") %> */\n',
    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      build: {
        src: 'tmp/<%= pkg.name %>.all.js',
        dest: 'build/js/<%= pkg.name %>.min.js'
      }
    },
    cssmin: {
      options: {
        banner: '<%= banner %>' 
      },
      build: {
        src: 'src/css/<%= pkg.name %>.css',
        dest: 'build/css/<%= pkg.name %>.min.css'
      }   
    },
    //将template转换成JS
    html2js: {
      options: {
        module: 'cuf-nav-template'
      },
      main: {
        src: ['src/template/*.html'],
        dest: 'tmp/templates.js'
      }
    },
    copy: {
      main: {
         files:[
           {expand: true, cwd: 'src/js', src: ['*.js'], dest: 'tmp/'}
         ]
      }
    },
    concat: {
      main: {
       src: ['tmp/templates.js', 'tmp/<%= pkg.name %>.js'],
       dest: 'tmp/<%= pkg.name %>.all.js'
      }  
    }, 
    clean: {
      all: ['tmp', 'build/*'],
      tmp: ['tmp']
    },
    //处理uglify的bug for angular,将ngmin放在它前面处理 
    ngmin: {
      main: {
        src: 'tmp/<%= pkg.name %>.all.js',
        dest: 'tmp/<%= pkg.name %>.all.js'
      }
    }
  });

  //Load the plugin that provides the task. 手动加载grunt task
  //grunt.loadNpmTasks('grunt-contrib-uglify');
  //grunt.loadNpmTasks('grunt-contrib-cssmin');

  // Default task(s). 设置自己的task
  grunt.registerTask('default', 
               [
                 'clean:all', 
                 'copy:main', 
                 'html2js:main', 
                 'concat:main', 
                 'ngmin', 
                 'uglify', 
                'cssmin'
              ] 
  );
};

详细Grunt使用

2014-8-27 浏览器渲染过程

浏览器的渲染过程

浏览器的渲染是通过其渲染引擎实现的

什么是渲染引擎?

渲染引擎是一种对HTML文档进行解析并将其显示在页面上的工具,在浏览器中担任重要任务。

浏览器不同,渲染引擎也不同

  • Chrome、Safari、Opera浏览器中使用WebKit引擎
  • Firefox浏览器中使用Gecko引擎
  • IE浏览器中使用Trident引擎

浏览器渲染主流程

  1. 渲染引擎首先解析HTML文档,构建DOM树。同时根据外部CSS文件或页面中的style元素中的内容解析样式信息。
  2. 根据DOM树与样式信息构建渲染树。
  3. 当渲染树被构建完毕时,开始布局(layout)过程,根据渲染树中的位置信息在屏幕中布局元素(即将元素安排在指定位置)。
  4. 接下来开始绘制(paint)过程,将渲染树中的可视化信息绘制在屏幕中。

这是一个渐进的过程。为达到更好的用户体验,渲染引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其余内容的同时,呈现引擎会将部分内容解析并显示出来。 这也就是我们为什么将CSS文件在html头中引入的原因。

渲染过程中layout和paint的区别

  • layout
    当窗口尺寸被修改(resize),发生滚动操作,或position、display、width、height等与元素位置相关的样式属性值被更新时触发布局过程。在布局过程中由于要计算所有元素的位置信息,更加会降低页面加载性能。在WebKit引擎中把布局过程称为Layout过程,在Gecko引擎中把绘制过程称为Reflow过程。
  • paint
    当color、background-color、visiblity、outline等与视觉相关的样式属性值被更新时触发绘制过程。在绘制过程中由于要重计算元素的视觉信息,所以会降低页面加载性能。在WebKit引擎中把绘制过程称为Painting过程,在Gecko引擎中把绘制过程称为Repaint过程。

触发layout和paint的原因

  • 元素的追加、修改与删除
  • 动画
  • 样式修改
  • 元素的class属性值修改
  • hover伪类选择器所触发的元素状态改变
  • 由用户在input元素中的输入而引起的文字节点改变
  • 使用offsetWidth、offsetHeight或getComputedStyle取得样式属性值
  • 文字字体的改变
  • 窗口尺寸的改变(resize)
  • 元素透明度的改变
  • 页面或元素内的滚动

如何减少layout和paint

  • Javascript
    • 通过DocumentFragment减少DOM操作时引起的布局次数
    • 通过复制减少DOM操作时引起的布局次数
    • 使用class汇总多个样式修改
    • 设置动画帧率在60FPS以内
  • CSS
    • 使用position:fixed固定布局对性能产生负面影响
    • 对执行动画的元素使用position:absolute可以缩小布局范围
    • overflow:scroll所引起的滚动将对页面性能产生较大影响
    • 使得布局过程或绘制过程消耗较多资源成本的样式属性
      @font-face
      animation
      transition
      box-shadow
      border-radius
      gradient
      opacity
      background-size
      text-align

如何监测layout和paint

使用chrome dev tools的timeline panel监测layout和paint,从而有针对性的优化页面

扩展阅读

CSS Triger
Pixels are expensive
the runtime performance checklist
浏览器是如何工作的?
使用dev tools timeline panel

2014-9-24 HTML5 Slides (上)

HTML5 Slides (上)

关于HTML5, 其实我们一直再说, 从来没有认真过, 下面是Chun Lin Yang同学分享的HTML5 Slides.

Offline / Storage

  • Web Storage
  • Web SQL Database
  • IndexedDB
  • Application Cache
  • Quota API

Realtime / Communication

  • Web Workers
  • WebSocket
  • Notifications

File / Hardware Access

  • Native Drag & Drop
  • Desktop Drag-In (File API)
  • Desktop Drag-Out
  • FileSystem APIs
  • Geolocation
  • Device Orientation
  • Speech Input

Semantics & Markup

  • Better semantic tags
  • Markup for applications
  • Descriptive link relations
  • Microdata
  • ARIA attributes
  • New form types
  • Form field types on mobile

HTML5 Slides

你可以从这里访问HTML5 Slides
http://slides.html5rocks.com/#landing-slide

2014-9-11 CSS3 2D Transform | BlueMix Case Study | chrome dev tools mobile-emulation | Google Material Design

CSS3 2D transform (Hao Ju Zheng)

2D transform

通过 CSS3 2D转换, 我们能够对元素进行移动、缩放、转动、拉长或拉伸。

浏览器支持
IE9,IE10,Chrome,FireFox

学习资料
W3Cschool Transform教程
Example1
Example2

Transform 常用变换函数

函数 描述
matrix(n,n,n,n,n,n) 定义 2D 转换,使用六个值的矩阵。
translate(x,y) 定义 2D 转换,沿着 X 和 Y 轴移动元素。
translateX(n) 定义 2D 转换,沿着 X 轴移动元素。
translateY(n) 定义 2D 转换,沿着 Y 轴移动元素。
scale(x,y) 定义 2D 缩放转换,改变元素的宽度和高度。
scaleX(n) 定义 2D 缩放转换,改变元素的宽度。
scaleY(n) 定义 2D 缩放转换,改变元素的高度。
rotate(angle) 定义 2D 旋转,在参数中规定角度。
skew(x-angle,y-angle) 定义 2D 倾斜转换,沿着 X 和 Y 轴。
skewX(angle) 定义 2D 倾斜转换,沿着 X 轴。
skewY(angle) 定义 2D 倾斜转换,沿着 Y 轴。

如何兼容IE8,7,6
http://www.useragentman.com/IETransformsTranslator/

扩展知识
2D矩阵变换原理

标准浏览器:matrix(1,0,0,1,0,0)
            matrix(a,b,c,d,e,f)

IE8,7,6:   progid:DXImageTransform.Microsoft.Matrix(
            M11=1, M12=0,M21=0,M22=1,SizingMethod='auto expand');
            M11 == a
            M12 == c
            M21 == b
            M22 == d
  • 矩阵实现位移(disX和disY为偏移距离)
$$x位移: e = e + disX y位移:f = f + disY$$
  • 矩阵实现缩放(x和y为缩放倍数)
$$x轴缩放: a = x*a; c=x*c; e=x*e y轴缩放: b = y*b; d=y*d; f=y*f$$
  • 矩阵实现倾斜(xDeg和yDeg为扭曲角度)
$$c = Math.tan(xDeg/180*Math.PI) b = Math.tan(yDeg/180*Math.PI)$$
  • 矩阵实现旋转(deg是旋转角度)
$$a = Math.cos(deg/180*Math.PI); b = Math.sin(deg/180*Math.PI); c = -Math.sin(deg/180*Math.PI); d = Math.cos(deg/180*Math.PI);$$

矩阵函数的使用Example

  • 实战 在div元素中实现文字旋转居中
    • step1 写两个嵌套div(外层相对定位,内层绝对定位),外层的高是内层的宽,外层的宽是内层的高
    • step2 使内层div文字居中,可选,通过left,top调整内层div的位置
    • step3 通过调整内层div的transform-origin, 以它为旋转中心,进行旋转

CSS3 2D Transform PPT

BlueMix Case Study (Hao Zhang)

2014-12-23 CommonJS AMD CMD and UMD | 一周前端好文分享

CommonJS AMD CMD and UMD (Zhen Ou Yun)

  • CommonJS
  • AMD(Asynchromous Module Definition)
  • CMD(Common Module Definition)
  • UMD(Universal Module Definition)

CommonJS

  • CommonJs 是服务器端模块的规范,Node.js采用了这个规范 (Modues/1.x)
  • 一个单独的文件就是一个模块
  • 加载模块是同步的

AMD(Asynchromous Module Definition)

  • AMD 是 RequireJS 在推广过程中对模块定义的规范化产出
  • AMD异步加载模块

CMD(Common Module Definition) 延自CommonJS Modules/2.0规范

  • CMD是SeaJS 在推广过程中对模块定义的规范化产出
  • 对于依赖的模块AMD是提前执行,CMD是延迟执行。不过RequireJS从2.0开始,也改成可以延迟执行(根据写法不同,处理方式不通过)
  • CMD推崇依赖就近,AMD推崇依赖前置

UMD(Universal Module Definition)

  • UMD是AMD和CommonJS的糅合
  • AMD 浏览器第一的原则发展 异步加载模块
  • CommonJS 模块以服务器第一原则发展,选择同步加载,它的模块无需包装(unwrapped modules)
  • UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。 在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块

2014-8-5: 从输入URL到页面加载完成的过程中都发生了什么事情 | nodejs和express

  1. 从输入 URL 到页面加载完成的过程中都发生了什么事情 (Zhen Ou Yun)
    这是一个可以简单也可以复杂的问题,它没有标准答案,考验回答者知识的广度和深度。有兴趣的同学可以试着回答一下,在看下面链接之前。

    参考
    http://fex.baidu.com/blog/2014/05/what-happen/
    http://www.berlinix.com/net/from-url-input.php

  2. nodejs和express (Hao Ju Zheng)
    在开发CUF项目时候,有时候需要对前端组件进行动态数据测试(数据从后端过来)或这书写Example,例如查询,分页,删除等操作,使用传统服务器端语言,就有点小题大做了。传统服务器端语言,像Java,需要配置struts.xml,书写action,重启tomcat,这些都过于繁琐和低效。

    基于上述背景,决定选用nodejs作为后端服务器, Javascript作为nodejs的语言与前端配合具有其天生的优势:

    • 对JSON数据操作极其容易
    • 丰富的模块和包(express框架可以通过三行code实现一个Ajax请求)
    • 通过包supervisor支持即改即生效

    如何开始nodejs和express之路

    • 安装nodejs

      • 下载安装包(这里以Linux为例)
      • 解压,并将bin目录加入环境变量path中,如果是bash,在.bash_profile中加入下面的code
        PATH=$PATH:/opt/nodejs/node-v0.10.30-linux-x64/bin
      
        export PATH 
      • 重现登陆你的shell
    • 安装express

      • 使用npm安装express和express-generator
        npm install express
      
        npm install -g express-generator
      • 创建express web项目(使用express创建基于ejs模板的项目)
        express -e ./myapp
      • 安装依赖
        npm install
        npm start
    • 写一个的ajax请求

      • 修改routes/users.js
        router.get('/', function(req, res) {
          res.setHeader('Content-Type', 'application/json;charset=utf-8');
          res.send({id: 1, username: 'hjzheng', password: 'hjzheng'});
        });
    • 对应的目录有写好的CRUD ajax请求模板,有兴趣的同学可以参考一下

2016-2-16 2015 CUF Team 总结

关于 2015 CUF Team 总结

背景
  • Common Team (CUF Team): 2个前端工程师,有 Java 开发能力。
  • Product Teams: 40多个 Java 工程师,没有独立前端开发能力,当UX设计出新页面的时候,需要 Common Team 进行支持(如果现有的CUF JS库可以满足,就不需要,如果不能满足,就需要提供组件或者直接帮着做)。
  • 面临前端技术全面更换的问题。
前端新技术调研 (已经完成)
  • 关注业界流行趋势,结合团队实际情况,选择技术进行调研。
    • 前端开发中存在哪些问题
    • 新技术用来解决哪些问题
  • Common Team 内部自己先实践,出 demo 和最佳实践。
    • 如何更好的应用新技术
    • 新技术的最佳实践
新技术落地问题 (目前最大的问题)
  • 与 Product Team 工程师合作。
    • 培训
  • 设计端到端的完整工作流。
    • 参与到产品开发中去,整合前后端资源,设计完整流程和方案
目前的现状

当前已经有一个 Product Team 在使用我们的成果,但是只是将最佳实践的代码拿过去用,并没有结合自己的实际情况去设计完整的方案,还是旧的手工开发模式,没有将gulp等自动化方式整合进去。

产生这样情况的原因:

第一,是 Common Team 的定位问题,我们将自己定义为一个辅助角色。而不是主导角色,很难将前后端资源整合到一起,只是出了问题,帮忙解决问题。

第二,Team 内部缺乏具有前后端架构能力的人。 我们最初设计是前后端分离,后端使用标准 RESTful API 的形式,通过 gulp 针对不同的环境进行API切换,但现实的问题是,Product Team 没有时间或者不愿意将后台修改成标准 RESTful,这个完全是 Common Team 自己闭门造车的造成的结果,没有结合后端实际情况的设计,这也是为什么需要 Common Team 的人参与到实际产品中,并主导产品端到端的设计的原因。

第三,缺少 Manager 强有力的支持。这是这种以 Business 为导向公司的通病,产品经理不会在乎产品架构设计,一旦新需求来临,产品经理们只在乎能否以最快的速度做完,要求工程师给出 plan,再加上某 UX 的奇葩的设计,所以也导致了 Product Team 直接将代码拿过去用的结果。

另外据说还有两个 Product Team 准备去用最佳实践。

下一步,如何做

如何做,其实不难:

首先,Common Team 需要重新定位自己,扩大 Team 影响力,具有一定的自主能力,不能再和之前一样,受其他因素的干扰,比如,其他 team 缺人,被借去帮忙,再比如,某 UX 竟然都可以干预实现,决定用何种技术:必须用 SVG ,不能用 iconfont 。

第二,如上面所提到的落地问题的方案,对 Product Team 的工程师进行培训,让他们体会到新技术的好处,这样日后在产品中使用新技术,不会有畏难和抵制的情况。(人面对未知事物时,或多或少会有抵触心理)

第三, 一定要参与到产品的实际架构中去,结合实际情况去主导整个架构的设计,不要闭门造车。(这样做,显然是有难度的,具体原因就不明说了)

第四,提高自身的技术和业务水平,具备前后端架构的能力,影响更多的 Product Team 的工程师,让他们具有独立架构前端基本能力,因为现在的前端技术发展速度之快,是任何人都无法想象,再也不能像以前一样,一种技术吃好几年。

2014-12-8 AngularJS 执行流程 | 如何使用RequireJS管理AngularJS和Dojo

AngularJS 执行流程

首先感谢慕课网提供的阿里懒懒交流会的视频,本人是受益匪浅的,这次主要是想分享由城池同学分享的AngularJS执行流程的视频

通过对AngularJS源码(基于AngularJS v1.3.3源码)的分析,将AngularJS执行流程分为三大块:

  • bindJQuery
  • publishExternalAPI
  • angularInit
  //AngularJS源码25741 - 25747行
  bindJQuery();

  publishExternalAPI(angular);

  jqLite(document).ready(function() {
    angularInit(document, bootstrap);

bindJQuery

判断是否引入JQuery,如果没有就内置JQlite(对JQuery的轻量级实现)

publishExternalAPI

  • 挂载常用API,如:bootstrap,forEach等方法(源码2111行 -- 2142行)
  • 将nglocate挂载到angular.module上 (源码2146行)
  • 将ng挂载到angular.module上 (源码2151行)
  • 注意源码2144行 setupModuleLoader方法 如何实现挂载module,该方法在源码1665行注意该方法返回的对象,这个是angularjs实现链式操作的关键
//源码1952 return moduleInstance
 var moduleInstance = {
     // Private state
     _invokeQueue: invokeQueue,
     _configBlocks: configBlocks,
     _runBlocks: runBlocks,
     requires: requires,
     name: name,
     provider: invokeLater('$provide', 'provider'),
     factory: invokeLater('$provide', 'factory'),
     service: invokeLater('$provide', 'service'),
     value: invokeLater('$provide', 'value'),
     constant: invokeLater('$provide', 'constant', 'unshift'),
     animation: invokeLater('$animateProvider', 'register'),
     filter: invokeLater('$filterProvider', 'register'),
     controller: invokeLater('$controllerProvider', 'register'),
     directive: invokeLater('$compileProvider', 'directive'),
     config: config,
 ... ...

angularInit

  • 通过ng-app="xx",取出moduleName (源码1324行)
  • bootstrap(appElement, [module]) (源码1403行)
  • createInjector (源码1434行) 实现依赖注入
createInjector(modules)
//经所有provider存放在这里
provideCache: {$provider, $injector}
//如果调用过,存在这里
instanceCache: {$injector}

042315138498282

2014-8-12 CSS选择器

  1. CSS选择器 (Chun Lin Yang)
    大家在使用CSS选择器的时候,由于考虑浏览器的兼容性,基本上使用的都是些简单的选择器,不但错过一些高级选择器的使用,还错误的认为IE8不支持某些高级选择器,所以希望下面的选择器兼容表格,可以让你大胆的使用某些高级选择器。

    选择器 Example description IE FireFox Chrome
    基本选择器
    * * 选择所有元素 7 1 0.2
    #id #header 选择 id="header" 的元素 5 1 0.2
    .class .item 选择 class="item" 的所有元素 full 7, part 5 1 0.2
    Element p 选择所有 <p> 元素 5 1 0.2
    Element,Element div,p 选择所有<div>和<p> 元素 5 1 0.2
    属性选择器
    [attribute] [target] 选择具有target属性的所有元素 7 1 0.2
    [attribute=value] [target=_black] 选择具有target='_black'的所有元素 7 1 0.2
    [attribute~=value] [class~=item] 选择具有class属性且含有单词item的元素 7 1 0.2
    [attribute*=value] [title*=flower] 选择具有title属性且含有flower的元素 7 1 0.2
    [attribute^=value] [title^=a] 选择具有title属性且vlaue以a开头的元素 7 1 0.2
    [attribute$=value] [title$=z] 选择具有title属性且value以z结尾的元素 7 1 0.2
    层次选择器
    Element+Element div+p 选择紧接在<div>元素之后的<p>元素 7 1 0.2
    Element~Element div~p 选择前面有<div>元素的每个<p>元素 7 1 0.2
    Element Element div p 选择<div>元素包含的所有<p>元素 5 1 0.2
    Element>Element div>p 选择<div>元素直接子元素为<p>的元素 7 1 0.2
    伪类选择器
    动态伪类选择器
    :link a:link 选择未被访问过的a元素 5 1 0.2
    :visited a:visited 选择已被访问过的a元素 5 1 0.2
    :active a:active 选择激活状态的a元素 8 1 0.2
    :hover a:hover 选择鼠标悬停在a元素上 full 7, part 5 1 0.2
    :foucs a:focus 选择获得焦点的a元素 8 1 0.2
    UI元素伪类状态选择器
    :checked input:checked 选择选中的checkbox或者radio元素 9 1 0.4
    :enabled input:enabled 选择启用的input元素 9 1 0.2
    :disabled input:disbaled 选择禁用的input元素 9 1 0.2
    目标伪类选择器
    :target a:target 选择当前活动的<a>元素 9 1 0.2
    结构伪类选择器
    :nth-child li:nth-child(2) 选择li父级下的第二个子元素,并且这个元素还的是li元素 9 1 0.4
    :nth-last-child li:nth-last-child(2) 选择li父级下的第二个子元素(从后计算),并且这个元素还是li元素 9 1 0.4
    :nth-of-type li:nth-of-child(2) 选择li父级下的第二个li元素 9 1 0.4
    :nth-last-of-type li:nth-last-of-type(2) 选择li标签父级下的第二个li元素(从后计算) 9 1 0.4
    :first-child li:first-child 选择li父级下的第一个子元素,并且这个元素还是li元素 9 1 0.4
    :first-of-type li:first-of-type 选择li父级下的第一个li子元素 9 1 0.4
    :last-child li:last-child 选择li父级下的最后一个子元素,并且这个元素还是li元素 9 1 0.4
    :last-of-type li:last-of-type 选择li父级下的最后一个li子元素 9 1 0.4
    :only-child li:only-child 选择li父级下只含有一个子元素,并且这个元素还是li元素 9 1 0.4
    :only-of-type li:only-of-child 选择li父级下只含有一个li子元素 9 1 0.4
    :empty li:empty 选择子元素为空的li标签(子元素包含文本节点) 9 1 0.4
    否定伪类选择器
    :not div:not(p) 选择子元素中不含有p的div元素 9 1 0.2
    伪元素选择器
    ::before div::before 在每个<div>元素的内容之前插入内容 8 1 0.2
    ::after div::after 在每个<div>元素的内容之后插入内容 8 1 0.2
    ::first-line p::first-line 选择每个<p>元素的内容的第一行 5.5 1 0.2
    ::first-letter p::first-letter 选择每个<p>元素的内容的首字母 5.5 1 0.2

    Examples (Hao Ju Zheng)

    让IE8支持CSS3选择器 (Hao Ju Zheng)
    http://selectivizr.com/

2015-6-19 Angular资料整理(Angular Style Guide and so on)

2015-1-13 D3(Data-Driven Documents)

D3(Data-Driven Documents)

什么是D3?

这里的D3,首先不是尼康相机也不是暗黑破坏神3更不是维生素。

摘自数据可视化实战:使用D3设计交互式图表

D3(有时候也叫D3或d3.js)是一个JavaScript库,用于创建数据可视化图形。
事实上,D3是一个缩写,它的全称叫Data-Driven Documents(数据驱动的文档)。
数据来源于你,而文档就是基于Web的文档(或者网页),代表可以在浏览器中展现的一切,
比如HTML、SVG。D3扮演的是一个驱动程序的角色,因为它联系着数据和文档。

D3优点

  • 资料丰富,案例非常多。
  • SVG矢量图形的特点是无损缩放,这个优势在显示2D图形式会有非常好的效果,并且兼容各种分辨率。
  • SVG图形的节点可以像dom元素一样控制,这就让自主创作图形变得更容易。相对于canvas这也是非常大的优势。

D3缺点

  • SVG是2D矢量图,不能画3D图形。(用2D矢量可以画很多带透视效果的伪3D图,那并不是真正的3D图!)
    d3.
  • 不支持IE6,7,8。如果想要IE8使用d3,请用r2d3.js(一个结合了 Raphael.js的扩展库)。Raphael.js是一个跨浏览器的矢量图形库,它实现IE6,7,8兼容的方法是:在IE6,7,8中使用VML,在其他浏览器中使用SVG。另外,如果图形复杂,就不要指望用Raphael.js在IE上能跟D3画出一样酷炫的效果。
  • SVG的节点都是对象,非常占用内存。例如论坛里一个朋友使用d3绘制超过12000个节点的图,直接导致每个试图打开它的浏览器都崩溃了。这个时候如果不愿意做简化那么应该试试canvas绘图。

一个例子, 基于AngularJS (http://projects.delimited.io/experiments/last-fm/)

angular.module('viz').directive('toptagChart', ['lastfm', 

  function (lastfm) {

    var link = function ($scope, $el, $attrs) {
      //定义大小
      var diameter = 500;

      //使用pack布局,关于pack你可以查看D3 API
      var bubble = d3.layout.pack()
        .sort(null)
        .size([diameter, diameter])
        .padding(2.5);

      //创建svg元素,并定义大小 
      var svg = d3.select($el[0]).append("svg")
        .attr({width: diameter, height: diameter})
        .attr("viewBox", "0 0 " + diameter + " " + diameter);

      //追加g元素 
      var chart = svg.append("g");

      //追加text元素,显示loading
      chart.append("text").attr("id", "loading")
        .text("Loading...")
        .attr("transform", "translate(200,250)");

      var update = function () {
        var data = $scope.toptags.map(function (d) {
          d.value = d[$scope.tagsize];
          return d;
        });

        //将数据塞入pack布局中,pack布局会
        //自动帮我们计算坐标和bubble的半径大小根据value
        bubble.nodes({children: data});

        //data如果有数据,删除text元素
        if (data.length) chart.select("#loading").remove();

        //选取所有class为node元素
        //很多人很奇怪,为啥元素没有创建,却要去选取
        //这就是D3的特点,通过下面的enter()方法先占位
        //enter(), 这个方法会分析当前选择的DOM 元素和传给它的数据,
        //如果数据值比对应的DOM 元素多,就创建一个新的占位元素。
        //然后把这个新占位元素的引用交给链中的下一个方法
        var selection = chart.selectAll(".node")
          .data(data);

        //enter方法占位,追加g元素,并添加node class
        var enter = selection.enter()
          .append("g").attr("class", "node")
          .attr("transform", function (d) { 
            return "translate(" + d.x + "," + d.y + ")"; 
          });

        //在g元素里面添加圆,利用pack布局计算好的圆心坐标和半径
        enter.append("circle")
          .attr("r", function (d) { return d.r; })
          .style("fill", '#FFCB72')
          .on("click", function (d) {
            svg.selectAll("circle").style("fill", '#FFCB72');
            d3.select(this).style("fill", "#19314A");

            lastfm.topArtists(d.name)
              .success(function (res) {
                if (res.error) {
                  throw new Error(res.message);
                } else {
                 $scope.currtag = d.name;
                  var artists = res.topartists.artist.map(function (a) {
                    a.genre = d.name;
                    a.arank = +a['@attr'].rank;
                    return a;
                  });
                  $scope.artists = artists;
                }
              });
          });

        //在g元素里追加文本
        enter.append("text")
          .attr("dy", ".3em")
          .style("text-anchor", "middle")
          .text(function (d) { return d.name; });

        //当圆心坐标改变时,增加translation效果
        selection.transition().duration(2000)
          .attr("transform", function (d) { 
            return "translate(" + d.x + "," + d.y + ")";
          });

        //当圆的半径改变时,增加translation效果
        selection.selectAll("circle").transition().duration(3000)
          .attr("r", function (d) { return d.r; });

        resize();
      };

      function resize() {
        svg.attr("width", $el[0].clientWidth);
        svg.attr("height", $el[0].clientWidth); //It's a square
      }

      $scope.$on('windowResize',resize);
      //tagsize如果有变化,调用update方法
      $scope.$watch('tagsize', update);
      $scope.$watch('toptags', update);

    };
    return {
      template: '<div class="chart col-sm-12 col-md-12 col-lg-12 col-xl-12"></div>',
      replace: true,
      link: link, 
      restrict: 'E' 
    };
}]);

另一个例子,是我自己写的(http://get-set.cn/front-end-chart/)

代码: https://github.com/hjzheng/front-end-collect

参考资料

我涉及的数据可视化的实现技术和工具
数据可视化实战:使用D3设计交互式图表
Creating Custom D3 Directives in AngularJS

2015-5-30 使用gulp

为什么使用gulp?

首先看一篇文章 Gulp的目标是取代Grunt

根据gulp的文档,它努力实现的主要特性是:

  • 易于使用:采用代码优于配置策略,gulp让简单的事情继续简单,复杂的任务变得可管理。
  • 高效:通过利用node.js强大的流,不需要往磁盘写中间文件,可以更快地完成构建。
  • 高质量:gulp严格的插件指导方针,确保插件简单并且按你期望的方式工作。
  • 易于学习:通过把API降到最少,你能在很短的时间内学会gulp。构建工作就像你设想的一样:是一系列流管道。

Gulp通过流和代码优于配置策略来尽量简化任务编写的工作。

别的先不说,通过代码来比较两者(gulp VS grunt)
可以参照我的代码,也可以阅读该文章
Gruntfile.js
gulpfile.js

两者的功能基本类似,gulp是通过代码完成任务,体现了代码优于配置的原则,对程序员更加友好,另外它也可以将多个功能一次性串起来,不需要暂存在本地,体现了对流的使用,这个可以阅读该文章里的例子。

一些资料

Gulp官网 http://gulpjs.com/
Gulp中文网 http://www.gulpjs.com.cn/
Gulp插件 http://gulpjs.com/plugins/
Awesome Gulp https://github.com/alferov/awesome-gulp

2015-3-5 Shim和Polyfill的区别

Shim 和 Polyfill 的区别

在JavaScript的世界里,有两个词经常被提到,shim和polyfill.它们指的都是什么,又有什么区别?

Shim

一个shim是一个库,它将一个新的API引入到一个旧的环境中,而且仅靠旧环境中已有的手段实现.

Polyfill

在2010年10月份的时候,Remy Sharp在博客上发表了一篇关于术语"polyfill"的文章,

一个polyfill是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能.

因此,一个polyfill就是一个用在浏览器API上的shim.我们通常的做法是先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill.然后新旧浏览器就都可以使用这个API了.术语polyfill来自于一个家装产品Polyfilla:

Polyfilla是一个英国产品,在美国称之为Spackling Paste(译者注:刮墙的,在**称为腻子).记住这一点就行:把旧的浏览器想象成为一面有了裂缝的墙.这些polyfill会帮助我们把这面墙的裂缝抹平,还我们一个更好的光滑的墙壁(浏览器)

Example

  1. Paul Irish发布过一个Polyfill的总结页面“HTML5 Cross Browser Polyfills”.
  2. es5-shim是一个shim,而不是polyfill.因为它是在ECMAScript3的引擎上实现了ECMAScript5的新特性,而且在Node.js上和在浏览器上有完全相同的表现(译者注:作者的意思是因为它能在Node.js上使用,不光浏览器上,所以它不是polyfill).

译者注:按照作者的解释,"polyfill是专门兼容浏览器API的shim,shim的范围更大些".照我看来,这个解释并不正确.但对这样两个连母语是英语的人们也很难理解的词,我也无能为力了.希望真正理解的朋友给讲下.

至于翻译,我觉的就不需要翻译了(类似bug这样的词).如果担心读者不懂,可以用脚注的方式说明一下.或者直接翻译成"兼容代码",再或"模拟该API的代码"等短语也可以吧.

原文地址: http://www.cnblogs.com/ziyunfei/archive/2012/09/17/2688829.html

更多资料: http://www.ituring.com.cn/article/details/766

2014-11-5 SVG入门

SVG

什么是SVG?

可缩放矢量图形是基于可扩展标记语言(标准通用标记语言的子集),用于描述二维矢量图形的一种图形格式。它由万维网联盟制定,是一个开放标准。

SVG与浏览器

IE8及其以下版本 安装插件Adobe SVG viewer or 引入svg web的js文件 (https://code.google.com/p/svgweb/)

Inline SVG:
IE9, Firefox 4, Chrome 7, Safari 5.1, Opera 11.6
iPhone 3.2, Android 3.0 - Partial

SVG Animations
Firefox 4.0, Chrome 4, Safari 5.0, Opera 9.0
iPhone 5.0, Android 3.0 - Partial

Canvas 与 SVG 的比较

下表列出了 canvas 与 SVG 之间的一些不同之处。
Canvas

  • 依赖分辨率
  • 不支持事件处理器
  • 弱的文本渲染能力
  • 能够以 .png 或 .jpg 格式保存结果图像
  • 最适合图像密集型的游戏,其中的许多对象会被频繁重绘

SVG

  • 不依赖分辨率
  • 支持事件处理器
  • 最适合带有大型渲染区域的应用程序(比如谷歌地图)
  • 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
  • 不适合游戏应用

实例学习

如何引入SVG

  • svg 基于xml的技术
  • svg文件(参考对应的日期文件夹中svg_include.html)
    • 写法
    • 图片<img src="file.svg"> ,样式背景,框架<iframe src="file.svg">
    • 直接在html页面中添加svg

SVG中的基本图形

  • 矩形 <rect>
  • 圆形 <circle>
  • 椭圆 <ellipse>
  • 线 <line>
  • 折线 <polyline>
  • 多边形 <polygon>
  • 路径 <path>

SVG中的分组标签

  • 分组标签<g>

SVG中的滤镜

SVG中的渐变

SVG中的动画
example

SVG库

2014-11-18 bower浏览器端库管理工具

Bower:浏览器端库管理工具

随着网页功能变得越来越复杂,同一张网页加载多个JavaScript函数库已经很常见。开发者越来越需要一个工具,对浏览器端的各种库进行管理,像NPM一样,Bower就是为了解决这个问题而诞生的针对浏览器端的库管理工具。

Bower基于node.js,所以安装之前,必须先确保已安装node.js。

安装 bower

npm install bower -global

使用 bower

帮助

bower help

安装库

bower install jquery

默认情况下,会安装该库的最新版本,但是也可以手动指定版本号。

bower install jquery-ui#1.10.1

上面的命令指定安装jquery-ui的1.10.1版。

如果某个库依赖另一个库,安装时默认将所依赖的库一起安装。比如,jquery-ui依赖jquery,安装时会连jquery一起安装。

安装后的库默认存放在项目的bower_components子目录,如果要指定其他位置,可在.bowerrc文件的directory属性设置。

库的查找

bower search jquery

查看库的信息

bower info jquery-ui

更新库

bower update angularjs

卸载库

bower uninstall angularjs

列出当前安装的库

bower list

bower 配置文件

.bowerrc

{
  "directory" : "components",
  "json"      : "bower.json",
  "endpoint"  : "https://Bower.herokuapp.com",
  "searchpath"  : "",
  "shorthand_resolver" : ""
}
  • directory:存放库文件的子目录名。
  • json:描述各个库的json文件名。
  • endpoint:在线索引的网址,用来搜索各种库。
  • searchpath:一个数组,储存备选的在线索引网址。如果某个库在endpoint中找不到,则继续搜索该属性指定的网址,通常用于放置某些不公开的库。
  • shorthand_resolver:定义各个库名称简写形式。

bower.json

{
  "name": "app-name",
  "version": "0.1.0", 
  "dependencies": {
    "sass-bootstrap": "~3.0.0",
    "modernizr": "~2.6.2",
    "jquery": "latests"
  }
}

http://javascript.ruanyifeng.com/tool/bower.html

2015-7-10 使用UI Router实现AngularJS 多步骤表单(渣译)

使用UI Router实现AngularJS 多步骤表单(渣译)

原文地址: https://scotch.io/tutorials/angularjs-multi-step-form-using-ui-router

今天,我们将使用 AngularJS,UIRouter 和 AngularJS ngAnimate 模块去创建一个动态的多步骤表单。这项技术可以被用于大型表单。我们也可以看到该技术被用于 Web 上的很多地方。像购物车,注册表单,入职流程,等已经通过使用多步骤表单形式提高用户舒适度的在线表单。下面就是我们所要创建的:

qq 20150710172814

UI Router 具有的如下功能:

嵌套状态 ( nested states ) 并且每个状态对应不同的视图的功能, 利用这些功能,我们能很容易的制作一个多步骤表单。为了快速理解它的好处和 UI Router 是如何工作,请查阅我们的其它文章: AngularJS Routing Using UI-Router 。让我们言归正传,开始创建我们精彩的表单!

建立工程

我们将为应用使用简单的结构,需要一个 layout 文件,表单每一部分的视图文件,一个样式表和保存所有 Angular 代码的 JavaScript 文件。

下面是我们的应用程序的文件。创建这些文件,我们将开始填写他们。

- index.html
- form.html
- form-profile.html
- form-interests.html
- form-payment.html
- app.js
- style.css

每个 form-____.html 的文件将会被作为嵌套视图用于表单中,这些是将要创建的表单的每一部分。

Layout/Template 文件 (index.html)

让我们开始工程,使用 index.html 作为 main 文件,在 index.html 导入所有的资源( AngularJS, ngAnimate, UI Router, JavaScript 脚本和样式 )并放置 ui-view 告诉 UI Router 在哪里插入视图,我们也会使用 Bootstrap 快速设置样式。

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">

    <!-- CSS -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootswatch/3.1.1/darkly/bootstrap.min.css">
    <link rel="stylesheet" href="style.css">

    <!-- JS -->
    <!-- load angular, nganimate, and ui-router -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-animate.min.js"></script>
    <script src="app.js"></script>

</head>

<!-- apply our angular app -->
<body ng-app="formApp">

    <div class="container">

        <!-- views will be injected here -->
        <div ui-view></div>

    </div>

</body>
</html>

随着所有的文件装载完毕,让我们进入 app.js , 开始创建我们的 Angular 应用和基于状态的路由。注意 formApp 是如何应用到 body 上的。

构建 Angular 应用 ( app.js )

我们将会创建我们的应用和路由。对大型应用,你会将 angular 应用,路由和控制器分开放入它们各自单独的模块中,但是对于我们的目标,我们会将它们放在一块。

`````` app.js```

// app.js
// create our angular app and inject ngAnimate and ui-router 
// =============================================================================
angular.module('formApp', ['ngAnimate', 'ui.router'])

// configuring our routes 
// =============================================================================
.config(function($stateProvider, $urlRouterProvider) {

    $stateProvider

        // route to show our basic form (/form)
        .state('form', {
            url: '/form',
            templateUrl: 'form.html',
            controller: 'formController'
        })

        // nested states 
        // each of these sections will have their own view
        // url will be nested (/form/profile)
        .state('form.profile', {
            url: '/profile',
            templateUrl: 'form-profile.html'
        })

        // url will be /form/interests
        .state('form.interests', {
            url: '/interests',
            templateUrl: 'form-interests.html'
        })

        // url will be /form/payment
        .state('form.payment', {
            url: '/payment',
            templateUrl: 'form-payment.html'
        });

    // catch all route
    // send users to the form page 
    $urlRouterProvider.otherwise('/form/profile');
})

// our controller for the form
// =============================================================================
.controller('formController', function($scope) {

    // we will store all of our form data in this object
    $scope.formData = {};

    // function to process the form
    $scope.processForm = function() {
        alert('awesome!');
    };

});

现在,我们拥有了依赖注入 ngAnimate 和 ui.router 的 Angular 模块,也有已经创建好的路由。注意,在这里我们如何为每个状态定义 url ,视图文件( templateUrl )和控制器。 form 将会作为主状态,它可以通过 . 表示的子状态,例如 在 form.profile 中的 . 。这背后的想法是,每个嵌套状态将被纳入主表单视图( main form view ),作为应用程序改变的状态。我们会在下一个章节证明这一点。我们现在要为表单和它的每一个嵌套状态创建视图。

表单模板视图 ( form.html )

让我们开始创建 form.html 文件。它将会被作为剩下的表单视图文件的模板文件,就像 index.html 被用作整个工程的总模板一样。所有我们需要做的是将 ui-view 包含在这个文件中,使嵌套状态知道从哪里注入它们的视图。

<!-- form.html -->
<div class="row">
<div class="col-sm-8 col-sm-offset-2">

    <div id="form-container">

        <div class="page-header text-center">
            <h2>Let's Be Friends</h2>

            <!-- the links to our nested states using relative paths -->
            <!-- add the active class if the state matches our ui-sref -->
            <div id="status-buttons" class="text-center">
                <a ui-sref-active="active" ui-sref=".profile"><span>1</span> Profile</a>
                <a ui-sref-active="active" ui-sref=".interests"><span>2</span> Interests</a>
                <a ui-sref-active="active" ui-sref=".payment"><span>3</span> Payment</a>
            </div>
        </div>

        <!-- use ng-submit to catch the form submission and use our Angular function -->
        <form id="signup-form" ng-submit="processForm()">

            <!-- our nested state views will be injected here -->
            <div id="form-views" ui-view></div>
        </form>

    </div>

    <!-- show our formData as it is being typed -->
    <pre>
        {{ formData }}
    </pre>


</div>
</div>

注意,这是我们第二次在工程中使用 ui-view 了,这也正是 UI Router 为何如此强大;允许嵌套状态和视图。这为我们创建应用提供了很大的灵活性。更多关于 UI Router 视图的信息,可以查阅它的官方文档。添加基于状态 Active 类,我们希望每一个状态按钮在它是活动的时候能够显示出来。为了做到这一点,我们使用 UI Router 提供的 ui-sref-active 的指令。当 ui-sref 匹配当前的状态时,这样就会添加我们指定的类。为你的表单添加校验,你可以阅读 AngularJS Form Validation 这时候,你可能想知道我们表单是看起来是什么样子,让我们进入浏览器来看一看!

qq 20150710172909

到达这里,不是所有的事情都是我们希望的那样,但是已经有伟大的事情开始了。让我们继续推进,添加一些样式,然后再添加嵌套视图和动画。

基本的样式 (style.css)

为了得到一个好看的表单,我们设置 form-container 和 status-buttons 样式。

/* style.css */
/* BASIC STYLINGS
============================================================================= */
body                            { padding-top:20px; }

/* form styling */
#form-container                { background:#2f2f2f; margin-bottom:20px;
    border-radius:5px; }
#form-container .page-header   { background:#151515; margin:0; padding:30px; 
    border-top-left-radius:5px; border-top-right-radius:5px; }

/* numbered buttons */
#status-buttons                 {  }
#status-buttons a               { color:#FFF; display:inline-block; font-size:12px; margin-right:10px; text-align:center; text-transform:uppercase; }
#status-buttons a:hover         { text-decoration:none; }

/* we will style the span as the circled number */
#status-buttons span            { background:#080808; display:block; height:30px; margin:0 auto 10px; padding-top:5px; width:30px; 
    border-radius:50%; }

/* active buttons turn light green-blue*/
#status-buttons a.active span   { background:#00BC8C; }

现在,按钮看起来好看多了,让我们继续嵌套视图(nested views)。

嵌套表单视图 form-profile.html, form-interests.html, form-payment.html

这会是容易的部分。我们定义不同的带有输入框的视图。我们把它们和 formData 对象绑定,使我们可以看到表单中输入的数据。这里有我们的视图文件:

Form Profile View

<!-- form-profile.html -->
<div class="form-group">
    <label for="name">Name</label>
    <input type="text" class="form-control" name="name" ng-model="formData.name">
</div>

<div class="form-group">
    <label for="email">Email</label>
    <input type="text" class="form-control" name="email" ng-model="formData.email">
</div>

<div class="form-group row">
<div class="col-xs-6 col-xs-offset-3">
    <a ui-sref="form.interests" class="btn btn-block btn-info">
    Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span>
    </a>
</div>
</div>

Form Interests View

<!-- form-interests.html -->
<label>What's Your Console of Choice?</label>
<div class="form-group">
    <div class="radio">
        <label>
           <input type="radio" ng-model="formData.type" value="xbox" checked>
           I like XBOX
        </label>
    </div>
    <div class="radio">
        <label>
            <input type="radio" ng-model="formData.type" value="ps">
            I like PS4
        </label>
    </div>
</div>

<div class="form-group row">
<div class="col-xs-6 col-xs-offset-3">
    <a ui-sref="form.payment" class="btn btn-block btn-info">
    Next Section <span class="glyphicon glyphicon-circle-arrow-right"></span>
    </a>
</div>
</div>

Form Payment View

<!-- form-payment.html -->
<div class="text-center">
    <span class="glyphicon glyphicon-heart"></span>
    <h3>Thanks For Your Money!</h3>

    <button type="submit" class="btn btn-danger">Submit</button>
</div>

那么现在,我们拥有三个定义好的视图,当我们查看表单时,它们会被展示。我们也使用 next button 和 ui-sref 连接到每个新状态。

当使用 ui-sref 时,你想连接已经在路由中定义过的状态,而不是 URL。Angular 会使用 ui-sref 为你创建 href 。

qq 20150710172647

为 form 添加动画

从一开始,ngAnimate 就已经进入到我们的工程,当我们改变状态,已经添加用于动画的类。它会自动添加类 ng-enter 和 ng-leave 用于 view 显示和消失。现在我们所要做的就是设置那些样式,我们有我们的完成表单!要理解 Angular 动画,这篇文章是一个很好的起点。让我们进入 CSS 文件,添加动画,并把它们应用到我们的表单。

/* style.css */
/* ANIMATION STYLINGS
============================================================================= */
#signup-form            { position:relative; min-height:300px; overflow:hidden; padding:30px; }
#form-views             { width:auto; }

/* basic styling for entering and leaving */
/* left and right added to ensure full width */
#form-views.ng-enter,
#form-views.ng-leave      { position:absolute; left:30px; right:30px;
    transition:0.5s all ease; -moz-transition:0.5s all ease; -webkit-transition:0.5s all ease; 
}

/* enter animation */
#form-views.ng-enter            { 
    -webkit-animation:slideInRight 0.5s both ease;
    -moz-animation:slideInRight 0.5s both ease;
    animation:slideInRight 0.5s both ease; 
}

/* leave animation */
#form-views.ng-leave            { 
    -webkit-animation:slideOutLeft 0.5s both ease;
    -moz-animation:slideOutLeft 0.5s both ease;
    animation:slideOutLeft 0.5s both ease;   
}

/* ANIMATIONS
============================================================================= */
/* slide out to the left */
@keyframes slideOutLeft {
    to      { transform: translateX(-200%); }
}
@-moz-keyframes slideOutLeft {  
    to      { -moz-transform: translateX(-200%); }
}
@-webkit-keyframes slideOutLeft {
    to      { -webkit-transform: translateX(-200%); }
}

/* slide in from the right */
@keyframes slideInRight {
    from    { transform:translateX(200%); }
    to      { transform: translateX(0); }
}
@-moz-keyframes slideInRight {
    from    { -moz-transform:translateX(200%); }
    to      { -moz-transform: translateX(0); }
}
@-webkit-keyframes slideInRight {
    from    { -webkit-transform:translateX(200%); }
    to      { -webkit-transform: translateX(0); }
}

首先,我们设置表单样式,当一个新的视图离开或进入的时候,它们是绝对定位的。这样可以确保当进入的时候,一个视图不会推挤其他视图。其次,我们在 .ng-enter 和 .ng-leave 类里应用动画。再次,我们使用 @Keyframes 定义动画。随着所有部分一起工作起来,我们全部表单都具有了 Angular 动画。UI Router based states, and Angular data-binding.

结论

UI-Router,ngAnimate,和所有在 Angular 中有趣的东西能走到一起去创造伟大的应用。希望这篇文章向您展示如何制作一个多步骤的表单,并使用多种 Angular 的技术和工具来构建它。这些概念已经被应用到许多其他的用户界面。感谢您的阅读,大胆的说出你建议和提出问题。

演示:http://embed.plnkr.co/M03tYgtfqNH09U4x5pHC/preview
代码:http://plnkr.co/edit/M03tYgtfqNH09U4x5pHC?p=preview

2015-5-20 YouTube精彩Angular视频 Reusable Components in Angular

Reusable Components in Angular

  • Multi-transclude
  • Attribute passing
  • Sub-directives

视频: https://www.youtube.com/watch?v=dF_ObGgzGE8
Slides: https://docs.google.com/presentation/d/1ozBlL1MXxyYPSLzIaMtHO1YF-tHkEzKFsvt4s3rBBt0/pub#slide=id.g57f904f61_80

Multi-transclude Example

看这个例子前需要注意几个点

Fat Arrow(箭头函数)有几个使用注意点。
函数体内的this对象,绑定定义时所在的对象,而不是使用时所在的对象。
不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
不可以使用arguments对象,该对象在函数体内不存在。

  • 自定义transclude函数
    • transclude function
    • Two parameters:
      • scope (optional)
      • callback function
        • passes clone
  • transclude函数执行时机 (注意指令的生命周期,你可以参看Slides P99
  • link
  • controller
  • compile
  • 它们之间的对比

HTML

   <ot-site>
        <div transclude-to="site-header">
            I am transcluding the header
        </div>
        <div transclude-to="site-menu">
            I am transcluding the menu
        </div>
        <div transclude-to="site-body">
            I am transcluding the body
        </div>
   </ot-site>

JavaScript

    // Use ES6 new feature
    // ng-transclude can not implement the result that we want. 
    /*$transclude(function(clone){
        $element.empty();
        $element.append(clone);
    });*/
    /**
    * test Module
    *
    * Description
    */
    /*angular.module('test', []).directive('otSite', () => {
        // Runs during compile
        return {
            scope: {},
            restrict: 'E', // E = Element, A = Attribute, C = Class, M = Comment
            template: `
                <div class="row">
                    <header class="header" ng-transclude></header>
                    <nav class="menu" ng-transclude></nav>
                    <main class="body" ng-transclude></main>
                    <footer class="footer"></footer>
                </div>
            `,
            replace: true,
            transclude: true,
            link: function($scope, iElm, iAttrs, controller) {

            }
        };
    });*/

    //Custom transclude
    //1.Get target ID
    //2.Find target element by ID
    //3.Append clone element to target 

   /* 
    transclude function
       Two parameters:
       scope (optional)
          callback function
               passes clone

    */

    /*
    Transclude function access point
    compile
    controller 
    link
    */

    angular.module('test', []).factory('MultiTransclude', () => {
        return {
            transclude: (iElm, transcludeFn) => {
                transcludeFn((clone) => {
                    angular.forEach(clone, (cloneEl) => {
                        if(cloneEl.attributes) {
                            var tId = cloneEl.attributes["transclude-to"].value;
                            var target = iElm.find(`[transclude-id="${tId}"]`);

                            if(target.length) {
                                target.append(cloneEl);
                            } else {
                                cloneEl.remove();
                                throw new Error(`
                                    Target not found, Please specify 
                                           the correct transclude-to Attribute
                                `);
                            }
                        }
                    });
                });
            }
        };
    })
    .directive('otSite', ['MultiTransclude', (MultiTransclude) => {
        // Runs during compile
        return {
            scope: {},
            restrict: 'E', // E = Element, A = Attribute, C = Class, M = Comment
            template: `
                <div class="row">
                    <header class="header" transclude-id="site-header"></header>
                    <nav class="menu" transclude-id="site-menu"></nav>
                    <main class="body" transclude-id="site-body"></main>
                    <footer class="footer"></footer>
                </div>
            `,
            transclude: true,
            link: function($scope, iElm, iAttrs, controller, transclude) {
               MultiTransclude.transclude(iElm, transclude);
            }
        };
    }]);

2014-11-25 Sublime Text入门和JQuery Mobile入门

Sublime text使用

Package Control 安装方法

  • 按Ctrl+`调出console
  • 粘贴以下代码到底部命令行并回车:
  • 重启Sublime Text 3。
  • 如果在Perferences->package settings中看到package control这一项,则安装成功。
import urllib.request,os; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); open(os.path.join(ipp, pf), 'wb').write(urllib.request.urlopen( 'http://sublime.wbond.net/' + pf.replace(' ','%20')).read())

Sublime Text2的命令

import urllib2,os; pf='Package Control.sublime-package'; ipp = sublime.installed_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None; urllib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler( ))); open( os.path.join( ipp, pf), 'wb' ).write( urllib2.urlopen( 'http://sublime.wbond.net/' +pf.replace( ' ','%20' )).read()); print( 'Please restart Sublime Text to finish installation')

用Package Control安装插件的方法:

  • 按下Ctrl+Shift+P调出命令面板
  • 输入install 调出 Install Package 选项并回车,然后在列表中选中要安装的插件。

为Package Control 添加代理

将以下代码加入到Preferences >> Package Settings >> Package Control >> Settings – User 中:

// Proxy Settings
"http_proxy": "your.proxy.fqdn:80",
"https_proxy": "your.proxy.fqdn:80",
"proxy_username": "my_username",
"proxy_password": "my_password",

插件推荐 Package Control

主题推荐

入门PPT

常用快捷键 传送门 MAC版的快捷键

快捷键 功能
Ctrl+L 选择整行(按住-继续选择下行)
Ctrl+KK 从光标处删除至行尾
Ctrl+Shift+K 删除整行
Ctrl+Shift+D 复制光标所在整行,插入在该行之前
Ctrl+J 合并行(已选择需要合并的多行时)
Ctrl+KU 改为大写
Ctrl+KL 改为小写
Ctrl+D 选词(按住-继续选择下个相同的字符串)
Ctrl+M 光标移动至括号内开始或结束的位置
Ctrl+Shift+M 选择括号内的内容(按住-继续选择父括号)
Ctrl+/ 注释整行(如已选择内容,同“Ctrl+Shift+/”效果)
Ctrl+Shift+/ 注释已选择内容
Ctrl+Space 自动完成(win与系统快捷键冲突,需修改)
Ctrl+Z 撤销
Ctrl+Y 恢复撤销
Ctrl+Shift+V 粘贴并自动缩进(其它兄弟写的,实测win系统自动缩进无效)
Ctrl+M 光标跳至对应的括号
Alt+. 闭合当前标签
Ctrl+Shift+A 选择光标位置父标签对儿
Ctrl+Shift+[ 折叠代码
Ctrl+Shift+] 展开代码
Ctrl+KT 折叠属性
Ctrl+K0 展开所有
Ctrl+U 软撤销
Ctrl+T 词互换
Ctrl+Enter 插入行后
Ctrl+Shift+Enter 插入行前
Ctrl+K+Backspace 从光标处删除至行首
Ctrl+Shift+UP 与上行互换
Ctrl+Shift+DOWN 与下行互换
Shift+Tab 去除缩进
Tab 缩进
F9 行排序(按a-z)

视频教程

Sublime Text 全程指南

相关文章

2015-8-3 AngularJS 常见问题集锦

(function() {
    'use strict';

    angular
        .module('app.common')
        .factory('file', factory);

    factory.$inject = ['$http', '$q'];

    /* @ngInject */
    function factory($http, $q) {
        var service = {
            getFiles: getFiles
        };
        return service;

        ////////////////
        function getFiles(files) {
          var promises = files.map(function(file) {
             return $http.get(file);
          });
          return $q.all(promises);
        }
    }
})();
    app.config()
    app.run()
    directive’s compile functions (if they are found in the dom)
    app.controller()
    directive’s link functions (again if found)
angular.module('app').config(function($provide) {
    $provide.decorator("$exceptionHandler", ['$delegate', function($delegate) {
        return function(exception, cause) {
            $delegate(exception, cause);
            alert(exception.message);
        };
    }]);
});

2015-3-13 Angular的Table 组件

Angular的Table 组件

  1. UI Grid (ng-grid)
    官方网址: http://ui-grid.info/
    github: https://github.com/angular-ui/ng-grid
    Example: http://ui-grid.info/docs/#/tutorial/401_AllFeatures
    该组件属于大名鼎鼎的angular-ui项目, 功能强大,除了常见的一些基本功能外,还加入了一些高级功能:

    Standard Features
    - Sorting
    - Filtering
    - User interaction

    Advanced Features
    - Virtualization
    - Column pinning
    - Grouping
    - Edit in place
    - Expandable rows
    - Internationalisation

    推荐指数 4颗星

  2. ng-table
    官方网址: http://bazalt-cms.com/ng-table/
    github: https://github.com/esvit/ng-table
    Example: http://bazalt-cms.com/ng-table/example/23

    一个简单不错的Angular table组件,轻松满足你的基本功能,github上有1300多个star和400多个fork,说明它还是蛮流行的嘛!
    推荐指数 4颗星

  3. smart table
    官方网址: http://lorenzofox3.github.io/smart-table-website/
    github: https://github.com/lorenzofox3/Smart-Table
    Example: http://lorenzofox3.github.io/smart-table-website/#examples-section

    Smart Table也算是一个不错选择,相比其他,它轻量,支持插件,易于扩展。

    推荐指数 4颗星

  4. Angular-Datatables
    官方网址: http://l-lin.github.io/angular-datatables/
    github: https://github.com/l-lin/angular-datatables
    Example:http://l-lin.github.io/angular-datatables/#/zeroConfig

    Angular-Datatables是将jquery datatables 通过angular的方式封 装成指令,所以它具备jquery datatables的特点,功能强大,API不太好用

    推荐指数 3颗星

  5. tablelite
    官方网址:http://adaptv.github.io/adapt-strap/##tablelite
    github:https://github.com/Adaptv/adapt-strap
    Example: http://adaptv.github.io/adapt-strap/##tablelite

    tablelite是作为adapt-strap项目的一部分,建议如果你的项目需要用到bootstrap的时候再去使用它。

    推荐指数 3颗星

  6. kendo-ui中的grid
    官方网站: http://www.telerik.com/kendo-ui
    github: https://github.com/kendo-labs/angular-kendo
    Example: http://kendo-labs.github.io/angular-kendo/

    kendo UI是一套完整的UI解决方案,它支持Angular化,它的grid功能异常强大,如果你不缺钱的话,它将是一个不错的选择。

    推荐指数 3颗星

  7. 自己实现
    如果你的grid只是简单排序,分页和过滤的话,我的建议是自己实现或者选择smart-table,一个例子http://codepen.io/bryanschoeff/pen/cuBvd/

有兴趣试试

推荐指数 5颗星

其他资料: http://stackoverflow.com/questions/21375073/best-way-to-represent-a-grid-or-table-in-angularjs-with-bootstrap-3

2015-4-14 angular实现ng-repeat递归

AngularJS recursive templates

http://benfoster.io/blog/angularjs-recursive-templates
http://www.cnblogs.com/kuangliu/p/4146705.html

工作中我们经常要遍历多层数据,如果数据是已知层级的话,用 ng-repeat 就搞定了,要是数据深度是无限的呢,或者我们要实现一个无限层级的 tree 的时候,该怎么办?
答案是使用 ng-include 指令递归模板

Example

HTML

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link href="../../vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet"/>
    <link href="../../vendor/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet"/>
</head>
<body ng-app>
   <div ng-controller="treeController" class="container">
       <div class="row">
           <h2>ng-repeat recursive list example</h2>
           <ul>
               <li ng-repeat="item in tree" ng-include="'treeItem'"></li>
           </ul>
       </div>
   </div>

    <script src="../../vendor/angularjs/angularjs.js"></script>
    <script src="treeList.js"></script>
    <script type="text/ng-template" id="treeItem">
        {{item.id}} --- {{item.name}}
        <ul ng-if="item.children">
           <li ng-repeat="item in item.children" ng-include="'treeItem'">
           </li>
       </ul>
    </script>
</body>
</html>

treeList.js

/**
 * Created by hjzheng on 2014/10/27.
 */
var treeController = function ($scope) {
    $scope.tree = [
        { id: 1, name: 'John', score: 130, city: 'New York', birthday: '1980/2/5',
            children:[
                { id: 6, name: 'John2', score: 82, city: 'San Fran1', birthday: '1990/1/21'},
                { id: 7, name: 'John2', score: 81, city: 'San Fran2', birthday: '1990/1/22',
                    children:[{ id: 8, name: 'John3', score: 89, 
                                               city: 'San Francisco', birthday: '1990/1/21'}]
                }
            ]
        },
        { id: 2, name: 'Alice', score: 123, city: 'Washington', birthday: '1984/3/7'},
        { id: 3, name: 'Lee', score: 149, city: 'Shanghai', birthday: '1986/10/8'},
        { id: 4, name: 'Mike', score: 100, city: 'London', birthday: '1988/8/12'},
        { id: 5, name: 'Tom', score: 89, city: 'San Francisco', birthday: '1990/1/21',
            children: [
               { id: 9, name: 'Tom1', score: 77, city: 'San Francisco', birthday: '1990/1/21'},
               { id: 10, name: 'Tom2', score: 85, city: 'San Francisco', birthday: '1990/1/21'},
               { id: 11, name: 'Tom3', score: 83, city: 'San Francisco', birthday: '1990/1/21'}
            ]
        }
    ];
}

Angular Tree Grid(自己实现)

通过Angular自定义Filter,实现复杂Tree数据遍历(复杂数据参见上面的例子)和过滤(对expend数据过滤)
Example:
http://jsfiddle.net/hjzheng/78jz0mrL/ (翻墙)

2015-8-21 Angular Debug 小技巧

Angular Debug 小技巧

下面是对文章Tips & Tricks for debugging unfamiliar AngularJS code的摘抄

查看元素的 scope

  • 打开 chrome dev tools(使用F12)。
  • 用 Inspect 工具,在页面上选择一个元素。
  • 在控制台内,用 $($0) 取得该元素,如果没有导入 JQuery,则用 angular.element($0)
  • $($0).scope() 返回该元素上的 scope ,可以检查该 scope 中属性。
  • 如果属性继承自父 scope,该属性不会在当前 scope 中显示。
  • 你可以通过 $($0).scope().$parent 查看父 scope , 你也可以通过 $($0).scope().$parent.$parent 依次往上查看。
  • 你可以查看 root scope : $($0).scope().$root
  • 如果你 Inspect 一个指令,可以通过 $($0).isolateScope() 查看它的隔离 scope。
  • 如果你 Inspect 指令中的一个带隔离 scope 的元素,你也可以用 $($0).scope() 方法。

screenshot_072615_115503_am

scope 中的属性来自于哪里

  • 例如你要查找一个属性 foo , 你可以使用 $($0).scope().foo
  • 如果该属性被定义,说明该属性存在。
  • 不存在的话,你继续向上寻找,直到找到为止。
  • 但是这样依然无法确定属性在哪里?因为 scope 之间存在继承关系,子 scope 可以访问 父 scope 中的变量。
  • 你需要通过 $($0).scope().hasOwnProperty('foo') 确定属性 foo 是否在当前 scope。
  • 如果返回 false ,继续向上查找 $($0).parent().scope().hasOwnProperty('foo') 直达找到为止。

screenshot_072615_122143_pm

当前元素属于哪个 controller

  • $($0).closest('[ng-controller]').attr('ng-controller')

screenshot_072615_122619_pm

如何让修改过的属性值生效

  • $($0).scope().isFoo = true 设置 isFoo 属性为 true。
  • $($0).scope().$digest() 迫使 Angular 改变该值。
  • 页面 Dom 会发生相应的变化。

angulardigest

2015-10-13 OSX初体验

背景

公司突然大发慈悲,为我们这帮屌丝更换电脑,用来三年的 ThinkPad T420 终于可以退休啦!公司为我们提供两种选择,继续ThinkPad系列,或者MAC系列,作为前端工程师我,当然选择MAC啦!新电脑发下来后,各种兴奋,为了不耽误工作,先找了个入门视频快速学习和了解OSX这个系统。传送门-入门视频youtube

入门篇

熟悉各种手势操作

MAC具有一个灵活和强大的触控板,为了提供我们的工作效率,你首先必须可以熟悉和灵活使用它。
系统偏好设置->触控板 里面有具体功能介绍和动画演示,当然如果你不差钱的话,可以买一个Magic Mouse,它的设置在系统偏好设置->鼠标

熟悉MAC的键盘符号和其快捷键

为了进一步的提高效率,你需要熟悉常用的快捷键,而这些快捷键是由键盘符号组成的。
键盘符号传送门
mac-key-icon
常用快捷键
cmd + 空格 切换输入法
cmd + q 退出, cmd + ctrl + f 全频/退出全屏
cmd + c 拷贝, cmd + v 黏贴
cmd + c 拷贝, cmd + option + v 移动
cmd + shift + 3 截图-全屏, cmd + shift + 4 截图-区域
cmd + w 关闭,cmd + h 隐藏,cmd + q 退出程序
cmd + tab 切换任务
option + command + esc 强制退出任务,类似windows任务管理器的结束任务功能
更多快捷键
安装软件 CheatSheet,长按 command 键,就可以查看当前所有可以使用的快捷键

自定义快捷键和手势
当然也可以自定义快捷键和手势,推荐两款软件

更多内容可以参考文章干掉鼠标!用这 4 款 App 大幅提升 Mac 键盘效率

软件安装和卸载

  • 安装应用,安装好后移入APP,退出桌面磁盘镜像。
  • 删除应用,拖到废纸篓里就行。
  • 当然你也可以通过App Store安装应用和卸载应用

Finder和Spotlight的使用

这个可以观看背景中分享的视频。

熟悉终端的使用

其实就是熟悉Shell命令行,因为之前使用过Linux,这个就不再详细说了。

开发篇

Homebrew

OS X 不可或缺的套件管理器

  •  安装
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 使用
$ brew install wget

如果你想使用图形界面,那么推荐Cakebrew给你

Git

可以参考github官网上关于MAC上安装git的教程 传送门,当然也可以使用 brew 安装

$ brew install git

NodeJS

作为前端开发过程中必不可少的部分,无论是构建工具 gulp,还是包管理工具 bower 都是基于 Node 的。

你可以使用 brew 进行安装。

$ brew install node

Sublime Text 3

这是我目前用过最好的前端编辑器之一,更多内容,请点击这里。传送门 Sublime Text入门

iTerm 2

刚开始使用该软件,以后熟悉后会继续更新,先来一篇新手入门
iTerm2新手应知特色功能介绍

关于使用iTerm2使用profile实现自动ssh登录和telnet认证的方法,这里就不详细说了,将两个自动化脚本分享出来:
telnet.exp
login.exp

在分屏状态下,使用 cmd + [cmd + ] 进行分屏切换

Dash

有了Dash,妈妈在也不用担心我查找API了,所有你能想到的API文档,都可以有,不信,我们可以试试!

RescueTime

RescueTime会记录你在电脑的时间都用在哪里了,然后你可以根据时间统计结果,进行调整,提高自己的工作效率。

WebStorm

另一个前端编辑神器:
简单的快捷键整理

修改键(基于Mac OS X 10.5 +)
command + 0 打开终端

默认快捷键
command + 1 打开Projects
command + 2 打开最喜爱,我用来从终端跳回编辑区

在终端中
command + T 新建 终端tab
command + w 关闭 终端tab

在编辑区
shift + command + [ / ] 切换tab
command + D 重复当前行
shift + command + 上 / 下 整行上下移动
command + -> 行尾
command + <- 行首
command + L 跳到第几行
command + Z 撤销
command + shift + Z 重做
command + delete 删除整行
shift + 方向键 选中区域
option + 方向键 按单词移动光标

ctrl + tab 快速导航

你需要知道的webstorm快捷键

XMind

最受欢迎思维导图软件,全力打造易用、美观、高效的可视化思维管理工具。

未完待续 ... ...

2014-10-21 HTML5 Slides (下) | Learn much javascript from one line of code | Javascript的诞生和死亡

HTML5 Slides (下)

Graphics / Multimedia

  • Audio + Video
  • FullScreen API
  • Canvas 2D
  • Canvas 3D (WebGL)
  • Inline SVG

CSS3

  • New CSS Selector
  • Webfonts
  • Text wrapping
  • Columns
  • Text stroke
  • Hue/saturation/luminance color
  • Rounded corners
  • Gradients
  • Shadows
  • Background enhancements
  • Border image
  • Flexible Box Model
  • Transitions
  • Transforms
  • Animations

Nuts & Bolts

  • New Selectors
  • Custom data-* attributes
  • Element.classList
  • History API

Learn much javascript from one line of code

代码: 为页面所有元素添加1像素outline

[].forEach.call($$("*"),function(a){
  a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16)
})

你可以在console中运行该code查看效果

分析代码

  • $$("*");
  • [].forEach.call()
  • (~~(Math.random()*(1<<24))).toString(16)

$$("") 这个来自command_line_API,类似的还有$和$x, 该方法类似于document.querySelectorAll('')

上述方法得到是nodeList对象,是一个array-like对象,它不是一个数组,没有数组的方法, 所以使用数组的call方法,借用数组的forEach方法, [].forEach.call()

给所有元素加outline,如何取得颜色值?
1<<24 向左位移

1<<0 //2^0
1<<1 //2^1
1<<2 //2^2
1<<3 //2^3

Math.random()*(1<<24)取得0到2^24(FFFFFF)的随机数字.

~~ 取整数,类似于parseInt ~按位取反, 更多信息

var a = 12.34, // ~~a = 12
    b = -1231.8754, // ~~b = -1231
    c = 3213.000001; // ~~c = 3213

~~a == parseInt(a, 10); // true
~~b == parseInt(b, 10); // true
~~c == parseInt(c, 10); // true

toString(16) 转换成16进制

(30).toString(); // "30"
(30).toString(10); // "30"
(30).toString(16); // "1e" Hexadecimal
(30).toString(2); // "11110" Binary
(30).toString(36); // "u" 36 is the maximum base allowed

JavaScript诞生和死亡 <视频>

2014-9-2 XSS 前端防火墙 | Fiddler的使用 | Chrome Dev Tools使用2

XSS 前端防火墙 (Zhen Ou Yun)

关于 XSS 怎样形成、如何注入、能做什么、如何防范,前人已有无数的探讨,这里就不再累述了。
几乎每篇谈论 XSS 的文章,结尾多少都会提到如何防止,然而大多万变不离其宗。要转义什么,要过滤什么,不要忘了什么之类的。尽管都是众所周知的道理,但 XSS 漏洞十几年来几乎从未中断过,不乏一些大网站也时常爆出,小网站更是家常便饭。
而本文介绍的则是另一种预防思路 —— 通过前端监控脚本,让每一个用户都参与漏洞的监控和上报。

原文地址: http://fex.baidu.com/blog/2014/06/xss-frontend-firewall-1/

Fiddler (Hao Ju Zheng)

使用Fiddler提高工作效率

什么是Fiddler?
Fiddler是最强大最好用的Web调试工具之一,它能记录所有客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据. 使用Fiddler无论对Dev还是QA来说,都有很大的帮助。(千万不要告诉QA,要不然Dev会死的很惨,开个玩笑)

Fiddler官网
Fiddler原理
说白了, Fiddler就是夹在客户端和服务器端的一个代理, 劫持http请求和返回,从而达到双向欺骗效果

Dev常用功能:
Fiddler中设置断点修改Request请求参数

  • 在Fiddler命令行中执行
bpu  http://9.111.244.79:8080/xxxxx/j_spring_security_check
  • 重新登录HPC, 你会发现该请求被劫持,然后在Inspectors中修改登录的用户名和密码
  • 可以使用下面命令取消断点
bpu

Fiddler中设置断点修改Response返回

  • 在Fiddler命令行中执行
bpafter http://9.111.244.79:8080/xxxxx/xxx/networks/getNetworkSummary.action
  • 在该页面重新执行该请求,在raw中修改JSON数据,以达到自己的目的
  • 可以使用下面命令取消断点
bpafter

Fiddler中创建AutoResponder规则
这个功能类似于chrome dev tools的workspace功能,只不过它不仅可以替换js文件,也可以替换任何http请求的返回。
在AutoResponder中建立相应的规则即可,即可替换文件,又可以模拟404,500等服务器返回状态。

用Fiddler修改User-Agents

扩展阅读:

Chrome Dev Tools使用2 (Hao Ju Zheng)

接上次前端开发工具介绍,继续对Chrome Dev Tools进行介绍

  • async call stack(异步调用)
  • console API
  • command line API

2015-6-2 使用$provide.decorator方法去扩展angular现有指令

使用$provide.decorator方法去扩展angular现有指令

angular.config(['$provide', function ($provide){
    $provide.decorator('accordionGroupDirective', function($delegate) { 
          var directive = $delegate[0];
          directive.templateUrl = "views/parts/accordion-unit.html";
          angular.extend(directive.scope, { index:'@' });
          return $delegate;
    });
}]);

几个切入点

  • 扩展scope参数
  • 替换模板
  • 扩展或替换controller
  • 扩展link或compile
扩展scope参数

使用angular.extend方法合并scope对象,该方式在1.2.x下是好的,到了1.3就不work了,不过有workaround方法,就是直接向directive.$$isolateBindings对象里面push你的参数,可以参看下面的例子

$provide.decorator('alertDirective', function($delegate) {
     var directive = $delegate[0];    
     //works on 1.2 
     /*angular.extend(directive.scope, {
         apply: '&',
         discard: '&'
     });*/

     //1.3.x bug: https://github.com/angular/angular.js/issues/10149
     directive.$$isolateBindings.apply = {
       attrName: 'apply',
       mode: '&',
       optional: true
     };

     directive.$$isolateBindings.discard = {
       attrName: 'discard',
       mode: '&',
       optional: true
     };

     ... ...

     return $delegate;
 });
替换模板

直接对directive对象的templateUrl或tenmplate属性直接赋上你的模板:

directive.templateUrl = "views/parts/accordion-unit.html";
directive.template = "<div>Just Test</div>";
扩展或替换controller

扩展或替换 controller 或者 link 方法:
替换是直接附上新的函数即可
扩展是使用JavaScript函数进行继承,将要扩展函数的this上的属性和方法,全部继承过来。具体可以参看gist, 具体还没实践,但是理论上肯定是可以的.

另一种扩展controller的方法,使用$controller,测试后有些问题(会丢失一些方法),大家可以研究一下(来自参考资料的方法)

app.config(function($provide) {
  $provide.decorator('fooDirective', function($delegate, $controller) {
    var directive = $delegate[0];

    var controllerName = directive.controller;
    directive.controller = function($scope, $timeout) {
      angular.extend(this, $controller(controllerName, {$scope: $scope}));

      $timeout(function() {
        $scope.name = "from the decorator now";
      }, 3000);
    };

    return $delegate;
  });
});

扩展link或compile (来自参考资料的方法)

备份link函数对其进行扩展

app.config(function($provide) {
  $provide.decorator('fooDirective', function($delegate) {
    var directive = $delegate[0];

    directive.scope.fn = "&";
    //backup old link method 备份旧的link
    var link = directive.link;

   //extend compile 扩展compile
    directive.compile = function() {
      return function(scope, element, attrs) {
        link.apply(this, arguments);
        element.bind('click', function() {
          scope.$apply(function() {
            scope.fn();
          });
        });
      };
    };

    return $delegate;
  });
});

备份旧的compile方法,执行,对返回的link方法进行扩展

app.config(function($provide) {
  $provide.decorator('fooDirective', function($delegate) {
    var directive = $delegate[0];

    var compile = directive.compile;

    directive.compile = function(tElement, tAttrs) {
      var link = compile.apply(this, arguments);
      tElement.append('<div>Added in the decorator</div>');
      return function(scope, elem, attrs) {
        link.apply(this, arguments);
        // We can extend the link function here
      };
    };

    return $delegate;
  });
});
Example

扩展Bootstrap-UI Alert Directive
扩展Bootstrap-UI Dropdown Directive

参考资料:
Experiment: Decorating Directives
AngularJS in Patterns (Part 2). Services.

2014-12-2 基于AngularJS的复杂业务系统的代码架构探索 | 关于Git使用

基于AngularJS的复杂业务系统的代码架构探索

在遇到任何一个复杂业务系统,在项目设计之初,应遵循的一些基本设计原则,最终使得项目具有良好的可扩展性和可维护。
最终,当需求发生变化的时候,可以做到从容应对。

视频

http://www.imooc.com/video/3979

关于Git使用

Git远程操作详解

http://www.ruanyifeng.com/blog/2014/06/git_remote.html
git_command

Git视频教程

http://www.imooc.com/learn/208

Git多人合作经验

  • 多用客户端和工具,少用命令行
  • 每次提交前,先diff自己的代码,在提交
  • 下班前,整理好自己的工作区
  • 并行项目使用分支开发,避免互相干扰
  • 遇到冲突,找到原因,不要随便丢弃别人代码
  • 产品发布之后,打一个tag
Git命令图解

git_command

2014-8-19 前端开发工具介绍

前端开发工具介绍 (工欲善其事必先利其器)

轻量级装备(手枪) Notepad ++ (参见北河的PPT)

  • 官方地址: http://notepad-plus-plus.org/
    • 使用方便,短小精悍。
    • 上可修改各种程序文件,下可修改各种配置文件。
    • 亦可临时处理文本数据。
    • 最新版本已经集成插件管理器
  • 优点
    • 开源免费
    • 配置简单
    • 编码功能强大
    • 小而快
  • 缺点
    • 仅支持windows
    • 快捷键功能较弱
    • 智能化程度低
  • 推荐插件
    • Emmet: emmt参考文档
    • TextFX: 强大的文本转换工具
    • Compare: 比较工具
    • JSLint: JS校验
    • Explorer: 文件浏览
    • JSTool: JS压缩和格式化
    • JSONViewer: 查看和格式化JSON数据

重量级装备(机枪) WebStorm (参见北河的PPT)

  • 官方地址:http://www.jetbrains.com/webstorm/
    • 为前端而生,仅仅支持html+js+css是不够的,nodejs,coffeescript,angular亦不在话下。
  • 优点
    • 跨平台
    • 为前端设计
    • N多默认配好的小功能
    • 高质量插件支持
  • 缺点
    • 收费
    • 配置项复杂
    • 无中文支持
  • 更多

贴身装备(砍刀) Chrome Dev tools

前端Code分享和记录利器(匕首)

  • 在学习前端知识时,时常需要记录和实践,这时候下面的实时展示code运行结果工具派上用场。
  • jsfiddlejsbin
  • 优点
    • 快速实践和记录知识
    • 易于修改和分享
    • 支持多种框架
  • 缺点
    • 无法离线工作
    • 不易进行大型项目

2014-12-16 ES6 Template String | 写给大家看的设计书

ES6 Template String

//Basic usage with an expression placeholder
var person = 'Hao Ju Zheng';
console.log(`Yo! My name is ${person}`);

//Expressions work just as well with object literals
var user = {name: 'Zhen Ou Yun'};
console.log(`Thanks, ${user.name}`);

//Expression interpolation, One use is readable inline math.
var a = 50;
var b = 100;
console.log(`The number of JS frameworks is ${a + b} and not ${ 2 * a +b }`);

//Multi-line strings without needing \n\
console.log(`string text line 1
string text line 2`);

//Function inside expressions
function fn() {return "result"}
console.log(`foo ${fn()} bar`);

浏览器支持情况

  • firefox34 及其以上版本
  • chrome 马上会支持

目前解决浏览器兼容方案

用途

  • 国际化
  • HTML模板
  • 多行文本

ES6 Features

ES6 Features兼容表

ES6 Template String PPT

2014-7-29: CSS Sprite | Image Data URL | Icon Font | 使用border制作三角形

  1. CSS Sprite
    这次为什么要说CSS精灵,并不是说大家不知道什么是CSS Sprite或如何使用CSS Sprite,而是在与美工或UX合作进行图片合并的时候,由于他们不知道我们的HTML结构,每次合成的图片无法满足我们的要求,导致效率低下,所以我们决定自己解决, 使用在线合成工具: spritepad

    注意:

    • 当图片大于或等于容器元素,直接紧凑的合成在一起。
    • 当图片小于容器元素:
      • 如果background-position左右横向放置,合成时,保证图片左右两边没有元素
      • 如果background-position上下垂直放置,合成时,保证图片上下两边没有元素。
  2. image data url
    这是一种只会在极端情况下,使用的技术,这种极端情况如下:

    • 项目临时增加一个图片,想快速部署
    • 图片大小非常小,且无需重用

    可以考虑该方法,减少图片,但是会增加CSS文件大小。

    如何使用

       .class {
           background: url(data:image/gif;base64,R0lGODl ... ) no-repeat left center;
       }

    注意
    在线将图片转换成data工具: encodeData

  3. icon font
    希望我们designer可以考虑使用icon font

    • 优点: 矢量图,可以像字体一样,修改颜色和大小,不用考虑background-position,且performance优于图片
    • 缺点: 只支持纯色

    关于更多icon font知识

  4. 使用border制作三角形

    • 优点: 减少图片,
    • 缺点: 多写一个html元素

    关于使用border制作三角形

2015-4-2 Angular file upload directive || JavaScript跨域总结

2015-3-23 angular-translate || angular controller as syntax

angular-translate

Getting Started

1.安装

bower install angular-translate
bower install angular-translate-loader-static-files

2.添加依赖

var app = angular.module('myApp', ['pascalprecht.translate']);

3.配置(这里加载本地资源文件)

$translateProvider.useStaticFilesLoader(
    files: [{
        prefix: 'locale-',
        suffix: '.json'
    }, {
        prefix: '/absolute/path/to/locale-',
        suffix: '.json'
    }, {
        prefix: 'another/path/to/locales/',
        suffix: ''
    }]
 );
$translateProvider.preferredLanguage('en');

4.资源文件

 // locale-en.json
 {
 "HEADLINE": "What an awesome module!",
 "PARAGRAPH": "Srsly!",
 "PASSED_AS_TEXT": "Hey there! I'm passed as text value!",
 "PASSED_AS_ATTRIBUTE": "I'm passed as attribute value, cool ha?",
 "PASSED_AS_INTERPOLATION": "Beginners! I'm interpolated!",
 "VARIABLE_REPLACEMENT": "Hi {{name}}",
 "BUTTON_LANG_DE": "german",
 "BUTTON_LANG_EN": "english"
 }

 // locale-de.json
 {
 "HEADLINE": "Was für ein großartiges Modul!",
 "PARAGRAPH": "Ernsthaft!",
 "PASSED_AS_TEXT": "Hey! Ich wurde als text übergeben!",
 "PASSED_AS_ATTRIBUTE": "Ich wurde als Attribut übergeben, cool oder?",
 "PASSED_AS_INTERPOLATION": "Anfänger! Ich bin interpoliert!",
 "VARIABLE_REPLACEMENT": "Hi {{name}}",
 "BUTTON_LANG_DE": "deutsch",
 "BUTTON_LANG_EN": "englisch"
 }

5.使用

6.Example

7.常用方法

//config translate to load static file
test.config(function($translateProvider){
    $translateProvider.useStaticFilesLoader({
        files: [{
          prefix: './i18n/locale-',
          suffix: '.json'
         }]
    });
    $translateProvider.registerAvailableLanguageKeys(['en', 'zh'], {
       'en_US': 'en',
       'en_UK': 'en',
       'zh_CN': 'zh'
    }); 
    //set preferred lang
    //$translateProvider.preferredLanguage('en');
    //auto determine preferred lang
    $translateProvider.determinePreferredLanguage();
    //when can not determine lang, choose en lang.
    $translateProvider.fallbackLanguage('en');
});

2014-10-28 书写高效的CSS

书写高效的CSS

浏览器样式匹配规则

  • 关键选择器
  • 从右往左

关键选择器

选择器的最后面的部分即为关键选择器(即用来匹配目标元素的那部分,而不是该元素的父辈元素)

 #header, a img, h1 + [title] {
    ... ...
 }
 //关键选择器分别为 #header, img, [title]

拆分样式

为了提高样式匹配效率,浏览器根据关键选择器将样式拆分为四种类型,放置到4张不同的哈希表里:

  • ID规则
  • Class规则
  • 标签规则
  • 通用规则(不符合上面的都是)

ID规则

这一类别包含了那些将 ID 选择器作为关键选择器的规则

button#backButton {…} /* This is an ID-categorized rule */
#urlBar[type="search"] {…} /* This is an ID-categorized rule */
table > tr > td#myCell:active {…} /*This is an ID-categorized rule*/

Class规则

如果一个规则将一个 class 作为它的关键选择器,那么它就属于该类别.

button.settingButton {…} /* A class-based rule */
.fancyText {…}    /* A class-based rule */
ul > .menu-left[checked="true"] {…} /* A class-based rule */                 

标签规则

如果既没有 class 也没有 ID 来作为关键选择器,那么接下来的候选者就是 标签 类别.如果一条规则将一个标签作为它的关键选择器,那么这条规则就属于该类别.

 table {…} /* A tag-based rule */
 ul > li {…} /* A tag-based rule */
 input[type="checkbox"] {…} /* A tag-based rule */

通用规则

不属于上面那些类别的规则都属于这个类别

   [hidden="true"] {…} /* A universal rule */
   * {…} /* A universal rule */
   ul > [title="hehe"] {…} /* A universal rule */

从右向左

浏览器读取你的选择器, 遵循的原则是从选择器的右边到左边读取. 先从关键选择器开始匹配规则, 然后左移, 匹配祖先, 成功, 持续左移, 直到和规则匹配, 或者是因为不匹配而放弃。 所以,对于一个给定的元素, 需要匹配的规则越少, 样式的解析就会越快.

高效CSS指南

  • 避免通用规则
  • 不要用标签名或 classes 来限制 ID 规则
  • 不要用标签名限制 class 规则
  • 尽量使用最具体的类别
  • 避免后代选择器
  • 属于标签类别的规则永远不要包含子选择器
  • 在使用子选择器的地方想想为什么
  • 依赖继承

如何测试 ?

Chrome30(不包含30)以下的版本包含有CSS selector profile可以对选择器进行性能测试

CSS样式分析

analyze-css

参考资料:

书写高效的CSS

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.