OhNaNaSun / imoocLesson

imooc的课程
1 stars 0 forks source link

AngularJS #1

Open OhNaNaSun opened 7 years ago

OhNaNaSun commented 7 years ago

自定义指令

api 单向绑定不能应用于 对象 并且 继承父级scope,又改变自身scope上的值

< or <attr - set up a one-way (one-directional) binding between a local scope property and an expression passed via the attribute attr. The expression is evaluated in the context of the parent scope. If no attr name is specified then the attribute name is assumed to be the same as the local name. You can also make the binding optional by adding ?: <? or <?attr.

For example, given and directive definition of scope: { localModel:'<myAttr' }, then the isolated scope property localModel will reflect the value of parentModel on the parent scope. Any changes to parentModel will be reflected in localModel, but changes in localModel will not reflect in parentModel. There are however two caveats:

one-way binding does not copy the value from the parent to the isolate scope, it simply sets the same value. That means if your bound value is an object, changes to its properties in the isolated scope will be reflected in the parent scope (because both reference the same object). one-way binding watches changes to the identity of the parent value. That means the $watch on the parent value only fires if the reference to the value has changed. In most cases, this should not be of concern, but can be important to know if you one-way bind to an object, and then replace that object in the isolated scope. If you now change a property of the object in your parent scope, the change will not be propagated to the isolated scope, because the identity of the object on the parent scope has not changed. Instead you must assign a new object.

One-way binding is useful if you do not plan to propagate changes to your isolated scope bindings back to the parent. However, it does not make this completely impossible.

父级作用域&独立作用域

<div ng-app = "myApp">
    <div ng-controller="myCrl">
        <span>父级controller上的属性:{{name}}</span>
        <greeting></greeting>

    </div>
</div>
<script>
    var myApp = angular.module("myApp", []);
    myApp.controller("myCrl", function($scope){
        $scope.name = "sss"
    })
    myApp.directive("greeting", function(){
        return {
            restrict: "E",
            template: "<div>direct上自己的属性:<input type='text' ng-model='name'/><span>{{name}}</span></div>",
            //能拿到父级controller上的属性,一个改变都改变。其实是同一个作用域
            //现在我们创建独立作用域
            scope:{},//父级属性不变了
            replace: true
        }
    })
</script>

- 基于字符串(或者变量)的绑定:使用@操作符,双引号内的内容当做字符串进行绑定。

你还可以绑定来自外层scope的值。在属性值中插入{{}}即可。但是改变direct中的属性,父级中的属性不变。 image 或者传递字符串 image

-使用=操作符,与父scope中的属性进行双向绑定。父级controller里的属性会一起变化

image

-传递一个来自父scope的函数,稍后调用。传递的属性和父scope上的没关系了。

image 多个directive也没问题 image

OhNaNaSun commented 7 years ago

checkbox组合 controller之间传递方法 js,css版本号

OhNaNaSun commented 7 years ago

ui-router

api

view: @

路由 Route

$stateProvider
    .state('contacts.list', {
        url: '',
        templateUrl: 'contacts.list.html'
    })

    .state('contacts.detail', {
        url: '/{contactId:[0-9]{1,4}}',

        // view 用在该状态下有多个 ui-view 的情况,可以对不同的 ui-view 使用特定的 template, controller, resolve data
        // 绝对 view 使用 '@' 符号来区别,比如 'foo@bar' 表明名为 'foo' 的 ui-view 使用了 'bar' 状态的模板(template),相对 view 则无
        views: {
            // 无名 view
            '': {
                templateUrl: 'contacts.detail.html',
                controller: ['$scope', '$stateParams', 'utils',
                    function ($scope, $stateParams, utils) {
                        $scope.contact = utils.findById($scope.contacts, $stateParams.contactId);
                    }
                ]
            },

            // for "ui-view='hint'"
            'hint@': {
                template: 'This is contacts.defail populating the "hint" ui-view'
            },

            // for "ui-view='menuTip'"
            'menuTip': {
                templateProvider: ['$stateParams',
                    function($stateParams) {
                        return '<hr><small class="muted">Contact ID: ' + $stateParams.contactId + '</small>';
                    }
                ]
            }
        }
    })

URL参数

参考: 【原创】ui.router源码解析

基本参数

通常,url动态部分被称为参数,有几个选项用于指定参数。基本参数如下:

$stateProvider
    .state('contacts.detail', {
        // 这里设置了url参数
        url: "/contacts/:contactId",
        templateUrl: 'contacts.detail.html',
        controller: function ($stateParams) {
            // If we got here from a url of /contacts/42
            expect($stateParams).toBe({contactId: 42});
        }
    })

或者,你也可以使用花括号的方式来指定参数:

// 与前面的设置方法等效
url: "/contacts/{contactId}"

