中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定-創(chuàng)新互聯(lián)

Angularjs1.X進(jìn)階筆記(1)—兩種不同的雙向數(shù)據(jù)綁定

聊聊 Angularjs1.x中那些活見(jiàn)鬼的事情。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、網(wǎng)頁(yè)空間、營(yíng)銷(xiāo)軟件、網(wǎng)站建設(shè)、輝縣網(wǎng)站維護(hù)、網(wǎng)站推廣。

[TOC]

一. html與Controller中的雙向數(shù)據(jù)綁定

html-Controller的雙向數(shù)據(jù)綁定,在開(kāi)發(fā)中非常常見(jiàn),也是Angularjs1.x的宣傳點(diǎn)之一,使用中并沒(méi)有太多問(wèn)題。

1.1數(shù)據(jù)從html流向controller

也就是從視圖層流向模型層,原生html中需要使用表單元素(例如input標(biāo)簽)來(lái)收集用戶輸入信息,Angularjs中通過(guò)在表單元素上使用ng-model標(biāo)簽,當(dāng)用戶輸入信息時(shí),同步將用戶輸入的信息賦值給controller中的變量:

<body ng-app="myApp">
   <div id="main" ng-controller="myCtrl">
       <p>改變輸出值:</p>
       <input type="text" ng-model="testInfo.content" ng-change="showInput()">
   </div>
 <script src="./angular.min.js"></script>
 <script>
    angular.module('myApp',[])
    .controller('myCtrl',['$scope',function($scope){
       $scope.showInput = function() {
          console.log($scope.testInfo.content);
        }
    }]);
 </script>
</body>

在頁(yè)面上輸入1234567即可看到,每次在頁(yè)面輸入數(shù)字后,控制臺(tái)輸出的$scope,testInfo.content的值都和頁(yè)面保持一致:

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

1.2 數(shù)據(jù)從controller流向html

也就是從模型層流向數(shù)據(jù)層,當(dāng)controller中的數(shù)據(jù)模型變量發(fā)生變化后,Angularjs又會(huì)根據(jù)數(shù)據(jù)模型的值去改變ng-model指令綁定的表單元素的值,使用ng-bind指令也可以被動(dòng)獲得來(lái)自controller的數(shù)據(jù)流。

我們編寫(xiě)如下demo進(jìn)行測(cè)試:

<body ng-app="myApp">
    <div id="main" ng-controller="myCtrl">
        <button ng-click="add()">+1</button>
        <p>改變輸出值:</p>
        <input type="text" ng-model="testInfo.content">
        <p>使用ng-bind綁定的標(biāo)簽:</p>
        <p ng-bind="testInfo.content"></p>
    </div>
    <script src="./angular.min.js"></script>
    <script>
    angular.module('myApp', [])
        .controller('myCtrl', ['$scope', function($scope) {
            //初始化
            $scope.testInfo = {
                content: 0
            }

            $scope.add = function () {
               $scope.testInfo.content += 1;
               console.log($scope.testInfo.content);
            }
        }]);
    </script>
</body>

demo中,每次點(diǎn)擊+1按鈕,$scope.testInfo.content的值會(huì)增加1,我們可以看到頁(yè)面上的結(jié)果:

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

1.3 你丫倒是刷視圖啊

來(lái)看看第一個(gè)活見(jiàn)鬼的例子,demo跟上面很類似,只是將鼠標(biāo)點(diǎn)擊觸發(fā)的方式改成了定時(shí)器自動(dòng)觸發(fā)

<body ng-app="myApp">
    <div id="main" ng-controller="myCtrl">
        <button ng-click="add()">+1</button>
        <p>改變輸出值:</p>
        <input type="text" ng-model="testInfo.content">
        <p>使用ng-bind綁定的標(biāo)簽:</p>
        <p ng-bind="testInfo.content"></p>
    </div>
    <script src="./angular.min.js"></script>
    <script>
    angular.module('myApp', [])
        .controller('myCtrl', ['$scope', function($scope) {
            //初始化
            $scope.testInfo = {
                content: 0
            }

            //定時(shí)自增
            setInterval(function () {
              $scope.testInfo.content += 1;
              console.log('$scope.testInfo.content的值現(xiàn)在是:',$scope.testInfo.content);
            },1000)
        }]);
    </script>
