Angular1.X

服務(wù)

1.Constant
2.Value
3.Service
4.Factory
5.Provider
除了Constant,所有類型服務(wù)背后都通過Provider實(shí)現(xiàn)

angular.module('lulu.app').provider('greeting', function(){
  var _name = '66';
  this.setName = function(name){
    _name = name;
  };
  this.$get = function(){
    return _name;
  }
});
angular.module('lulu.app').controller('SomeCtrl', function($scope, greeting){
  $scope.message = greeting; //值為66
});
//provider可配置
angular.module('lulu.app').config(function(greetingProvider){
  greetingProvider.setName('lulu');
});

//value
angular.module('lulu.app').value('greeting', '66');

//service
angular.module('lulu.app').service('greeting', function(){
  this.say = function(name){
    return name;
  }
});
//等價(jià)于
angular.module('lulu.app').provider('greeting', function(){
  this.$get = function(){
    var Greeting = function(){
      this.say = function(name){
        return name;
      };
    };
    //service用new的方式創(chuàng)建
    return new Greeting();
  };
});

//factory
angular.module('lulu.app').factory('greeting', function(){
  return 66;
});
//等價(jià)于
angular.module("lulu.app").provider('greeting', function(){
  this.$get = function(){
    var greeting = function(){
      return 66;
    }

    return greeting();
  }
});

***service和factory區(qū)別在于內(nèi)部創(chuàng)建時(shí)一個(gè)是new一個(gè)直接返回

//constant
angular.module('lulu.app').constant('greeting', '66');

Constant時(shí)機(jī)非常早讼昆,可以在Config中使用

MVVM

View:專注顯示忿危,視圖模板
ViewModel:負(fù)責(zé)給View提供顯示數(shù)據(jù)久信,以及供View操作Model途徑冷冗,$scope對象充當(dāng)了這個(gè)角色
Model:領(lǐng)域?qū)ο笾ㄎ眩瑯I(yè)務(wù)相關(guān)數(shù)據(jù)
Controller:負(fù)責(zé)ViewModel對象初始化

Angular啟動(dòng)過程

1.瀏覽器下載HTML/CSS/Javascript
2.瀏覽器開始構(gòu)建DOM
3.Jquery初始化
4.Angular初始化:創(chuàng)建各種模塊若厚,在模塊中注冊各種Angular對象
5.Jquery啟動(dòng)
6.AngularI啟動(dòng)拦英,查找第一個(gè)帶有ng-app的節(jié)點(diǎn)
7.加載子模塊,關(guān)聯(lián)DOM和模塊测秸,使DOM變活(展示數(shù)據(jù)疤估,響應(yīng)事件)
8.啟動(dòng)子模塊灾常,執(zhí)行run回調(diào)
9.渲染頁面
10.數(shù)據(jù)綁定與digest循環(huán)

依賴注入DI

只要指出我需要哪些對象,讓后就會(huì)有人(框架)把這個(gè)對象給我

Javascript中實(shí)現(xiàn)DI
函數(shù)對象的toString()铃拇,返回函數(shù)源碼钞瀑,解析源碼參數(shù)

Angular中的DI
所有主要編程元素都要通過某種方式注冊
注冊表Module,Angular跨Controller共享數(shù)據(jù)或通訊慷荔,可以創(chuàng)建Service/Value/Constant分別注入仔戈,共享同一對象
provider通過$get函數(shù)注入,provider('test', function(/只能注入constant, provider/))
循環(huán)依賴不能使用依賴注入拧廊,可以在代碼內(nèi)部調(diào)用
var http = $injector.get('$http');

Digest

Angular將雙向綁定轉(zhuǎn)換成一堆watch监徘,遞歸檢查watch表達(dá)式結(jié)果是否改變,等到Model值不再變化吧碾,不會(huì)觸發(fā)watcher函數(shù)凰盔,一個(gè)完整的digest循環(huán)結(jié)束
Angular拓展了瀏覽器事件模型,建立了自己上下文倦春,ngClick, ngChange會(huì)將瀏覽器事件轉(zhuǎn)化為$scope的響應(yīng)函數(shù)户敬,響應(yīng)函數(shù)中改變Model,觸發(fā)臟檢查機(jī)制睁本,并不存在定時(shí)的臟檢查

