angular directives scope

以前学过,但是忘记了,所以重新记录一篇文章。

directive中的restrict属性,来决定这个指令是作为标签(E)、属性(A)、属性值(C)、还是注释(M)。

1、false(默认值):直接使用父scope。比较“危险”。

可以理解成指令内部并没有一个新的scope,它和指令以外的代码共享同一个scope。

2、true:继承父scope

 

 

3、{ }:创建一个新的“隔离”scope,但仍可与父scope通信

隔离的scope,通常用于创建可复用的指令,也就是它不用管父scope中的model。然而虽然说是“隔离”,但通常我们还是需要让这个子scope跟父scope中的变量进行绑定。绑定的策略有3种:

  • @:单向绑定,外部scope能够影响内部scope,但反过来不成立
  • =:双向绑定,外部scope和内部scope的model能够相互改变
  • &:把内部scope的函数的返回值和外部scope的任何属性绑定起来
(1)@:单向绑定

示例代码:

<body ng-app="watchDemo">
<!--外部scope-->
<p>父scope:<input type="text" ng-model="input"></p>
<!--内部隔离scope-->
<my-directive my-text="{{input}}"></my-directive>

<script>
    var app = angular.module('watchDemo', []);
    app.directive('myDirective', function () {
        return {
            restrict: 'E',
            replace: true,
            template: '<p>自定义指令scope:<input type="text" ng-model="myText"></p>',
            scope: {
                myText: '@'
            }
        }
    });
</script>
</body>

(2)=:双向绑定

示例代码:

<body ng-app="watchDemo">
<!--外部scope-->
<p>父scope:<input type="text" ng-model="input"></p>

<!--内部隔离scope-->
<!--注意这里,因为是双向绑定,所以这里不要“{{}}”这个符号-->
<my-directive my-text="input"></my-directive>

<script>
    var app = angular.module('watchDemo', []);
    app.directive('myDirective', function () {
        return {
            restrict: 'E',
            replace: true,
            template: '<p>自定义指令scope:<input type="text" ng-model="myText"></p>',
            scope: {
                myText: '=' // 这里改成了双向绑定
            }
        }
    });
</script>
</body>
(3)&:内部scope的函数返回值和外部scope绑定

 

<body ng-app="watchDemo">
<!--外部scope-->
<p>父scope:<input type="text" ng-model="input"></p>

<!--内部隔离scope-->
<!--注意这里,函数名字也要用 连字符命名法-->
<my-directive get-my-text="input"></my-directive>

<script>
    var app = angular.module('watchDemo', []);
    app.directive('myDirective', function () {
        return {
            restrict: 'E',
            replace: true,
            template: '<p>结果:{{ getMyText() }}</p>',
            scope: {
                getMyText: '&' // 这里改成了函数返回值的绑定
            }
        }
    });
</script>
</body>

AngularJS实现slide指令

前端的HTML代码如下:

<div test-slide="{{imgs}}" data-time="3"></div>

指令testSlide代码:

.directive("testSlide", function ($interval) {
    return {
        restrict: 'A',
        replace: false,
        link: function (scope, ele, attr) {
            scope.imgs = JSON.parse(attr.testSlide);
            var time = parseFloat(attr.time);
            if (scope.imgs.length > 0 && time > 0) {
                if (typeof window.__slide === "object" && window.__slide != null) {
                    $interval.cancel(window.__slide);
                }
                window.__slide = $interval(function () {
                    var n = $(".slide>.active");
                    var c = $(".slide").children();

                    var index = -1;
                    $.each(c, function (i, n) {
                        if (i + 1 === c.length && index === -1) {
                            index = 0;
                        }
                        if ($(n).hasClass('active') === true && index === -1) {
                            index = i+1;
                        }
                    })

                    n.removeClass('active slideInRight');
                    $(c[index]).addClass('active slideInRight');

                    if(typeof c[index] === "undefined"){
                        $interval.cancel(window.__slide);
                    }
                }, time * 1000)
            }
        },
        template: '<div><style>\n' +
        '        .slide{width: 100%;}\n' +
        '        .slide .slide-img{width: 100%;display: none;}\n' +
        '        .slide .active{display: block;}\n' +
        '    </style><div class="slide">' +
        '   <div class="slide-img {{$first?\'active\':\'\'}}" ng-repeat="v in imgs">' +
        '       <img ng-src="{{v}}"/>' +
        '   </div>' +
        '</div></div>'
    }
})

 

功能实现了,但是可能需要增加一些动画效果,这里就懒得整了。

angularJs ng-options指令详解

ng-options一般有以下用法及其详解

数组:

  •  label for value in array
  •  select as label for value in array
  •  label group by group for value in array
  •  label disable when disable for value in array
  •  label group by group for value in array track by trackexpr
  •  label disable when disable for value in array track by trackexpr
  •  label for value in array | orderBy:orderexpr track by trackexpr(for including a filter with track by)

