成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Angularjs 1 深度解析:組件化編程

caohaoyu / 3418人閱讀

摘要:一個(gè)高度可復(fù)用的組件則可以被稱為控件,是可以多帶帶投稿項(xiàng)目庫的。行為的定制化通過參數(shù)綁定實(shí)現(xiàn)組件行為的定制化。組件被銷毀時(shí)調(diào)用。當(dāng)有組件復(fù)用的情況時(shí)請(qǐng)使用標(biāo)識(shí)指定接收對(duì)象模型另外最好給事件名添加組件前綴。

轉(zhuǎn)自自己在開源中國的博客:https://my.oschina.net/u/7247...

angular 1 也要面向組件編程

前端組件化是前端開發(fā)模式中一個(gè)不可逆轉(zhuǎn)的趨勢,三大主要前端框架 angular 2 react vue 都不約而同的把組件化編程作為自己的一大賣點(diǎn),angular 1 作為一個(gè)歷史相對(duì)悠久的框架,在私生子 angular 2 的推動(dòng)下,終于也搭上了組件化編程的末班車,公司里那些老項(xiàng)目終于也有機(jī)會(huì)體驗(yàn)組件化編程的滋味。

angular 1 的組件化之路

angular 1 中類似組件化的編程思想其實(shí)很早就有,只不過那時(shí)候不叫組件,而叫指令(Directive),指定 restrict: "E" 后這個(gè)指令就與如今組件的用法很相似了。angular 1.5 中,又將指令根據(jù) angular 2 的類似概念加以限制,脫胎為如今的組件(Components)。

組件的特點(diǎn)

官方文檔列舉了組件和指令的不同點(diǎn)。除此之外,一個(gè)規(guī)范的組件還應(yīng)符合以下幾個(gè)特點(diǎn)。

組件的標(biāo)簽名稱必須包含中劃線

組件擁有良好的生命周期

組件有自包含性

組件有自封閉性

組件有可復(fù)用性

組件可以被定制化

下面依次說明。

組件的名稱規(guī)范

與指令不同,組件必須是一個(gè)元素,HTML 對(duì)于這一點(diǎn)有特殊的規(guī)范。

HTML 規(guī)范把帶有中劃線的標(biāo)簽留給開發(fā)者使用,這樣形成的元素又稱作自定義元素(Custom Element)。我們雖然沒有用到自定義元素的概念,但兩者的行為是相似的。我們應(yīng)該符合這一標(biāo)準(zhǔn)。

這一點(diǎn)規(guī)范對(duì)應(yīng)到 angular 1 中即為:組件名稱必須帶有駝峰形式。

例如:

module.component("dialog", {
    // ...
});

這是不對(duì)的。HTML 規(guī)范已經(jīng)定義了 dialog 這個(gè)標(biāo)準(zhǔn)元素,重復(fù)使用標(biāo)簽名可能導(dǎo)致我們自定義的組件行為和標(biāo)準(zhǔn)元素的行為混雜到一起,導(dǎo)致奇葩 bug;而且如果這樣做也間接導(dǎo)致開發(fā)者不能使用原生的 dialog 標(biāo)簽。

另外,就算現(xiàn)在標(biāo)準(zhǔn)沒有定義某個(gè)元素,不代表將來不會(huì)定義。我們的程序既然跑在瀏覽器里,就要按規(guī)矩辦事。這是一種合法的寫法:

module.component("customDialog", {
    // ...
});
組件的自包含性

一個(gè)設(shè)計(jì)良好的組件一定有它自己的行為和默認(rèn)樣式。

默認(rèn)行為

默認(rèn)行為在 angular 1 中用控制器(Controller)定義。

function CustomDialogController($service) {
    this.someField = 123;
    this.someMethod = function someMethod() {

    }
}
CustomDialogController.$inject = ["$service"];

module.component("customDialog", {
    controller: CustomDialogController,
    template: require("./customDialogTemplate.html"),
});