遍歷一遍所有watcher函數(shù)稱為一輪臟檢查尿庐,執(zhí)行完一輪,如果任何一個(gè)watcher監(jiān)聽值改變呢堰,再進(jìn)行一輪臟檢查抄瑟,直到所有watchers函數(shù)都報(bào)告值不變了,$digest循環(huán)結(jié)束枉疼,才能把變化更新到DOM

何時(shí)進(jìn)入臟檢查皮假?
每一個(gè)進(jìn)入Angular上下文環(huán)境的事件,都會(huì)執(zhí)行一次$digest

$watch函數(shù)返回一個(gè)反注冊函數(shù)
$scope.$apply(function(){}); //手動(dòng)觸發(fā)digest循環(huán)

$rootScopt是所有$scope基礎(chǔ)

指令生命周期

Inject, Compile, Controller加載骂维, pre-link, post-link

angular.module('lulu.app').directive('test', function(){
  console.log('Inject'); //只發(fā)生一次

  return {
    restrict:'EA',
    transclude:true,
    replace:true,
    template:'<div>{{count}}</div>',
    scope:{
      count:'='
    },
    //每個(gè)指令實(shí)例化時(shí)執(zhí)行一次惹资,傳入elm還未被link,無法訪問$scope
    compile:function(elm, iAttrs){
      console.log('compile' + iAttrs.count);

      //controll初始化$scope后航闺,進(jìn)入正式解析過程褪测,對每個(gè)實(shí)例只執(zhí)行一次
      return {
        //從父節(jié)點(diǎn)到子節(jié)點(diǎn)觸發(fā),子節(jié)點(diǎn)DOM不穩(wěn)定潦刃,不適合在其上加DOM監(jiān)聽
        pre:function(scope, elm, iAttrs){
          console.log('pre-link' + iAttrs.count + ' scope' + scope.count);
        },
        //從子節(jié)點(diǎn)到父節(jié)點(diǎn)觸發(fā)
        post:function(scope, elm, iAttrs){
          console.log('post-link' + iAttrs.count + ' scope' + scope.count);
        }
      };
    },
    //初始化$scope
    controller:function($scope){
      console.log('controller');
    }
  };
});

$observe監(jiān)聽DOM中屬性值變化
$watch監(jiān)聽scope屬性變化

指令scope綁定策略
@綁定{{}}侮措,單向綁定,返回String
=綁定一個(gè)對象福铅,雙向綁定萝毛,返回Object
&綁定一個(gè)函數(shù)

指令scope作用域
false:直接使用父級scope
true:繼承父級scope,創(chuàng)建后copy父scope,與父級無關(guān)
{}:創(chuàng)建一個(gè)新的隔離scope

controller as vm

好處:
1.$scope注入不再是必須的(除非用到$watch, $emit, $on等)
2.避免this指針坑
3.避免原型鏈繼承對于值類型的坑(視圖模板所有字段都限制于vm別名應(yīng)用的屬性,會(huì)導(dǎo)致整個(gè)頁面刷新)

<div>{{vm.name}}</div>
(function(){
  angular.module('lulu.app')
  .controller('HomeCtrl', HomeCtrl);
  
  function HomeCtrl(){
    var vm = this;
    vm.name = 66;
  };
});

性能

1.移除不必要的$watch
2.::語法滑黔,實(shí)現(xiàn)one-time綁定
3.滾屏加載數(shù)據(jù)笆包,分部加載數(shù)據(jù)
4.$compileProvider.debugInfoEnabled(true);
5.慎用filter,$digest中略荡,filter至少執(zhí)行2次庵佣,應(yīng)避免filter執(zhí)行耗時(shí)操作,或在controller中預(yù)先處理完數(shù)據(jù)在視圖中直接綁定
6.ng-repeat添加track by可以避免$scope.tasks = data;移除所有DOM后重新渲染汛兜,track by可以對應(yīng)原DOM進(jìn)行更新
angular不會(huì)大范圍更新DOM巴粪,每次更新區(qū)域小,超過2000個(gè)watcher需要好好考慮優(yōu)化

攔截器(AOP機(jī)制)

實(shí)現(xiàn)Ajax請求攔截切入

防閃爍

{{}}替換為ng-bind
ngCloak通過樣式切換實(shí)現(xiàn)隱藏顯示

