AngularJS-笔记2

==============================    自定义指令    ==================================
<!DOCTYPE html>
<html>
        <!-- template.html中属性myModel通过ng-model内置指令绑定到input组件;
                而属性myModel是自定义指令配置对象中replace=true创建的孤立作用域中scope定义的.
                myModel: "=" 表示<hello my-model="parentModel"></hello>中my-model绑定的parentModel属性, 而该属性属于父作用域中定义的.
                因此最终实际是parentModel属性和template.html中的input组件双向绑定了. -->
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="https://cdn.staticfile.org/angular.js/1.5.8/angular.min.js"></script>
    </head>
 
    <body ng-app="myApp">
        <div ng-controller="myCtrl">
            <!-- 注意<hello>标签中的属性必须要是指令配置对象中定义的驼峰命名变量myModel用'-'分隔改名后的my-model类似于ng-model,而不允许是其他任意名字. 若只是一个单词无需用-直接使用即可.
                即my-model和scope.myModel是同一个东西. -->
            <hello my-model="parentModel"></hello>   
        </div>
    </body>
 
    <script>
        var myApp = angular.module("myApp", []); myApp.controller("myCtrl", ["$scope", function($scope){ $scope.parentModel = "hello"; $scope.$watch("parentModel", function(newValue){ //监视父作用域属性parentModel,当属性值发生改变时才会执行相应的函数  console.log("parentModel-value: " + $scope.parentModel); }); }]); myApp.directive("hello", function(){ return { restrict: "EA", //自定义指令以html标签后内置html标签属性的方式使用  templateUrl: "template.html", //指令返回的DOM页面  replace: true, //创建一个不同于父作用域的孤立作用域  scope:{ //该指令作用域中定义的属性  myModel: "=", //当为"="时,scope.myModel、my-model以及ng-model="myModel"三者的名字要相同(驼峰命名中间者加-分隔) // innerModel: "=myModel" //当为"=attr"时,要求myModel和my-model两者名字相同, scope.innerModel和ng-model="innerModel"两者名字相同,这样才生效(这种方式本质和方式1相同)  }, link: function(scope){ console.log(scope) } } }) </script> </html>

template.html
<div>
    <h3>{{myModel}}</h3>
    <!-- <h3>{{innerModel}}</h3> -->
    <input ng-model="myModel">
    <!--注意模板文件中只允许一个根标签,</div>标签后不允许有其他东西包括注释.否则会报错"Error: [$compile:tplrt]"-->
</div>
 
指令各函数执行顺序, compile->controller->compile返回的link函数; (若compile返回prelink和postlink则controller和prelink先后执行,最后执行postlink; 默认compile返回的是postlink)
多层指令的comiple和控制器执行顺序为:由外到内(即先由外到内执行完所有指令的compile,然后由外到内执行所有controller)
 
在自定义指令在html文件中使用tmpplateUrl时,报错找不到url对应的html文件:(原因:文件跨域报错)
"Access to XMLHttpRequest at 'file:///C:/Users/l00517779/Desktop/AngularHello/src/myDirect/template.html' 
from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https."
解决办法:对于vscode IDE安装Live Server插件即可。安装该插件后,修改html文件保存后,页面会自动刷新。
查看Live Server插件的设置json:F1调出命令台,输入Open Default Settting(JSON),搜索live server即可(可以看到默认端口为5500)
 
在编写模板文件template.html中也可能会遇到如下错误:"Error: [$compile:tplrt]报错"
原因:注意模板文件中只允许一个根标签,</div>标签后不允许有其他东西包括注释.否则会报该错
 
报错:"Error: $compile:nonassign Non-Assignable Expression"
通常是使用了未定义的变量.例如:在使用自定义指令中scope的属性时未使用驼峰名的'-'变式.
 
服务:
angularModule.factory(name, getFn);
AngularJS服务都是单实例。即getFn函数在应用的整个生命周期中最多只会被调用一次。(即服务第一次被注入时,getFn会被调用创建唯一的服务实例并保存到缓存,下次使用直接查)
当服务第一次被注入到控制器或者指令等时,AngularJS会自动调用getFn函数实例化服务,该实例会被放入一个缓存对象中。当其它地方要注入该服务时,首先会判断该服务的实例是否已经存在,如果存在就将该实例返回,否则调用getFn创建实例。
provider方法定义的服务可以通过app.config函数在实例化前配置服务(即在服务注入前实现配置),config函数会在app.provider方法执行后执行。
当我们希望在应用开始前对服务进行配置的时候就需要使用到provider()。比如,我们需要配置服务在不同的部署环境里面(开发,演示,生产)使用不同的后端处理的时候就可以使用到了;
factory和service两个方法使用都差不多,大家可以根据自己喜好选择。
 
路由机制:根据url分配到对应的处理程序
在使用ui-router模块时,对于低版本的1.x angularJS库只存在angular-route.js,而不包含angular-ui-router.js库文件,这导致在使用时会报错"Error: $injector:modulerr Module Error"。
解决办法:
方法1:改用ngRoute即可(虽然ngRoute不如ui-router,1.2版本以上的1.x angularJS均支持ngRoute单独一个模块)
<script src="https://code.angularjs.org/1.5.8/angular-route.js"></script>
方法2:找一个在线的ui-router模块的库文件引入(建议下下来,获取该js的过程太慢)
<script src="//unpkg.com/@uirouter/angularjs/release/angular-ui-router.min.js"></script> 或
<script src = "https://unpkg.com/@uirouter/[email protected]/release/angular-ui-router.min.js">
路由跳转:$state.go('manage.dataLabel');
当某个状态被激活时,ui-view处的DOM元素将被该状态对应的HTML页面填充。
 
$stateProvider:状态提供者(state方法用于注册状态);
$urlRouterProvider:负责监听状态的变化并进行相应的处理(when()、otherwise()和rule()方法). 当$location变化的时候,$urlRouterProvider开始在一个规则的列表中一个个的查找,直到找到匹配的值。$urlRouterProvider用于在后端指定url的状态配置。所有的url被编译成UrlMatcher对象。
$controllerProvider:提供了一种可以根据业务逻辑动态添加控制器的方法
 
路由状态对象属性:
controller:状态页面对应的控制器(页面可以直接访问该控制器scope中的变量)
resolve:给状态controller注入一些该状态自己的函数或数据(例如可以在其中定义函数加载相关依赖js文件的函数)。即resolve中定义的函数在controller实例化之前执行.
对象的每个属性都是要注入controller的依赖。
属性值可以是一个字符串,也可以是一个函数:
1)如果属性值是String,该字符串是一个该模块上已注册的服务名;
2)如果值是一个函数,则注入这个函数,函数的返回值就是依赖。如果函数返回一个promise,它会在控制器被实例化之前resolved,同时其返回值会注入到控制器中。
 
运用AngularJS要注意的问题:
1、双向绑定的变量设置成$scope下的一个对象的属性,因为直接设置成$scope的属性时,不会从父容器中查找。eg:
        <div ng-controller="myController1">
            <div ng-if="true">
                <input value="inputValue.text" ng-model="inputValue.text">
                <!-- <input value="inputValue" ng-model="inputValue"> 
            </div>
            <h2>input输入框中的值是:{{inputValue.text}}</h2>
            <!-- <h2>input输入框中的值是:{{inputValue}}</h2> -->
        </div>
 
        myApp.controller("myController1", ["$scope", function($scope){
            // 如果将inputValue改变成一个对象,将这个对象的属性text赋给input的value。
            // 这时,如果输入框值改变,会依据原型继承链向上在控制器的scope中找到inputValue变量,并将输入框值更新到text属性中
            $scope.inputValue = {
                text : "hello angular"
            }; 
            // 由于ng-if会创建一个scope,所以,input上的scope变成了ng-if指令的scope。(一开始由于ng-if的scope中不存在inputValue变量会到父scope中查找,后面当值改变时ng-if会在ng-if创建的scope上创建一个inputValue)
            // 当值改变时,会在ng-if创建的scope上创建一个inputValue属性,并将input的内容赋给该变量,(但如果是对象是无法自动创建的,只能往上查找)
            // 并不会通知给外部控制器创建的scope上的inputValue变量。
            // $scope.inputValue = "hello angular";    
 
第三方API比如jQuery, jQuery的函数执行后并不会刷新视图,
需要放到$scope.$apply中执行以通知视图刷新. 而angularJS自带的ng-click指令执行的函数会自动刷新视图.
<div ng-controller="myController">
    <h3>{{value}}</h3>
    <button id="buttonId" >change value</button>        //改成<button ng-click="myClick()">change value</button>,再在控制器中定义myClick()也可实现自动刷新
</div>
    myApp.controller("myController", ["$scope", function($scope){
        $scope.value = "hello angularJS";
        $("#buttonId").on("click", function(){
            // 如果$scope.value += " aaa"不放置值$apply中,视图不会刷新
            $scope.$apply(function(){
                $scope.value += " aaa";
            });
            // $scope.value += " aaa";
        });
    }]);
 
$q.all是用于执行多个异步任务进行回调,它可以接受一个promise的数组,或是promise的hash(object)。任何一个promise失败,都会导致整个任务的失败。
 
angularJS中的$q服务、deferred对象和promise对象:
详见:
https://www.jianshu.com/p/ed6e9886fa76(详解这3个概念)
$q.all([promise1, promise2])方法返回的仍为promise对象,只不过只有所有的promise状态均为成功才为成功,否则失败;并且不会执行notify回调函数.

var myApp = angular.module("myApp", []);
myApp.controller("myCtrl", myContrl);
myApp.service("myService", myService);
myContrl.$inject = ['$q', "myService"];
myService.$inject = ['$q'];

//自定义服务. $q:是anjularjs的内置服务, 必须以依赖注入的方式注入后才能使用(不能简单地引入angular.js文件后像普通变量那样使用).
function myService($q){ var self = this; //this表示该服务器对象 self.name = "haha"; console.log("this: ", this); //console放前放后打印的结果都相同 this.asyncGreet = function(name){ var deferred = $q.defer(); //通过$q.defer()创建一个deferred延迟对象,在创建一个deferred实例时,也会创建出来一个派生的promise对象,使用deferred.promise就可以检索到派生的promise。 /**方式1:定义双层函数 */ //注意setTimeout只能传递函数引用,不能是task(), 否则会立即执行.若想执行带参函数, 可以在函数外面再定义一个函数返回该函数引用即可. //setTimeout等后面的代码执行完再执行该语句(若不通过setTimeout的方式来执行,则不会执行notify的回调函数); // var task = function(deferred2){ // return function(){ // deferred2.notify('About to greet ' + name + '.'); //延迟对象的notify方法。表示状态"正在执行中", 参数传入notify的回调函数即update. // deferred2.notify('notify ' + name + '.'); // if (okToGreet(name)) { // deferred2.resolve('Hello, ' + name + '!'); //任务被成功执行, deferred.resolve修改deferred对象的状态编程“成功执行”, 并且resolve函数的参数会传给对应的回调函数(对应下面的greeting). // } else { // deferred2.reject('Greeting ' + name + ' is not allowed.'); //任务未被成功执行,deferred.reject修改deferred对象的状态编程“未成功执行” // } // } // } // setTimeout(task(deferred), 5); /**方式2:使用外部变量 */ var task = function(){ deferred.notify('About to greet ' + name + '.'); //延迟对象的notify方法。表示状态"正在执行中", 参数传入notify的回调函数即update. deferred.notify('notify ' + name + '.'); if (okToGreet(name)) { deferred.resolve('Hello, ' + name + '!'); //任务被成功执行, deferred.resolve修改deferred对象的状态编程“成功执行”, 并且resolve函数的参数会传给对应的回调函数(对应下面的greeting). } else { deferred.reject('Greeting ' + name + ' is not allowed.'); //任务未被成功执行,deferred.reject修改deferred对象的状态编程“未成功执行” } } setTimeout(task, 5); alert("now"); //点确定才会执行后面的语句 console.log("haha"); /**方式3:但不会执行notify的回调函数 */ // deferred.notify('About to greet ' + name + '.'); //延迟对象的notify方法。表示状态"正在执行中", 参数传入notify的回调函数即update. // if (okToGreet(name)) { // deferred.resolve('Hello, ' + name + '!'); //任务被成功执行, deferred.resolve修改deferred对象的状态编程“成功执行”, 并且resolve函数的参数会传给对应的回调函数(对应下面的greeting). // } else { // deferred.reject('Greeting ' + name + ' is not allowed.'); //任务未被成功执行,deferred.reject修改deferred对象的状态编程“未成功执行” // } function okToGreet(name) { //只是mock数据,实际情况将根据相关业务实现代码 if(name == 'Superman') return true; else return false; } return deferred.promise; //返回deferred实例的promise对象(该promise对象可以认为是deferred对象的拷贝,但该promise不能修改deferred对象的状态,仅保存了deferred的状态) } console.log("self: ", self); console.log(this==self); console.log(this===self); //严格相等返回true, 即this就是self } //控制器构造函数会在scope范围内的html元素加载前执行,主要用于控制scope范围内的html元素的逻辑处理. function myContrl($q, myService){ console.log(this); //this表示该控制器对象 var promise = myService.asyncGreet('Superman'); //获得promise对象 //promise对象的then函数会获得当前任务也就是当前deferred延迟实例的执行状态。它的三个回调函数分别会在resolve(), reject() 和notify()时被执行 promise.then(function(greeting) { //promise根据deffered对象的执行状态,选择性执行后面的3个回调函数. then执行回调函数后会返回一个新的衍生promise,形成promise链. alert('Success: ' + greeting); }, function(reason) { alert('Failed: ' + reason); }, function(update) { alert('Got notification: ' + update); }).finally(function(){alert("finally")}); /* 另一种实现方式 */ // $q.when(myService.asyncGreet('Superman')).then(function(greeting) { // alert('Success: ' + greeting); // }, function(reason) { // alert('Failed: ' + reason); // }, function(update) { // alert('Got notification: ' + update); // }); }
// 当创建一个deferred实例时,promise实例也会被创建。通过deferred.promise就可以检索到deferred派生的promise。
// promise返回当前任务的完成结果, 作为完成或未完成的信号. promise的目的是允许interested parties 访问deferred任务完成的结果。
// 当某件耗时操作执行完后, 通过defred.resolve()等方法修改deffred的状态, 并将promise返回. 然后可以根据返回状态执行相应的回调函数。
// deferred对象一般在耗时操作中创建和返回; 然后在操作外部使用返回的promise对象来执行相应的回调函数。 从而能够实现异步执行一些多个耗时的操作,并自动对应执行结果进行处理.
 
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <title>js test</title>
</head>
 
<body ng-app="myApp">
<div ng-controller="myCtrl">
    <p>just a test!</p>
</div>
 
<script type='text/javascript' src='https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js'></script>
<script src="test.js"></script>
</body>
</html>
JS是单线程的,setTimeout实现了一种伪多线程的概念,实现更好的交互。
setTimeout获取函数的返回值,只能通过全局变量的方法(也可以直接在回调函数中修改全局变量不返回)。setTimeout()会等后面的代码执行完再执行回调函数(与主线程是同步关系)。
<head>
    <title>setTimeout调用又返回值的函数</title>
    <script language="javascript" type="text/javascript">
        var retValue = "";
        function test(name) {
            console.log(name)
            return "哈哈哈哈哈"; } function clickButton1() { var iTimeoutId = setTimeout("retValue = test('haha') ", 5000); //retValue就是全局变量retValue  } function clickButton2() { alert(retValue); } </script> </head> <body> <input type="button" onclick="clickButton1()" value="button1"> <input type="button" onclick="clickButton2()" value="button2"> </body>
setTimeout调用带参函数的方法:将函数再包装一层无参函数,或包装有参函数返回无参函数;最终实现的都是传给setTimeout的都是无参函数引用.
eg:setTimeout(function(){task(deferred)}, 5);
注:当setTimeout("task(parm)", 5)的形式调用时,双引号中的方法和实参均必须定义在全局作用域内即方法不能是内部方法,变量不能当前局部作用域的变量; 否则会报错“未定义”.
 
当setTimeout(task, 5)的形式调用时,task可以是局部或全局方法. 
 
懒加载的概念:
ui-router中状态配置项resolve即key-value是懒加载核心. 因为当跳转到当前状态时,在配置当前状态的控制器之前(即执行controller键值对之前),
会首先实例化resolve配置项中属性对应 内容,这样便可以在resolve中加载当前控制器对应的控制器文件.
所谓懒加载:是相对在首页分别加载状态的控制器js文件而言的,若不采用懒加载则需要在html头或尾加载所有状态的控制器js文件,从而导致首页加载过慢;
而使用懒加载后在跳转到当前状态才去加载它的控制器文件, 从而实现按需加载。
 
ng-class的几种使用方式:
通过键值对:<div class="openlayers cti-fl-left" ng-class="{'full':isFullScreen}"> <!--当isFullScreen为true时,将采取full样式-->
通过数组:ng-class="{true:'active-tool-botton'}[clickIndex == 0]" 
 
angular.module.value()与angular.module.constant():
angularJS定义全局变量的三种方法: https://blog.csdn.net/Evankaka/article/details/51137677
 
angular.run和angular.config有什么不同?
 
作用域的问题:
用$rootScope.var=value定义的变量可以在整个应用程序中使用, 包括在所有的控制器/服务/过滤器/指令中使用($rootScope.var的方式),还可以在任意html文件中使用("var"的方式)
控制器对应的scope中定义的变量可以用在控制器ng-controller管辖范围内的html元素内.
 
$rootscope.$apply()理解:
 
同一个模块下注册的服务、命令、过滤器等;在该模块上注册新的模块时,若要依赖该模块已注册的模块
module和provide是用来注册服务到injector中的。查看官方的API,可以看到$provide提供了provide()、constant()、value()、factory()、service()来创建各种不同性质的服务;angular.Module中也提供了这5个服务注册方法。其实2者功能是完全一样的,就是用来向DI容器注册服务到injector中。
 
 
模块、服务、指令、过滤器间的介绍: https://www.devtalking.com/articles/angularjs1x-guide/
服务详解+理解: https://juejin.im/entry/57e0fa7da22b9d0061256730

服务是一个对外提供某个特定功能,如消息服务、文件压缩等的独立模块。在AngularJS中,服务是一个单例对象或者函数。具有以下的两个特点:

  • 服务是一个单例,即无论这个服务被注入到任何地方,对象始终只有一个实例
  • 定义服务的方式也是通过function,但是与我们自己定义一个function然后在其他地方调用不同,因为服务是被定义在一个模块中,所以其使用的范围是可以被管理的,这一点体现了AngularJS非常强的避免全局变量污染意识。
注:当依赖注入的服务定义在了另一个模块中(即在另一个模块中注册),首先需要将该模块注入到被依赖的模块中,然后才能调用该模块的服务。
angular.module('myModule', [])
         .factory('myFactory', function () {
             return {};
         });
 var app = angular.module('myApp', ['myModule']);  
 app.controller('myCtrl', ['$scope', 'myFactory', function ($scope, myFactory) {
     console.log(myFactory);
 }]);
 
 
指令间可通过指令的控制器来通信,前提是在定义指令时,指定了require属性(即指定了需要依赖的指令名/指令名数组):
指令的link函数的第四个参数ctrl即会传入所依赖的指令的控制器实例.
若require属性的指令名前没有前缀,则只会在指令的当前作用域查找ng-model指令。eg:
<!-- 指令会在本地作用域查找ng-model -->
<div my-directive ng-model="object"></div>
 
$apply和$render的区别:
$apply:将angularJS上下文之外对model的修改,同步到view上. 即model->view
如果你在AngularJS上下文之外的任何地方修改了model,那么你就需要通过手动调用$apply()来通知AngularJS。
这就像告诉AngularJS,你修改了一些models,希望AngularJS帮你触发watchers来做出正确的响应。
比如1:你在setTimeout函数(JS函数)中调用anjular方法修改了model的值, 就必须手动调用$apply函数.
            当然也可以使用$timeout service来代替setTimeout(),因为前者会帮你调用$apply(),让你不需要手动地调用它。
你也可以在修改了model之后手动调用没有参数的$apply(),就像下面这样:
$scope.getMessage = function() {
  setTimeout(function() {
    $scope.message = 'Fetched after two seconds';
    console.log('message:' + $scope.message);
    $scope.$apply(); //this triggers a $digest
  }, 2000);
};
以上的代码使用了$apply()的第二种形式,也就是没有参数的形式。
需要记住的是你总是 应该使用接受一个function作为参数的$apply()方法。
这是因为当你传入一个function到$apply()中的时候,这个function会被包装到一个try…catch块中,所以一旦有异常发生,该异常会被$exceptionHandler service处理。
eg:在DOM Core API中调用angularJS的方法修改model,也需要手动调用$apply
           elm.bind('blur', function () {
                scope.$apply(function () {
                    console.log(elm.html());
                    ctrl.$setViewValue(elm.html());
                });
            });
$render:可以实现model->view也能实现view->model的传播.eg:
<html ng-app='form-example2''>
<head>
    <title>setTimeout调用又返回值的函数</title>
    <script src="https://cdn.staticfile.org/angular.js/1.5.8/angular.min.js"></script>
    <script src='script.js'></script>
</head>
<body ng-controller='myCtrl'>
    Input里面模型的值:{{vm.modelTest}}
    <input type="text" ng-model="vm.modelTest" model-render>
</body>
</html>
 
angular.module('form-example2', [])
    .controller('myCtrl', ["$scope", function(scope){
    }])
    .directive('modelRender', function () { return { require: 'ngModel', link: function (scope, iElm, iAttrs, ngModelCtrl) { iElm.on('mouseenter', function () { //情景1:直接通过js代码改变input的值,但ng-model绑定的变量的值未变 iElm.val(1); console.log(ngModelCtrl); //情景2:通过ng-model控制器设置绑定变量的值(而非手动在dom元素中输入),此时input中的值没有自动改变 ngModelCtrl.$setViewValue(11); console.log(ngModelCtrl); //其实$render可以model->view,也可以view->model. 以下两段代码也能提到外面. 赋值给$render只是因为$render是ngModelCtrl的属性方法, 方便在别处调用而无需重复代码段 ngModelCtrl.$render = function() { // 将ng-model的值设置给input元素: 即$render是将model的值渲染给view // iElm.val(ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue) ? '' : ngModelCtrl.$viewValue); // 将input元素的值,设置给model. ngModelCtrl.$setViewValue(iElm.val()); console.log(ngModelCtrl); }; //在修改model和view后执行$render() ngModelCtrl.$render(); console.log(ngModelCtrl); }) } } })
 
在使用angularJS时报错“Error: jqLite:nosel Unsupported Selector Lookup”:
原因:未引入jQuery
解决办法:必须在angularJS前引入JQuery
 

$compile:

这是个编译服务。编译一段HTML字符串或者DOM的模板, 产生一个将scope和模板连接到一起的函数。

eg:$compile(element)(s)    //将element元素编译,然后和作用域s关联,并返回该element.

 
依赖注入的服务可访问的问题:
已知framework模块依赖于atelierRouterConfig模块,framework模块中定义了mask服务。
那么atelierRouterConfig模块在定义taskListCtrl控制器时可以直接依赖注入服务mask吗?还是需要先让atelierRouterConfig模块依赖上framework模块,才能依赖注入服务framework?
在同一个模块()下注册的服务、控制器、指令等,是可以直接通过名字依赖注入的.
eg: 
var dependency = [
            "ng",
            "tiny",
            "ui.router",
            "hws",
            'tinyPlus', "commonDirective", //指令 "lazyloadDirective", //指令  frameworkConfig.name, atelierRouterConfig.name ]; var framework = angular.module("framework", dependency); //angular.module声明创建一个模块 framework.controller("serviceCtrl", serviceCtrl); framework.controller("menusCtrl", menusCtrl); framework.controller("modifyPasswordCtrl", modifyPasswordCtrl); framework.controller("resetPasswordCtrl", resetPasswordCtrl); //为模块声明创建服务,使用服务可通过依赖注入的方法注入到控制器或过滤器中 framework.service("mask", mask); framework.service("camel", http); framework.service("exception", exception); framework.service("storage", storage); framework.service("frameworkService", frameworkServ); framework.service("casService", casService); framework.service("utilService", utilService); framework.service("msgService", msgService); framework.service("localeService", localeService);
为什么有的函数直接就一个服务通过参数依赖注入了,或者说该函数为什么就能获取(访问)到该依赖?
framework模块中定义的服务、控制器间是可以直接通过名字获取该模块中的其他依赖服务的.
并且framework模块所依赖的tiny等模块中的服务, framework中也可以直接通过名字获取所依赖模块中注册的服务的.
由于framework模块依赖tiny模块,因此在index.html中,应先引入tiny.js再引入main.js. 
只要html中引入了模块对应的js文件,不同模块的js文件间就能直接通过模块名字符串来依赖.
 
ng-cloak:解决表达式闪的问题,或用ng-bind替换{{}}
 
修改ng-if或ng-show为true后,想通过DOM API获取指定id的element,发现获取不到:
解决办法:在将变量置为true后,执行$timeout回调函数内获取dom元素.(PS: js中的setTimeout需要在$scope.$apply()中调用才会同步对模型的修改)
$timeout和setTimeout的区别:
 
ng-repeat 中的 track by $index: https://www.cnblogs.com/xiongzuyan/p/5984626.html
<!-- 自定义index名称,可避免嵌套ng-repeat时,index名称发生冲突及覆盖 -->
        <div id="contentDiv" ng-repeat="(lineIdx, line) in contentList">
            <div class="lineDiv" id="" ng-repeat="(itemIdx, item) in line">
            </div>
        </div>
 
ng-repeat是重复当前div及内部内容,而非仅重复内部内容.
 
anjularJS绑定鼠标左键和右键事件:
 
//页面跳转前,执行的回调函数(比如: 页面跳转前解除window resize事件)
//默认$(window).resize函数在其他页面也会生效
$scope.$on("$destroy", function() {
 $(".sp-container").remove();
}); 
 
父js给tiModal传参问题:
参数传递方法:
    方法1:通过scope: $scope依赖注入,即可直接在modal控制器中直接使用$scope中的变量
    方法2:通过params:{}传入
两种方式对于Object而言,均传的引用;因此对Object的修改均会影响到父js;但对于数字等非Object变量,方法1仍可以修改其值并同步到父js,但方法2不能。
对话框选择的确定还是取消只能在Modal控制器中获取,想要根据选择状态来调用父js中的函数,可以将该函数定义成$scope的属性,然后依赖注入$scope.
 

$watch(watchFn,watchAction,deepWatch)

watchFn:angular表达式或函数的字符串

watchAction(newValue,oldValue,scope):watchFn发生变化会被调用

deepWatch:可选的布尔值命令检查被监控的对象的每个属性是否发生变化. 

$watch会返回一个函数,想要注销这个watch可以使用函数.

猜你喜欢

转载自www.cnblogs.com/luckyboylch/p/12330294.html
今日推荐