因?yàn)榻M件默認(rèn)啟用 controllerAs,所有變量和函數(shù)都是綁定到 this 上的,所以你也可以使用 ES2015class 語法來組織代碼:

class CustomDialogController {
    constructor($service) {

    }

    someMethod() {

    }
}
CustomDialogController.$inject = ["$service"];

module.component("customDialog", {
    controller: CustomDialogController,
    template: require("./customDialogTemplate.html"),
});

這樣做有一個(gè)問題就是其他函數(shù)不能使用 constructor 里注入的服務(wù)(Service),只能通過 this 中轉(zhuǎn)一次。我個(gè)人的做法是這樣:

class CustomDialogController {
    constructor($service) {
        this.services = { $service };
    }

    someMethod() {
        const { $service } = this.services;
    }
}
// 下略

建議對(duì)于邏輯相對(duì)簡單的組件的控制器使用 function 定義,復(fù)雜的組件使用 class 定義,后者代碼的層次要更為清晰易讀。

默認(rèn)樣式

組件的默認(rèn)樣式直接使用樣式表指定。

custom-dialog {
    display: block;
    // ...
}

對(duì)于所有瀏覽器不認(rèn)識(shí)的標(biāo)簽,默認(rèn)都是內(nèi)聯(lián)元素(display: inline),對(duì)于組件來說通常不是想要的。所以自定義的組件通常至少要有 display: (inline-)block 來改變?cè)氐哪J(rèn)顯示方式。

組件的自封閉性

自封閉性包含兩個(gè)方面:數(shù)據(jù)的自封閉性和樣式的自封閉性。

數(shù)據(jù)的自封閉性

angular 1 中,組件自身的 scope 已經(jīng)是隔離的(isolate),即組件的 scope 不繼承自父級(jí) scope(__proto__null)。除此之外,一個(gè)規(guī)范的組件不應(yīng)該直接使用外部的數(shù)據(jù),因?yàn)檫@樣會(huì)破壞組件的可復(fù)用性。舉幾個(gè)例子:

$rootScope

$root、$parent(模板中)

路由參數(shù)

localStorage、sessionStorage

這些數(shù)據(jù)都應(yīng)該通過參數(shù)綁定 binding 傳入。如果組件是路由插件生成,那么可以用 resolve。

其次,參數(shù)綁定不應(yīng)使用雙向綁定 =,規(guī)范的組件不應(yīng)(直接)修改組件外部傳入的數(shù)據(jù)。官方推薦的參數(shù)綁定方式有兩種

< 單向綁定,綁定可變數(shù)據(jù)。通常用于給組件傳遞數(shù)據(jù)

@ 字符串綁定,綁定字符串。通常用于指定組件行為

對(duì)于單向綁定對(duì)象的情況,由于是引用傳遞,也不應(yīng)該修改對(duì)象內(nèi)部的屬性。

遇到要向外部傳值的情況,推薦使用 ngModel 或 事件綁定(下面會(huì)提到)

樣式的自封閉性

組件間的樣式不應(yīng)該互相干擾,這一點(diǎn)可以簡單的通過 scss 的樣式嵌套(Nesting)實(shí)現(xiàn):

custom-dialog {
    display: block;
    // ...

    .title {
        // ...
    }

    .body {
        // ...
    }
}

這樣可以簡單的把組件的內(nèi)置樣式表限制在組件內(nèi)部,從而避免樣式外溢。但是這種方法對(duì)在組件內(nèi)部的其他組件不起效果。如果這個(gè)組件的模板中還引用了別的組件,或者這個(gè)組件被定義為可嵌入的(transclude),那么可以考慮加類名前綴:

custom-dialog {
    display: block;

    .custom-dialog {
        &-title {
            // ..
        }

        &-body {

        }
    }
}
組件的可復(fù)用性

組件為復(fù)用而生,擁有良好自封閉性的組件必然是可復(fù)用的,因?yàn)檫@個(gè)組件不受任何外部因素干擾。組件的復(fù)用形式包括

一個(gè)頁面中使用多次

在多個(gè)頁面中使用