父子$scope嵌套

默認(rèn)使用原型鏈繼承來至父級的$scope

<div ng-controller='ParentCtrl'>
  {{greeting}}
  <input type="text" ng-model="greet"/>
  <div ng-controller='ChildCtrl'>
    {{greeting}}
    <input type="text" ng-model="greet"/>
  </div>
</div>
//ParentCtrl
$scope.greeting = "66";

導(dǎo)致的問題:
1.開始全部顯示66
2.改變父input值粥谬,全部同步數(shù)據(jù)
3.改變子input值肛根,子組件同步數(shù)據(jù),父組件不能同步漏策,再改變父input派哲,子組件也不會(huì)同步數(shù)據(jù)
原因:
子組件開始自己沒有g(shù)reeting,會(huì)向上查找使用父的greeting屬性
當(dāng)子組件input值變更,子組件創(chuàng)建自己的greeting屬性掺喻,后就與父級greeting屬性隔離
使用controller as vm語法綁定vm.greeting可避免

路由

(function(){
  angular.module('lulu.routes')
  .config(routesConfig);

  function routesConfig($stateProvide, $urlRouterProvider){
    $stateProvide
      .state('book', {
        cache:true,
        url:'/book',
        templateUrl:'templates/product/book.html',
        controller: 'BookCtrl',
        controllerAs: 'vm',
        resolve:{
          //返回一個(gè)promise芭届,如promise狀態(tài)reject,會(huì)擋住路由
          //如不是promise, 對象會(huì)被注入到controller
          loggedIn:function(mkAuth){
            return mkAuth.checkLoggedIn();
          }
        }
      })
  };
});

ng-show/ng-hide/ng-if

ng-show/ng-hide通過css的display實(shí)現(xiàn)隱藏顯示感耙,ng-if通過移除添加DOM實(shí)現(xiàn)

$rootScope和$scope

$rootScope是頁面所有$scope父級
1.angular解析ng-app創(chuàng)建$rootScope
2.解析{{}}為變量
3.解析ng-controller創(chuàng)建$scope

{{}}原理

使用$interpolation服務(wù)查看文本節(jié)點(diǎn)是否有{{}}(插補(bǔ)標(biāo)記)褂乍,有則注冊watches,成為digest檢查的一部分

$timeout.cancel();

ng-repeat迭代

track by $index解決綁定數(shù)據(jù)相同(唯一表示數(shù)據(jù)和DOM關(guān)系)

頁面{{}}即硼,ng-click中可以用js原生方法么逃片?

不能,因?yàn)?scope上下文不存在那些原生方法只酥,如用as vm模式可以吧?

SPA缺點(diǎn)

1.SEO题诵,可通過Prerender解決部分
2.前進(jìn),后退等要程序管理

SPA SEO解決方案:
1.接入prerender.io等預(yù)渲染服務(wù)
2.騰出一臺(tái)服務(wù)器搭建phantomjs搞預(yù)渲染
3.將爬蟲請求引導(dǎo)到后臺(tái)定時(shí)生成或抓取的靜態(tài)HTML頁
4.SSR

項(xiàng)目

微信登錄授權(quán)

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<a >微信登錄</a>
function freshConfig() {
    var url = $location.absUrl();
    url = url.split('#')[0];
    //傳入當(dāng)前url
    weixin.jssdkConfig({url: url}).then(function (data) {
        if (data.code == 0) {
          //配置wx
          wx.config({
            debug: false, // 開啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來层皱,若要查看傳入的參數(shù)性锭,可以在pc端打開,參數(shù)信息會(huì)通過log打出叫胖,僅在pc端時(shí)才會(huì)打印草冈。
            appId: mkGlobalVal.weixin_appid, // 必填,公眾號的唯一標(biāo)識
            timestamp: parseInt(data.result.timestamp), // 必填瓮增,生成簽名的時(shí)間戳
            nonceStr: data.result.noncestr, // 必填怎棱,生成簽名的隨機(jī)串
            signature: data.result.signature,// 必填,簽名绷跑,見附錄1
            jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone'] // 必填拳恋,需要使用的JS接口列表,所有JS接口列表見附錄2
              });
            }
          });
};