</body>

你會(huì)活見(jiàn)鬼地發(fā)現(xiàn),數(shù)據(jù)模型一直在變,但是頁(yè)面卻沒(méi)有刷新:

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

這里就是 Angularjs1.X雙向數(shù)據(jù)綁定中的第一個(gè)坑 ,你會(huì)發(fā)現(xiàn)$scope上綁定的數(shù)據(jù)模型html中顯示的內(nèi)容有時(shí)候并不是實(shí)時(shí)關(guān)聯(lián)的。這其實(shí)和Angularjs1.X的執(zhí)行機(jī)制有關(guān)系。

如果我們自己來(lái)考慮,javascript中有一個(gè)變量的值發(fā)生了變化,現(xiàn)在要將這個(gè)值同步到html頁(yè)面上,需要怎么做呢?我們需要獲取到這個(gè)DOM元素,然后改變它的innerHTML屬性,如果是表單元素就修改value。其實(shí)Angularjs也是這樣做的,只不過(guò)使用了自己的封裝的方法——$apply()。那么此處的問(wèn)題其實(shí)就在于,在setInterval的回調(diào)函數(shù)中去修改數(shù)據(jù)模型的值時(shí),沒(méi)有觸發(fā)$apply()方法來(lái)更新視圖,而通過(guò)調(diào)用Angularjs封裝的ng-*方法(例如ng-click點(diǎn)擊方法)來(lái)修改視圖模型時(shí),會(huì)自動(dòng)觸發(fā)$apply()方法,視圖也就同步刷新了。

  • 解決方案1

    使用Angularjs封裝過(guò)的$interval服務(wù)來(lái)實(shí)現(xiàn)定時(shí)任務(wù),感興趣的讀者可以自己看一下Angularjs源碼中$intervalProvider的部分,就會(huì)發(fā)現(xiàn)在方法最后的地方調(diào)用了$rootScope.$apply()。

  • 解決方案2

    如果依然使用javascript原生的定時(shí)方法,那么則需要在修改完視圖的數(shù)據(jù)模型后,手動(dòng)調(diào)用$scope.$apply()方法來(lái)將數(shù)據(jù)模型的變動(dòng)同步到html頁(yè)面中。

二. Controller與Directive中的雙向數(shù)據(jù)綁定

除了controller與html中的雙向綁定,Angularjs中還有另一個(gè)雙向數(shù)據(jù)綁定,那就是controller與directive之間的綁定。綁定的形式有很多種,我們先來(lái)看一下最常見(jiàn)的雙向綁定。

2.1 directive中的雙向數(shù)據(jù)綁定

在設(shè)定自定義指令的scope參數(shù)時(shí),將屬性的值設(shè)置為=就可以實(shí)現(xiàn)雙向數(shù)據(jù)綁定,這里API的解釋是:

父級(jí)controller中的指定變量會(huì)與自定義指令link函數(shù)中的變量相互影響。

下面的實(shí)例中,我們將看看controller中的數(shù)據(jù)模型$scope.testInfo.content的值與自定義指令中scope.pagination如何相互影響,是否如定義所說(shuō)這里的綁定真的是雙向的。示例界面如下(demo源碼請(qǐng)見(jiàn)附件demo.html文件):

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

  • 每次點(diǎn)擊+1按鈕,Scope.testInfo.content的值都會(huì)增加1
  • 每次點(diǎn)擊show $scope.testInfo,控制臺(tái)都會(huì)打印出$scope.testInfo的值
  • 每次點(diǎn)擊標(biāo)簽上的數(shù)字,則會(huì)打印出自定義指令中scope.pagination的值,并將該值進(jìn)行自增

接下來(lái)的測(cè)試操作,我們將按照如下的流程進(jìn)行:

  1. 點(diǎn)擊5次+1按鈕,再點(diǎn)擊5次數(shù)字標(biāo)簽
  2. 點(diǎn)擊show $scope.testInfo按鈕
2.2 你丫怎么又不刷新了

隨著上一節(jié)的操作步驟,我們一起來(lái)見(jiàn)證雙向數(shù)據(jù)綁定中又一次鬧鬼事件:

  • 點(diǎn)擊5次+1按鈕,再點(diǎn)擊5次數(shù)字標(biāo)簽

    結(jié)果為:

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

