参加 D2 2015 技术论坛感想

上周末去杭州阿里巴巴西溪园区参加了 2015 年的 D2 论坛,正好是第十届。

我听了一天的主会场,并在知乎上实时直播: 参加第十届D2前端技术论坛,你有什么收获? – yuanyuanVivian 的答案 。在这里谈谈自己的心得感想吧!

NodeJs 开始绽放

主会场的几场分享都还算挺不错。其中 NodeJS 相关的两场分享,一个是 Tmall 的线上经验,一个是 QZone 的线上经验,都是耳熟能详的大网站。我认为这代表 NodeJs 的线上能力已经得到了足够的验证,可以加快推广了继续阅读参加 D2 2015 技术论坛感想

AngularJS 小技巧

AngularJS 开发过程中用得到的日常小技巧。

默认提交为 JSON 的问题

这是一个 AngularJS 专用补丁,确保 POST 提交的不是 JSON 而是正常的 payload。

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";

且 json 数据必须转换成 form 数据,详情请见 How can I post data as form data instead of a request payload?

(别的技巧待续,想听哪方面的技巧请留言)

AngularJS 父子 scope 之间的交流

本文是 《Parent/Child Controller Communication》 的译文。

======译文开始======

我最近经在教很多个朋友 AngularJS,而他们几乎都问了同样一个问题:

如何在 controller 之间传递消息(状态)?

这是个好问题。通常对初学者来说,它不直观。答案比我们想的要复杂(但实现起来很简单)。

有好多方法可以在 controller 之间通信 继续阅读AngularJS 父子 scope 之间的交流

跨浏览器的 Array.prototype.sort 的使用姿势

自定义比较函数时,因为 IE 下方法返回的值必须是 0 , -1 , 1 ,分别对应等于、第一个参数排在前面和第一个参数排在后面的情况。而 chrome 等 webkit 浏览器下是 0 (false) 和 -1 一样,都代表第一个参数排前面。array1.sort(); 的默认结果是升序排序。


var a = new Array(4, 11, 2, 10, 3, 1);

var b = a.sort();
document.write(b);
document.write("<br>");

// 这是 ASCII 字符顺序.
// 输出: 1,10,11,2,3,4

// 按照一个比较数组原书的函数来排序
b = a.sort(CompareForSort);
document.write(b);
document.write("<br>");
// Output: 1,2,3,4,10,11.

// 自定义升序排序的比较函数
function CompareForSort(first, second)
{
if (first == second)
return 0;
if (first < second)
return -1;
else
return 1;
}

// 升序排序比较函数的简短版本
function CompareForSort(first, second)
{
return first < second ? -1: 1;
}

参考

sort 方法 (Array) (JavaScript) – Internet Explorer 开发人员中心

angular.extend 实现解析

这是一篇废话,了解的请直接略过。

angular.extend 实现的代码如下:


/**

 * @ngdoc function

 * @name angular.extend

 * @module ng

 * @kind function

 *

 * @description

 * Extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
 * 将一个或多个 src 的 enumerable 属性复制到 dst 对象中。
 * to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
 * 若您需要保留最初的 dst 对象,你可以
 * by passing an empty object as the target: `var object = angular.extend({}, object1, object2)`.
 * 传入一个空对象作为 dst 参数: `var object = angular.extend({}, object1, object2)` 。
 * Note: Keep in mind that `angular.extend` does not support recursive merge (deep copy).
 * 注:注意 `angular.extend` 不支持递归复制(deep copy)。
 *

 * @param {Object} dst Destination object.
 * @参数 {对象} dst 目标对象
 * @param {...Object} src Source object(s).
 * @参数 {一个或多个对象} src 源对象
 * @returns {Object} Reference to `dst`.
 * @返回 {对象} `dst` 目标对象的引用
 */

function extend(dst) {

  var h = dst.$$hashKey;



  for (var i = 1, ii = arguments.length; i < ii; i++) {

    var obj = arguments[i];

    if (obj) {

      var keys = Object.keys(obj);  //用 Object.keys 而不是 for in 遍历所有 enumerable 属性,浏览器原生支持到 IE9+

      for (var j = 0, jj = keys.length; j < jj; j++) {

        var key = keys[j];

        dst[key] = obj[key];   //将属性直接用等号赋值过来

      }

    }

  }



  setHashKey(dst, h);  //给该  Object 加上 hash 值,方便 angular 快速访问

  return dst;  //返回目标对象

}

