在angular1中自定義directive時(shí)數(shù)據(jù)顯示不同步問(wèn)題的分析和解決

在angular1項(xiàng)目中充包,有的時(shí)候我們需要寫(xiě)自定義directive來(lái)完成某些應(yīng)用邏輯呛梆,但是如果你有過(guò)一些的angular1項(xiàng)目的開(kāi)發(fā)經(jīng)驗(yàn)杭抠,肯定會(huì)因?yàn)橐恍┠涿顢?shù)據(jù)雙向綁定羊始,回調(diào)函數(shù)無(wú)法調(diào)用執(zhí)行等問(wèn)題谱俭,困擾過(guò)。下面是一個(gè)簡(jiǎn)單的案例啄骇。

問(wèn)題引出

這里我們寫(xiě)一個(gè)簡(jiǎn)單的directive來(lái)說(shuō)明問(wèn)題痴鳄。

directive.js


angular.module('app.directive')
.directive('ayTest',function(){
    return {
        restrict: 'EA',
        scope: {
            name:'='
        },
        template:`
            <div class="padding mystyle">
                {{vm.name}}
            </div>
        `,
        controller:function($scope){
            var vm = $scope.vm = {};
            vm.name = $scope.name;

        }
    }

});

A.controller.js

    var vm = $scope.vm = {};
    vm.name = 'Tom1';
    $timeout(function(){
        vm.name = 'Tom2';
    },1000);
    $timeout(function(){
        vm.name = 'Tom3';
    },2000);

A.html

   <ay-test name="vm.name"></ay-test>

這個(gè)directive可以實(shí)現(xiàn)以我們自己的格式展示‘name’的功能,我們可以通過(guò)在template中填寫(xiě)自己獨(dú)有的style或者嵌套div來(lái)完善name展示模塊缸夹。

在這我們希望name能夠?qū)崿F(xiàn)雙向綁定痪寻,即當(dāng)在A頁(yè)面中name值發(fā)生變化的時(shí)候,directive也自動(dòng)獲得更改虽惭。

但是橡类,在這里并不能實(shí)現(xiàn)這個(gè)功能,當(dāng)name顯示為Tom1之后趟妥,就不會(huì)再變化了。

為什么會(huì)這樣呢佣蓉?

我們都知道自定義directive時(shí)披摄,有3個(gè)綁定符號(hào),分別是

  • @ 單向綁定屬性值
  • = 雙向綁定屬性
  • & 綁定用戶(hù)函數(shù)

這里為了實(shí)現(xiàn)信息的雙向綁定勇凭,已經(jīng)使用了=疚膊,為什么還無(wú)法完成雙向綁定呢?對(duì)于大神們虾标,當(dāng)然能一眼看出問(wèn)題的所在寓盗,但小白可能會(huì)摸索比較長(zhǎng)的時(shí)間~~~~

問(wèn)題出在vm.name = $scope.name;這句代碼上。因?yàn)閚ame是一個(gè)基本字符串璧函,賦值時(shí)傀蚌,相當(dāng)于對(duì)vm.name創(chuàng)建了一個(gè)新值,并賦值為$scope.name的值蘸吓。這樣善炫,雖然controller中的$scope.name和頁(yè)面上的{{name}}仍存在雙向綁定,但是和我們的vm.name卻無(wú)任何關(guān)系了库继。

我們應(yīng)該還知道下面的這個(gè)問(wèn)題:

//controller.js
$socpe.username = 'Mary';
//B.html
<input ng-model='username' />

如果你按照上面的方式來(lái)編碼箩艺,十有八九會(huì)出現(xiàn)意外情況。

出現(xiàn)這樣錯(cuò)誤的根本原因宪萄,其實(shí)還是對(duì)JavaScript變量的值訪問(wèn)艺谆、引用訪問(wèn),開(kāi)發(fā)中的值傳遞拜英、引用傳遞沒(méi)有理解清楚静汤。下面說(shuō)一些這方面的問(wèn)題。

Js基本類(lèi)型、值傳遞

下面是筆者摘自《JavaScript高級(jí)程序設(shè)計(jì)》中的幾段話(huà)撒妈,讀者可以參照理解恢暖。這里并不是筆者自己懶,而書(shū)中的表達(dá)更準(zhǔn)確狰右,而且也很容易理解~~(如果你說(shuō)不知道這本書(shū)杰捂,推薦快去讀一下,如果你做Js相關(guān)開(kāi)發(fā)棋蚌,會(huì)讓你受益匪淺嫁佳,我能給你電子版,聯(lián)系hao5743@163.com )

5種基本數(shù)據(jù)類(lèi)型:Undefined谷暮、Null蒿往、Boolean、Number和String湿弦,5種基本數(shù)據(jù)類(lèi)型是按值訪問(wèn)的瓤漏,因?yàn)榭梢圆僮鞅4嬖谧兞恐械膶?shí)際的值。