我們看到,第一次點(diǎn)擊數(shù)字標(biāo)簽時(shí),控制臺(tái)打出了link函數(shù)中scope.pagination的值為5,這說(shuō)明$scope.testInfo.content的值被傳遞給了自定義指令中的scope.pagination,也就是說(shuō)數(shù)據(jù)從controller流向了directive。而當(dāng)我們?cè)冱c(diǎn)擊4次數(shù)字標(biāo)簽(一共點(diǎn)了5次)后,從控制臺(tái)可以看出,scope.pagination的值已經(jīng)成為10,而頁(yè)面上使用ng-bind指令獲取到的結(jié)果卻依舊是5。也就是說(shuō),數(shù)據(jù)從沒(méi)有從directive流向controller。是不是有一種被騙的感覺(jué)?別著急,接著看。

  • 點(diǎn)擊show $scope.testInfo按鈕

    結(jié)果為:

Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定

當(dāng)我們點(diǎn)擊show $scope.testInfo時(shí),控制臺(tái)打印出了$scope.testInfo.content的值為5,這下證據(jù)坐實(shí)了,明明說(shuō)好的雙向數(shù)據(jù)綁定,然而當(dāng)自定義指令中的scope.pagination改變時(shí),$scope.testInfo.content并沒(méi)有跟著一起改變。But!?。?!我們會(huì)發(fā)現(xiàn),這個(gè)show $scope.testInfo點(diǎn)下去以后,頁(yè)面上通過(guò)ng-bind綁定的值卻變成了10。也就是說(shuō),數(shù)據(jù)又從directive流回了controller。

官方建議使用$watch方法來(lái)追蹤scope中的變量,而當(dāng)我們這樣做時(shí),會(huì)發(fā)現(xiàn)$watch函數(shù)僅能追蹤到那些通過(guò)修改controller中的數(shù)據(jù)模型而影響link函數(shù)中變量的行為并更新視圖。

這里就是 Angularjs1.X雙向數(shù)據(jù)綁定中的第二個(gè)坑,controller和directive中所謂的雙向數(shù)據(jù)綁定,并不能追蹤指定變量的所有變化,而且不是同步完成的。

其實(shí)這里的問(wèn)題仍然和Angularjs的運(yùn)行機(jī)制有關(guān),解決方案如下:

  • 解決方案1

    使用自定義指令的templateUrl屬性替換當(dāng)前指令的模板,使用ng-click指令來(lái)綁定一個(gè)點(diǎn)擊響應(yīng)函數(shù),在響應(yīng)函數(shù)中改變scope.piganation的值。

  • 解決方案2

    在手動(dòng)綁定的監(jiān)聽(tīng)回調(diào)中,修改自定義指令作用域內(nèi)的變量后,使用scope.$emit( )方法通知其父級(jí)controller,并在controller中使用$scope.$on( )方法監(jiān)聽(tīng)同名事件,并修改對(duì)應(yīng)的數(shù)據(jù)模型的值。

  • 解決方案3

    每當(dāng)改變自定義指令中的變量值后,調(diào)用scope.$apply()方法,將directive中的變量值同步至controller的數(shù)據(jù)模型以及頁(yè)面。

三.原理和實(shí)戰(zhàn)總結(jié)

3.1 Angularjs中雙向數(shù)據(jù)綁定的基本原理

Angularjs中的雙向數(shù)據(jù)綁定,是通過(guò)一種叫做*"臟循環(huán)檢查(dirty-checking)"的機(jī)制實(shí)現(xiàn)的。

其基本過(guò)程是這樣的,每當(dāng)我們使用ng-modelng-bind指令將數(shù)據(jù)模型中的某個(gè)變量值和html頁(yè)面上某個(gè)標(biāo)簽的內(nèi)容聯(lián)系起來(lái)時(shí),Angular就會(huì)把這些變量放進(jìn)一個(gè)WatchCollection的集合中,并自動(dòng)幫我們來(lái)監(jiān)控這些變量。每當(dāng)WatchCollection中有變量出現(xiàn)變動(dòng)時(shí),Angular就會(huì)遍歷WatchCollection來(lái)查看是否有其他監(jiān)控中的變量也被影響,每當(dāng)有一個(gè)變量被影響,Angular都會(huì)在遍歷后再進(jìn)行一次遍歷,直到某一次遍歷后WatchCollection中的變量都沒(méi)有變化,則Angular會(huì)認(rèn)為當(dāng)前的改動(dòng)已經(jīng)穩(wěn)定了,然后才會(huì)將數(shù)據(jù)模型的變化同步到DOM元素上去,也就實(shí)現(xiàn)了數(shù)據(jù)綁定。