function onShare(share) {
    //分享到朋友圈
    wx.onMenuShareTimeline(share);
    //分享給朋友
    wx.onMenuShareAppMessage(share);
    //分享到QQ
    wx.onMenuShareQQ(share);
    //分享到騰訊微博
    wx.onMenuShareWeibo(share);
    //分享到QQ空間
    wx.onMenuShareQZone(share);
}

//微信支付
if ($scope.mkTools.agentIsWeichat) {
    orderInfo = {
        "openid": $scope.currentUser.authData.weixin.openid,
        "no": data.no,
        "total_fee": data.total_fee,
        "body": data.product_snapshot.title
      };
          mkPayTools.weixinPay(orderInfo).then(angular.noop, error);
}
//創(chuàng)建訂單成功后砸捏,呼出微信支付界面
function weixinBridge(data, defer) {
        function onBridgeReady() {
          WeixinJSBridge.invoke('getBrandWCPayRequest', data, function (res) {
            //支付成功
            if (res.err_msg == "get_brand_wcpay_request:ok") {
              defer.resolve();
              window.location.href = "/#/payresult";
            }
            else {
              defer.reject();
            }
          });
        };

        if (typeof WeixinJSBridge == "undefined") {
          if (document.addEventListener) {
            document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
          } else if (document.attachEvent) {
            document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
            document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
          }
        }
        else {
          onBridgeReady();
        }
      };

      return defer.promise;
    };
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谬运,一起剝皮案震驚了整個(gè)濱河市隙赁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梆暖,老刑警劉巖伞访,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異轰驳,居然都是意外死亡厚掷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門级解,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冒黑,“玉大人,你說我怎么就攤上這事勤哗÷盏” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵俺陋,是天一觀的道長豁延。 經(jīng)常有香客問我,道長腊状,這世上最難降的妖魔是什么诱咏? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缴挖,結(jié)果婚禮上袋狞,老公的妹妹穿的比我還像新娘。我一直安慰自己映屋,他們只是感情好苟鸯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棚点,像睡著了一般早处。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瘫析,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天砌梆,我揣著相機(jī)與錄音,去河邊找鬼贬循。 笑死咸包,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的杖虾。 我是一名探鬼主播烂瘫,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奇适!你這毒婦竟也來了坟比?” 一聲冷哼從身側(cè)響起芦鳍,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎温算,沒想到半個(gè)月后怜校,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體间影,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡注竿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魂贬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巩割。...
    茶點(diǎn)故事閱讀 39,926評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖付燥,靈堂內(nèi)的尸體忽然破棺而出宣谈,到底是詐尸還是另有隱情,我是刑警寧澤键科,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布闻丑,位于F島的核電站,受9級特大地震影響勋颖,放射性物質(zhì)發(fā)生泄漏嗦嗡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一饭玲、第九天 我趴在偏房一處隱蔽的房頂上張望侥祭。 院中可真熱鬧,春花似錦茄厘、人聲如沸矮冬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胎署。三九已至,卻和暖如春窑滞,著一層夾襖步出監(jiān)牢的瞬間琼牧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工葛假, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留障陶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓聊训,卻偏偏與公主長得像抱究,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子带斑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Angular面試題 一鼓寺、ng-show/ng-hide與ng-if的區(qū)別勋拟? 第一點(diǎn)區(qū)別是,ng-if在后面表達(dá)式...
    w_zhuan閱讀 5,527評論 0 26
  • AngularJS是什么妈候?AngularJs(后面就簡稱ng了)是一個(gè)用于設(shè)計(jì)動(dòng)態(tài)web應(yīng)用的結(jié)構(gòu)框架敢靡。首先,它是...
    200813閱讀 1,606評論 0 3
  • 1苦银、angularjs的幾大特性是什么啸胧? 雙向數(shù)據(jù)綁定、依賴注入幔虏、模板纺念、指令、MVC/MVVM 2想括、列舉幾種常見的...
    2e9a10d418ab閱讀 1,271評論 0 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理陷谱,服務(wù)發(fā)現(xiàn),斷路器瑟蜈,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 《乖铺根,摸摸頭》-大冰 其實(shí)宪躯,剛開始看到這本書時(shí)我是拒絕讀的,因?yàn)槲抑酪亩迹@會(huì)是一本雞湯書眷唉。但是,我又覺得囤官,還沒讀一...
    千山萬水閱讀 562評論 4 6