ng-repeat

自己套自己(遞歸樹結(jié)構(gòu))

整個(gè)源代碼拷貝到其他項(xiàng)目中

等等。一個(gè)高度可復(fù)用的組件則可以被稱為控件,是可以多帶帶投稿 npm 項(xiàng)目庫的。

當(dāng)然,有些組件(比如多帶帶的頁面)可能復(fù)用需求沒那么高,可以視組件的復(fù)用程度不同,從組件的自封閉性和整體代碼量做一些取舍。

組件的定制化

一個(gè)高度可復(fù)用的組件一定可以被定制。

行為的定制化

通過參數(shù)綁定實(shí)現(xiàn)組件行為的定制化。例如:


    
module.component("customDialog", {
    template: require("./customDialogTemplate.html"),
    transclude: true,
    bindings: {
        title: "@",
        modal: "<",
    },
});

出于使用方便的考慮,定制用的參數(shù)都是可選的,組件內(nèi)部實(shí)現(xiàn)應(yīng)該給每個(gè)定制參數(shù)設(shè)定默認(rèn)值。

樣式的定制化

組件風(fēng)格定制可以使用 class 判斷。

custom-dialog {
    display: block;
    // ...

    .title {
        font-size: 16px;
        // ...
    }

    &.big {
        .title {
            font-size: 24px;
        }
    }
}

使用時(shí)

深度定制樣式比較好的方式是 CSS 屬性(CSS Variable,注意不是 SCSS 屬性)。