对象:

  •  label for (key , value) in object
  •  select as label for (key ,value) in object
  •  label group by group for (key,value) in object
  •  label disable when disable for (key, value) in object
  •  select as label group by group for(key, value) in object
  •  select as label disable when disable for (key, value) in object

选中:

ng-options的选中方式是根据ng-model而决定的,假如我们的对象是:

[{“value”:0,”name”:”否”},{“value”:1,”name”:”是”}]

那么ng-model对应的就是:

{“value”:0,”name”:”否”} 或者是 {“value”:1,”name”:”是”} 对象。

一个例子:

//The html code.
<select class="form-control" ng-model="selected" ng-options="n.name for (i,n) in defaultContent" ng-change="change(selected)"></select>

 

//and the js code.

.controller("testController",function($scope){

    /**
     * selected value.
     * @type {string}
     */
    $scope.content = "0";

    /**
     * select options object.
     */
    $scope.defaultContent = JSON.parse('[{"value":0,"name":"否"},{"value":1,"name":"是"}]');

    /**
     * foreach defaultContent and found the selected object.
     */
    for(i in $scope.defaultContent){

        /**
         * if defaultContent[i].value equals content,than the selected object is defaultContent[i].
         */
        if($scope.defaultContent[i].value == parseInt($scope.content)){
            $scope.selected = $scope.defaultContent[i];
            break;
        }
    }
    $scope.change = function(obj){
        log(obj)
    }
})
  • defaultContent是我们默认的下拉选择框的对象数组。
  • content是下拉选择框选中value的值
  • 经过遍历数组,找出选中值的对应对象复制给新申明的选中对象selected。
  • html代码ng-model赋值selected就可以了。

AngularJS使用ng-repeat不更细View

今天在使用angularJS开发一个上传图片的功能,但是遇到了view不更新的问题,查了国内大部分网站,发现很多人都出现过这个问题,但是他们一般都是出现在请求数据中,我的项目全部都是使用promise对象处理的,所以没有出现过他们出现的问题,但是上传图片是没有数据传输的(因为我意图是在本地裁剪图片);

如果有像我这样子的,可以使用:

$scope.$apply();
通知视图更新,但是这不是一个好的习惯。

原文:
$scope.$apply(function() {
  $scope.msgs = newMsgs;
});

That is telling Angular that you’ve modified something it needs to know about from a context that it doesn’t know about (the jQuery ajax call in this case).

There are some valid uses of $scope.$apply(), such as in event handlers, but most other times it is a sign of bad practices. You should definitely be using Angular’s $http for ajax calls.

 

 

 

angularJS移动应用触摸touch事件

首先我们定义一个指定(directive),如下面代码:

.directive('myTouchEven', ['$swipe', "$rootScope", function ($swipe, $rootScope) {
    return {
        restrict: 'EA',
        link: function (scope, ele, attrs, ctrl) {
            var startX, pointY;
            $swipe.bind(ele, {
                'start': function (coords) {
                    startX = coords.x;
                    pointY = coords.y;
                    c("startX:" + startX + "pointY:" + pointY)
                },
                'move': function (coords) {
                    var a = coords.x - startX;
                    if (a < -100 && a > -110) {
                        startX = coords.x;
                        $rootScope.$broadcast("TouchEven", "back");
                    } else if (a > 100 && a < 110) {
                        startX = coords.x;
                        $rootScope.$broadcast("TouchEven", "next");
                    }
                    c("move:" + a + " coords.x:" + coords.x)

                },
                'end': function (coords) {
                    c("end")
                    c("endX:" + coords.x + "endY:" + coords.y)
                },
                'cancel': function (coords) {
                    c("cancel")
                }
            });
        }
    }
}])

这里使用$swipe来帮顶触摸事件,在start事件中记录开始点击的坐标值(x、y)的数据;然后我们监控move事件,计算当前的坐标值(x、y)于开始点击的坐标值相差是多少,如果大于或者小于我们设定的数值,那么则发送一个全局广播,这里注入了$rootScope,用来发送全局广播($broadcast),其他指令(directive)、服务(service)、控制器(controller)等只要注册了(TouchEven)广播监听,就能接收到我们发送的广播事件,下面是示例代码:

.controller("ListController", function ($scope, $routeParams,ajax) {
    $scope.pages = 1;

    $scope.$on("TouchEven",function(a,b){
        var is_send = null;
        if(is_send == null){
            is_send = 1;

            if(b == "back"){
                $scope.pages -= 1;
            }else if(b == "next"){
                $scope.pages += 1;
            }

            ajax.get("/api/v1/articleList",{pages:$scope.pages})
                .success(function(data){
                    is_send = null;
                    c(data)
                    /**
                     * write something code.
                     */

                })
                .error(function(err){
                    is_send = null;
                    toast(err.response_err)
                    /**
                     * write something code.
                     */
                })


        }


    });
    
})

 

 

12