示例: '/hello/' - 只匹配'/hello/'路径,没有对斜杠进行特殊处理,这种模式将匹配整个路径,而不仅仅是一个前缀。 '/user/:id' - 匹配'/user/bob'、'/user/1234!!!',甚至还匹配 '/user/',但是不匹配'/user'和'/user/bob/details'。第二个路径段将被捕获作为参数"id"。 '/user/{id}' - 与前面的示例相同,但使用花括号语法。

含正则表达式的参数

使用花括号的方式可以设置一个正则表达式规则的参数:

// 只会匹配 contactId 为1到8位的数字
url: "/contacts/{contactId:[0-9]{1,8}}"

示例: '/user/{id:[^/]}' - 与'/user/{id}'相同 '/user/{id:[0-9a-fA-F]{1,8}}' - 与前面的示例相似,但只匹配1到8为的数字和字符 '/files/{path:.}' - 匹配任何以'/files/'开始的URL路径,并且捕获剩余路径到参数'path'中。 '/files/*path' - 与前面相同,捕获所有特殊的语法。 警告:不要把捕获圆括号写进正则表达式,ui-router 的 UrlMatcher 将为整个正则表达式添加捕获。

Query Parameters

可以通过?来指定参数作为查询参数

url: "/contacts?myParam"
// 匹配 "/contacts?myParam=value"

如果你需要不止一个查询参数,请用&分隔:

url: "/contacts?myParam1&myParam2"
// 匹配 "/contacts?myParam1=value1&myParam2=wowcool"

controller中获取参数

使用$state, $stateParams

OhNaNaSun commented 7 years ago

Module

参考:

.config

在模块的加载阶段,AngularJS会在提供者注册和配置的过程中对模块进行配置。在整个AngularJS的工作流中,这个阶段是唯一能够在应用启动前进行修改的部分。

angular.module('myApp', [])
  .config(function($provide) {
  });

.run

和配置块不同,运行块在注入器创建之后被执行,它是所有AngularJS应用中第一个被执行的方法。

运行块是AngularJS中与main方法最接近的概念。运行块中的代码块通常很难进行单元测试,它是和应用本身高度耦合的。

运行块通常用来注册全局的事件监听器。例如,我们会在.run()块中设置路由事件的监听器以及过滤未经授权的请求。

假设我们需要在每次路由发生变化时,都执行一个函数来验证用户的权限,放置这个功能唯一合理的地方就是run方法

angular.module('myApp', ['ngRoute'])
.run(function($rootScope, AuthService) {
    $rootScope.$on('$routeChangeStart', function(evt, next, current) {
        // 如果用户未登录
        if (!AuthService.userLoggedIn()) {
            if (next.templateUrl === "login.html") {
                // 已经转向登录路由因此无需重定向
            } else {
                $location.path('/login');
            }
        }
    });
});

run()函数接受一个参数。

initializeFn(函数)AngularJS在注入器创建后会执行这个函数。

OhNaNaSun commented 7 years ago

理解$watch ,$apply 和 $digest --- 理解数据绑定过程

这就是angular的双向数据绑定原理 理解$watch ,$apply 和 $digest --- 理解数据绑定过程 例子 $$phase

$watch的参数

谈谈AngularJS中的$watch 例子

每一个绑定到了UI上的数据都会生成一个$watch。对,那这写$watch是什么时候生成的呢? 当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段---译者注),Angular解释器会寻找每个directive,然后生成每个需要的$watch。

如果我们将$watch的第三个变量设置为true,那么此时我们进行的监视叫做“全等监视”,原词是“equality watch”。此时,$watch就像是一个醋意十足的恋人,只要看他的对象有一点风吹草动,马上就跳出来,大喊大叫:“你冷酷你无情,你无理取闹。就算我冷酷,我无情,我无理取闹,也没有你冷酷你无情,你无理取闹!尔康。。。。。”。

OhNaNaSun commented 7 years ago

inject api 例子

OhNaNaSun commented 7 years ago

1.ng的三种注入方式:推断式、标注式、内联式。 (1).推断式注入:ng根据函数的签名(被注入的函数名),将和函数签名一样的函数名注入到调用者中.函数签名要和注册的函数名完全一样,否则注入不成功.如function($scope){} $scope不能改为$scope1.有的代码压缩工具可能会将参数压缩,如$scope会变为e之类的,此时注入会失效. (2).声明式注入(标注式注入):函数参数名可以随便取,在底下声明----注入对象.$inject = ['函数签名1','函数签名2',...]; (3).内联式注入:综合以上两种方法 2.annotate是用来分析函数的参数的,它能把一个函数的参数提取出来,随后进行依赖分析.function(arg1,arg2){}得到的返回值是["arg1","arg2"]. 3.在bootstrop里面最后一个步骤创建注射器,两个注射器类型:providerInjector(创建注射器)和instanceInjector(获得对象实例)。 4.injector是用来实例化已经定义过的provider,实例化类型,invoke方法和加载模块的.