我們可以把WatchCollection理解為當(dāng)前頁(yè)面的一種抽象,其中包含著頁(yè)面上所有有可能發(fā)生變化的部分。

3.2 雙向數(shù)據(jù)綁定的實(shí)踐經(jīng)驗(yàn)

想要在Angularjs項(xiàng)目中更加穩(wěn)定地使用雙向數(shù)據(jù)綁定,筆者的建議是:

Angularjs項(xiàng)目中,盡可能地使用Angular告訴你的方式去編寫(xiě)所希望實(shí)現(xiàn)的功能。

我們可以回顧一下上面在使用雙向數(shù)據(jù)綁定發(fā)生異常時(shí)的場(chǎng)景:

  • 使用了原生的定時(shí)器(Angular中你應(yīng)該使用$interval,$timeout服務(wù))
  • 用類原生方法(bind)為元素添加事件監(jiān)聽(tīng)器,并在回調(diào)函數(shù)中修改了變量的值(Angular中,你應(yīng)該使用ng-click來(lái)實(shí)現(xiàn)點(diǎn)擊事件的監(jiān)聽(tīng))
  • ...

你會(huì)發(fā)現(xiàn),每當(dāng)自己沒(méi)有按照Angular的方式去編寫(xiě)代碼,或者沒(méi)有按照一個(gè)模塊設(shè)計(jì)的初衷去使用它時(shí),就無(wú)法確切地得到期望的結(jié)果。這是很容易理解的,如果你沒(méi)有按照Angular要求的方式書(shū)寫(xiě)代碼,憑什么期望它對(duì)你的代碼做出100%正確的回應(yīng)呢?至于上述兩種數(shù)據(jù)綁定中出現(xiàn)問(wèn)題的解決方案,上文已經(jīng)有所提及,此處不再贅述。

許多人都聽(tīng)說(shuō)過(guò)"盡量不要在controller中操作DOM"這句話,實(shí)際上它并不意味著你在controller中操作DOM會(huì)導(dǎo)致程序報(bào)錯(cuò),而是在說(shuō)如果你同時(shí)使用jQueryAngular兩套系統(tǒng)來(lái)管理自己的代碼,但又沒(méi)有按照官方指定的方式來(lái)規(guī)避它們之間的沖突,那代碼很可能會(huì)變得不穩(wěn)定。想想當(dāng)年騰訊電腦管家360安全衛(wèi)士將你的電腦卡死的場(chǎng)景,你就明白這樣做的結(jié)果了。

四. 小結(jié)——所謂高手

筆者曾經(jīng)看過(guò)這樣一段話,覺(jué)得深有感觸:

所謂高手,是指那些熟知套路創(chuàng)意無(wú)窮的人。而高手之間的較量,歸根結(jié)底都是基本功的比拼。

愿有朝一日,你也能成為高手。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

分享題目:Angularjs進(jìn)階筆記(1)不同類型的雙向數(shù)據(jù)綁定-創(chuàng)新互聯(lián)
鏈接地址:http://www.rwnh.cn/article32/csehsc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、面包屑導(dǎo)航營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、Google網(wǎng)站排名、動(dòng)態(tài)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司
沂源县| 晴隆县| 浦县| 鹤庆县| 双鸭山市| 永丰县| 安图县| 沙洋县| 苍溪县| 锡林浩特市| 汽车| 高台县| 定兴县| 若羌县| 皮山县| 元朗区| 广宗县| 西安市| 安丘市| 新源县| 和政县| 山丹县| 翁源县| 河东区| 容城县| 潮州市| 仪陇县| 平乡县| 唐河县| 侯马市| 化州市| 江陵县| 潮安县| 安化县| 加查县| 珠海市| 甘洛县| 安康市| 湟中县| 营口市| 伊宁市|