custom-dialog {
    display: block;
    // ...

    .title {
        font-size: 16px;
        color: var(--dialog-title-color, #333);
        // ...
    }

    &.big {
        .title {
            font-size: 24px;
        }
    }
}

這時(shí)只需要文檔中說明標(biāo)題顏色使用 --dialog-title-color 這個(gè) CSS 變量就好,外部使用不依賴于組件內(nèi)部 DOM 實(shí)現(xiàn)。使用時(shí)

.mydialog {
    --dialog-title-color: red;
}
組件的生命周期

從創(chuàng)建至銷毀,組件有自己的生命周期(lifecycle),而不像指令那樣把 scope 作為生命周期。常用的回調(diào)函數(shù)如下:

$onInit():組件被初始化時(shí)調(diào)用。與 constructor 不同,angular 1 確保 $onInit 被調(diào)用時(shí)組件的所有參數(shù)綁定都被正確賦值。

$onChanges(changeObj):組件參數(shù)綁定值被改變時(shí)調(diào)用。用于監(jiān)聽綁定值的變化,初次綁定時(shí)也會(huì)調(diào)用這個(gè)函數(shù)。

$onDestroy():組件被銷毀時(shí)調(diào)用。用于清理內(nèi)部資源如 $interval 等。

這些函數(shù)也是綁定在 this 上的。如果 controller 使用 ES2015class 定義方式,可以這么寫:

class CustomDialogController {
    constructor() {}

    onInit() {}

    onChanges({ prop1, prop2 }) {}

    onDestroy() {}
}
組件間的通信

組件間通信是一個(gè)讓很多人頭疼的問題,通常有這樣 3 種情況

子 -> 父

這種情況有標(biāo)準(zhǔn)的實(shí)現(xiàn)方式:事件綁定。例如

class CustomDialogController {
    close($value) {
        this.hide = true;
        this.onClose({ $value });
    }
}

module.component("customDialog", {
    controller: CustomDialogController,
    template: require("./customDialogTemplate.html"),
    bindings: {
        onClose: "&",
    },
});

使用時(shí):

這種方式也可以用于子組件向父組件傳值。

父 -> 子

用于觸發(fā)子組件的某個(gè)動(dòng)作。除了改變某個(gè)在子組件內(nèi)部監(jiān)聽變化的綁定參數(shù)值外,行之有效的方式就只有事件廣播。

子組件先監(jiān)聽某個(gè)事件

$scope.$on("custom-dialog--close", () => this.close());

父組件發(fā)送廣播

$scope.$broadcast("custom-dialog--close");

切記:事件是全局性的。當(dāng)有組件復(fù)用的情況時(shí)請(qǐng)使用標(biāo)識(shí)指定接收對(duì)象(BUS 模型);另外最好給事件名添加組件前綴。

同級(jí)組件

請(qǐng)通過父級(jí)組件中轉(zhuǎn)

子 -> 某全局性組件

這個(gè)顯示 Notification 時(shí)最常用。遇到這種情況時(shí),可以封裝服務(wù)(Service)。例如:

module.component("globalNotification", {
    controller: class GlobalNotificationController {
        constructor(notificationService) {
            notificationService.component = this;
        }

        show(props) {
            // ...
        }
    }
});

module.factory("notify", function NotifyService() {
    return {
        warn(msg) {
            this.show({ type: "warn", text: msg });
        }
        error(msg) {
            this.show({ type: "error", text: msg });
        }
    }
});

方案并不完美。如果有更好的建議歡迎提出。

結(jié)語

有人可能問既然三大前端框架都是組件化的,何必還要在 angular 1 上實(shí)現(xiàn)。殊不知 angular 1 的組件誕生的初衷就是為了減少向 angular 2 遷移的難度。機(jī)會(huì)總是留給有準(zhǔn)備的人,哪天老板大發(fā)慈悲表示給你把代碼重寫的時(shí)間,你卻看著項(xiàng)目里滿屏的 $scope.abc = xxx 不知所措,這豈不是悲劇。。。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94954.html

相關(guān)文章

  • Regularjs是什么

    摘要:目前已經(jīng)在大大小小多個(gè)線上產(chǎn)品中使用了,也收集了一些有效的建議好了,該看下一個(gè)最簡單的組件長什么樣吧免費(fèi)領(lǐng)取驗(yàn)證碼內(nèi)容安全短信發(fā)送直播點(diǎn)播體驗(yàn)包及云服務(wù)器等套餐更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)分享請(qǐng)?jiān)L問網(wǎng)易云社區(qū)。文章來源網(wǎng)易云社區(qū) 本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。 此文摘自regularjs的指南, 目前指南正在全面更新, 把老文檔的【接口/語法部分】統(tǒng)一放到了獨(dú)立的 Reference...

    seal_de 評(píng)論0 收藏0
  • 前端每周清單第 50 期: AngularJS and Long Term Support, Web

    摘要:在該版本發(fā)布之后,開發(fā)團(tuán)隊(duì)并不會(huì)繼續(xù)發(fā)布新的特性,而會(huì)著眼于進(jìn)行重大的錯(cuò)誤修復(fù)。發(fā)布每六個(gè)星期,團(tuán)隊(duì)就會(huì)創(chuàng)建新的分支作為發(fā)布通道,本文即是對(duì)新近發(fā)布的版本進(jìn)行簡要介紹。 showImg(https://segmentfault.com/img/remote/1460000013229009); 前端每周清單專注前端領(lǐng)域內(nèi)容,以對(duì)外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn);分為新聞熱...

    DobbyKim 評(píng)論0 收藏0
  • zepto/jQuery、AngularJS、React、Nuclear的演化

    摘要:每個(gè)框架類庫被大量用戶大規(guī)模使用都說明其戳中了開發(fā)者的剛需。但是未執(zhí)行完的情況下發(fā)生人機(jī)交互雖然不會(huì)報(bào)腳本錯(cuò)誤,但是嚴(yán)重影響用戶體驗(yàn)開發(fā)者們被各種爽到之后,這個(gè)問題已經(jīng)被拋到了九霄云外。 寫在前面 因?yàn)閦epto、jQuery2.x.x和Nuclear都是為現(xiàn)代瀏覽器而出現(xiàn),不兼容IE8,適合現(xiàn)代瀏覽器的web開發(fā)或者移動(dòng)web/hybrid開發(fā)。每個(gè)框架類庫被大量用戶大規(guī)模使用都說明...

    Rindia 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<