拓展阅读

怎样制作中间镂空的遮罩

SVG 版

最方便,兼容性最好的办法。方便镂空多个洞。代码来自 www.zhoumingzhi.com

镂空一个洞的代码


<div id="container" style="position: relative; margin: 550px 0 0 50px;">
<svg style="position: absolute;" width="400" height="280">
<defs>
<mask id="mask3">
<rect x="0" y="0" width="100%" height="100%" style="stroke:none; fill: #ccc"></rect>
<circle id="circle1" cx="100" cy="100" r="50" style="fill: #000" />
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" style="stroke: none; fill: #ccc; mask: url(#mask3)"></rect>
</svg>
<img src="http://img6.cache.netease.com/cnews/2014/11/3/20141103100737855b7.jpg" />
</div>

镂空多个洞的代码


<div id="container" style="position: relative;">
<svg style="position: absolute;" width="400" height="280">
<defs>
<mask id="mask3">
<rect x="0" y="0" width="100%" height="100%" style="stroke:none; fill: #ccc"></rect>
<circle id="circle1" cx="100" cy="50" r="50" style="fill: #000" />
<circle id="circle1" cx="300" cy="100" r="50" style="fill: #000" />
<circle id="circle1" cx="100" cy="200" r="50" style="fill: #000" />
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" style="stroke: none; fill: #ccc; mask: url(#mask3)"></rect>
</svg>
<img src="http://img6.cache.netease.com/cnews/2014/11/3/20141103100737855b7.jpg" />
</div>

Canvas 版

当镂空的形状比较复杂时,用 Canvas 的 globalCompositeOperation 是最终极的办法。当然 Canvas 也会有兼容性问题。

CSS clip 版

优点是所有浏览器都支持。缺点是更像是裁剪,只能遮罩特定的对象,而且只能镂空一个洞。

CSS 代码


#img1
{
position:absolute;
clip:rect(0px 50px 200px 0px)
}

HTML 代码


<img border="0" id="img1" src="/i/eg_bookasp.gif" width="120" height="151">

-webkit-mask 版

有前缀,而且其作用就是相当于在上面盖了一个图片,鸡肋一样的属性。如果直接盖一个图片的话,可以兼容所有场景和所有浏览器。-webkit-mask 实例代码来自 http://webengine.sinaapp.com/jian/

{
-webkit-mask: url(http://webengine.sinaapp.com/jian/images/mask.png) no-repeat center -10px;
-webkit-mask-size: 500px 750px;
}

CSS3 版

用 box-shadow ,代码如下:

position: fixed;
left: 150px;
top: 35px;
width: 100px;
height: 100px;
border-radius: 100px;
box-shadow: rgba(0,0,0,.8) 0px 0px 0px 2005px;
z-index: 100;

缺点是只能镂空一个洞。

IE8 及以下的传统版

有点是兼容性最强,形式随意,可以镂空任意个洞。缺点是给人感觉这种工作很 low,而且事实上确实乏味、辛苦而又没有技术含量。
在镂空区域的左、上、右、下分别放一个半透明 div 作为遮罩。
div 背景用滤镜半透明, IE7+ 可以用 png8 半透明图片来代替。

[翻译]简单实现 Angular-UI Bootstrap 的一个 alert service

导语

本文阐述 AngularJS 的 Bootstrap alert service 的简单实现方法,不依赖 jQuery,原文地址 https://coderwall.com/p/r_bvhg本文应该可以看作“一分钟入门 AngularJS Service 开发”,故转载并翻译之。

译文

Angular-UI Bootstrap 提供了不少流行的 Bootstrap 组件的 AngularJS directive(可显著降低代码量)。若您计划在您的 Angular App 中使用任何 Bootstrap 组件,强烈推荐您关注一下。它意味着直接包含 Bootstrap 的组件就能正确运行。 Service 用来在 controllers 之间共享代码。将代码从 controller 移出到 service,alert 是个正面的示例。 The Angular-UI Bootstrap 文档提供了如下例子:

VIEW

<div ng-controller="AlertDemoCtrl">
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
  <button class='btn' ng-click="addAlert()">Add Alert</button>
</div>

CONTROLLER

function AlertDemoCtrl($scope) {
  $scope.alerts = [
    { type: 'error', msg: 'Oh snap! Change a few things up and try submitting again.' }, 
    { type: 'success', msg: 'Well done! You successfully read this important alert message.' }
  ];

  $scope.addAlert = function() {
    $scope.alerts.push({msg: "Another alert!"});
  };

  $scope.closeAlert = function(index) {
    $scope.alerts.splice(index, 1);
  };
}

由于需要在 App 的不同 controller 里创建 alert,而代码在 controllers 之间互相引用又是个不良的编程习惯,所以我们得把它变成一个 service。

alertService

'use strict';

/* services.js */

// don't forget to declare this service module as a dependency in your main app constructor!
var appServices = angular.module('appApp.services', []);

appServices.factory('alertService', function($rootScope) {
    var alertService = {};

    // create an array of alerts available globally
    $rootScope.alerts = [];

    alertService.add = function(type, msg) {
      $rootScope.alerts.push({'type': type, 'msg': msg});
    };

    alertService.closeAlert = function(index) {
      $rootScope.alerts.splice(index, 1);
    };

    return alertService;
  });

View

这些标签也许会在您的 index.html 里,或者从一个头文件被包含过来。

<div>
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{ alert.msg }}</alert>
</div>