引用類(lèi)型的值是保存在內(nèi)存中的對(duì)象颊埃。于其他語(yǔ)言不同蔬充,JavaScript不允許直接訪問(wèn)內(nèi)存中的位置,也就是說(shuō)不能直接操作對(duì)象的內(nèi)存空間班利。在操作對(duì)象時(shí)饥漫,實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。引用類(lèi)型的值是按引用訪問(wèn)的罗标。

--參見(jiàn)《JavaScript高級(jí)程序設(shè)計(jì)》P69 4.1 基本類(lèi)型和引用類(lèi)型的值

如果從一個(gè)變量向另一個(gè)變量復(fù)制基本類(lèi)型的值庸队,會(huì)在變量對(duì)象上創(chuàng)建一個(gè)新值,然后把該值復(fù)制到為新變量分配的位置上闯割。

--參見(jiàn)《JavaScript高級(jí)程序設(shè)計(jì)》P69 4.1.2 復(fù)制變量值

ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的彻消。也就是說(shuō),把函數(shù)外部的值賦值給函數(shù)內(nèi)部的參數(shù)宙拉,就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣证膨。基本類(lèi)型值的傳遞如同基本類(lèi)型變量的復(fù)制一樣鼓黔,二引用類(lèi)型值的傳遞央勒,則如同引用類(lèi)型變量的復(fù)制一樣。有不少開(kāi)發(fā)人員在這一點(diǎn)可能會(huì)感到困惑澳化,因?yàn)樵L問(wèn)變量有按值和按引用兩種方式崔步,而參數(shù)只能按值傳遞。

--參見(jiàn)《JavaScript高級(jí)程序設(shè)計(jì)》P70 4.1.3 傳遞參數(shù)

解決方案

理解了上面的話(huà)缎谷,那么你就能輕易用不同的方案解決這個(gè)問(wèn)題了井濒。

方案1 直接使用$scope.name展示數(shù)據(jù)

directive.js


angular.module('app.directive')
.directive('ayTest',function(){
    return {
        restrict: 'EA',
        scope: {
            name:'='
        },
        //這里直接使用name灶似,不再使用vm.name
        template:`
            <div class="padding mystyle">
                {{name}}
            </div>
        `,
        controller:function($scope){
            var vm = $scope.vm = {};

        }
    }

});

不再使用vm的方式,而是直接綁定到頁(yè)面瑞你,可以解決問(wèn)題酪惭。

方案2 使用引用類(lèi)型打包基本類(lèi)型再傳遞

如果,你在angular1開(kāi)發(fā)中者甲,一直遵循了好的實(shí)踐春感,那么有可能vm.name你可能已經(jīng)使用習(xí)慣了。也許你會(huì)問(wèn)虏缸,如果我還想使用vm.name的方式鲫懒,我想遵循官方給出的最佳實(shí)踐,怎么解決這個(gè)問(wèn)題呢刽辙?

(什么是最佳實(shí)踐窥岩?如果你是angular開(kāi)發(fā)者,而還不知道的話(huà)宰缤,那么一定要去讀讀颂翼,原版在這里,英文差的看這里

當(dāng)然有方法啦慨灭!看下面
controller.js

    var vm = $scope.vm = {};
    vm.name = {};
    //將數(shù)據(jù)封裝到到內(nèi)部屬性data上
    vm.name.data = 'Tom1';
    $timeout(function(){
        vm.name.data = 'Tom2';
    },1000);
    $timeout(function(){
        vm.name.data = 'Tom3';
    },2000);

A.html

    <ay-test name="vm.name"></ay-test>

directive.js

.directive('ayTest',function(){
    return {
        restrict: 'EA',
        scope: {
            name:'='
        },
        template:`
            <div class="padding">
                {{vm.name.data}}
            </div>
        `,
        controller:function($scope){
            var vm = $scope.vm = {};
            //注意朦乏,雖然這里重新賦值了name,但是我們的vm.name.data還是同一份,所以仍能實(shí)現(xiàn)綁定
            vm.name = $scope.name;

        }
    }

});

方案3 使用$scope.$watch

如果你知道$scope.$watch缘挑,并且了解何時(shí)使用它集歇,那么你應(yīng)該知道這里也可能使用它來(lái)解決桶略∮锾裕看代碼。

controller.js

    var vm = $scope.vm = {};
    //并沒(méi)有進(jìn)行數(shù)據(jù)封裝
    vm.name = 'Tom1';
    $timeout(function(){
        vm.name = 'Tom2';
    },1000);
    $timeout(function(){
        vm.name = 'Tom3';
    },2000);

A.html

    <ay-test name="vm.name"></ay-test>

directive.js

angular.module('app.directive')
.directive('ayTest',function(){
    return {
        restrict: 'EA',
        scope: {
            name:'='
        },
        template:`
            <div class="padding">
                {{vm.name}}
            </div>
        `,
        controller:function($scope){
            var vm = $scope.vm = {};
            //添加數(shù)據(jù)監(jiān)測(cè)
            $scope.$watch('name',function(newValue,oldValue){
                vm.name = $scope.name;
            });

        }
    }
});

這個(gè)方法其實(shí)相當(dāng)于多加了一層的監(jiān)測(cè)际歼,vm.name和頁(yè)面上的{{vm.name}}綁定惶翻,通過(guò)$scope.$watch,我們讓vm.name$scope.name兩個(gè)變量的值保持一致性鹅心。

哪個(gè)方法好呢

個(gè)人推薦第一種方法吕粗,因?yàn)樗龅墓ぷ髯钌伲氏鄬?duì)較高(雖然高不了很多)旭愧。