最后,我们需要将 alertService 的 closeAlert() 方法绑定到 $globalScope 里。

Controller

function RootCtrl($rootScope, $location, alertService) {
  $rootScope.changeView = function(view) {
    $location.path(view);
  }

  // root binding for alertService
  $rootScope.closeAlert = alertService.closeAlert; 
}
RootCtrl.$inject = ['$scope', '$location', 'alertService'];

我对这个绑定并不完全满意,希望能够直接从 html 标签直接调用这个 service 的 closeAlert 方法,但是还没发现怎么实现。 现在创建一个 alert 只需从任何一个 controller 调用 alertService.add() 即可。

function ArbitraryCtrl($scope, alertService) {
  alertService.add("warning", "This is a warning.");
  alertService.add("error", "This is an error!");
}

任何人有什么改进,请留言。希望此文是篇有用的 Angular.js service 介绍文。

译者:留言里真的有改进和实现方法,译者总结如下:

jwickers:以下代码无须注入到 controller 中就能运行。想从 html 标签中直接调用 closeAlert 方法只需增加一个 close 方法到 alert 对象中。

sur:我也添加了一个 clear 函数到 Alert Service 里面,这样只需调用 AppAlert.clear() 就能一键删掉所有的 alert。

译者:用 $sce 和 ng-bind-html 配合使用,可以使消息支持 html,须包含 AngularJS Router 文件。若不需要可以自行删掉调用了 $sce 的部分,一样可以正常运行。

alertService

.factory('AppAlert', [
      '$rootScope', '$timeout', '$sce', function($rootScope, $timeout, $sce) { 
        var alertService;
        $rootScope.alerts = [];
        return alertService = {
          add: function(type, msg, timeout) {
            $rootScope.alerts.push({
              type: type,
              msg: $sce.trustAsHtml(msg),
              close: function() {
                return alertService.closeAlert(this);
              }
            });

            if (timeout) { 
                $timeout(function(){ 
                    alertService.closeAlert(this); 
                }, timeout); 
            }
          },
          closeAlert: function(alert) {
            return this.closeAlertIdx($rootScope.alerts.indexOf(alert));
          },
          closeAlertIdx: function(index) {
            return $rootScope.alerts.splice(index, 1);
          },
          clear: function(){
            $rootScope.alerts = [];
          }
        };
      }
    ]);

View

<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="alert.close()"><span ng-bind-html="alert.msg"></span></alert>

原文地址

Angular-UI Bootstrap alert service for Angular.js

拓展阅读

Angular.js: service vs provider vs factory?

Apache 配置某个路径的反向代理

示例

<virtualhost *:【正在监听的端口号】>
  ProxyRequest off

  <proxy *>
    Order deny,allow
    Allow from all
  </proxy>
  <location 【指定的路径】>
    ProxyPass 【代理地址,要带 http://】
    ProxyPassReverse  【代理地址,要带 http://】
  </location>
</virtualhost>

同理还可以用 LocationMatch 等 directive 更灵活的配置。

参考

<Location> Directive – core – Apache HTTP Server