最后的話(huà)

本文首先提出了在編寫(xiě)自定義directive時(shí)有時(shí)候會(huì)出現(xiàn)的數(shù)據(jù)無(wú)法同步的問(wèn)題颅筋。隨后分析了問(wèn)題,并給出了幾種解決方案输枯。

其實(shí)议泵,問(wèn)題的根本首先在于對(duì)JavaScript變量值訪問(wèn)引用訪問(wèn)值傳遞等概念的理解桃熄,其次在于對(duì)angular1scope層級(jí)先口、雙向綁定臟值檢測(cè)等概念的理解。

有時(shí)碉京,還能需要處理其他情況厢汹,比如默認(rèn)值處理,分條件展示谐宙,錯(cuò)誤值處理烫葬、數(shù)據(jù)回顯、回調(diào)函數(shù)處理等具體問(wèn)題卧惜,可以參考上面3種思路來(lái)具體實(shí)現(xiàn)厘灼。

很簡(jiǎn)單一個(gè)問(wèn)題,個(gè)人只是做了一下分析咽瓷,有錯(cuò)誤的地方請(qǐng)大神及時(shí)指出设凹,感激不盡~~

Author:shaochong

Email:hao5743@163.com

文章地址:https://hao5743.github.io/2016/12/05/Data-bind-problem-in-Angular-when-define-your-own-directives/

博客:http://hao5743.github.io/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茅姜,隨后出現(xiàn)的幾起案子闪朱,更是在濱河造成了極大的恐慌,老刑警劉巖钻洒,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奋姿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡素标,警方通過(guò)查閱死者的電腦和手機(jī)称诗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)头遭,“玉大人寓免,你說(shuō)我怎么就攤上這事〖莆” “怎么了袜香?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鲫惶。 經(jīng)常有香客問(wèn)我蜈首,道長(zhǎng),這世上最難降的妖魔是什么欠母? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任欢策,我火速辦了婚禮,結(jié)果婚禮上赏淌,老公的妹妹穿的比我還像新娘踩寇。我一直安慰自己,他們只是感情好猜敢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布姑荷。 她就那樣靜靜地躺著盒延,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鼠冕。 梳的紋絲不亂的頭發(fā)上添寺,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音懈费,去河邊找鬼计露。 笑死,一個(gè)胖子當(dāng)著我的面吹牛憎乙,可吹牛的內(nèi)容都是我干的票罐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼泞边,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼该押!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起阵谚,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蚕礼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后梢什,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奠蹬,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年嗡午,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了囤躁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡荔睹,死狀恐怖狸演,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情应媚,我是刑警寧澤严沥,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布猜极,位于F島的核電站中姜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏跟伏。R本人自食惡果不足惜丢胚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望受扳。 院中可真熱鬧携龟,春花似錦、人聲如沸勘高。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蕊蝗,卻和暖如春仅乓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蓬戚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工夸楣, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人子漩。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓豫喧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親幢泼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子紧显,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)缕棵,斷路器鸟妙,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 【JS-8】 angular js自定義指令 directive 如何使用忽匈?為什么要使用封裝的自定義指令房午? 小課堂...
    愛(ài)上Shu的小刺猬閱讀 1,891評(píng)論 0 3
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容丹允。關(guān)于...
    云之外閱讀 5,048評(píng)論 0 29
  • AngularJS是什么郭厌?AngularJs(后面就簡(jiǎn)稱(chēng)ng了)是一個(gè)用于設(shè)計(jì)動(dòng)態(tài)web應(yīng)用的結(jié)構(gòu)框架。首先雕蔽,它是...
    200813閱讀 1,602評(píng)論 0 3
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法折柠,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法批狐,繼承相關(guān)的語(yǔ)法扇售,異常的語(yǔ)法,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,623評(píng)論 18 399