Dojo1.11官方教程文檔翻譯(4.6)創建類

原文地址:https://dojotoolkit.org/documentation/tutorials/1.10/declare/index.html
本翻譯項目放在GitBook上,歡迎參與。
GitBook地址:https://www.gitbook.com/book/limeng1900/dojo1-11-tutorials-translation-in-chinese/details
轉載請註明出處:http://blog.csdn.net/taijiedi13/ – 碎夢道


dojo/_base/declare模塊是Dojo Toolkit裏類創建的基礎。declare允許多重繼承來讓開發者編寫靈活的代碼並避免重複同樣的代碼。Dojo、 Dijit 和 Dojox 模塊都使用declare;在本教程中,你將瞭解爲什麼你也要用它。

入門

確保你瞭解模塊教程中提出的概念。

Dojo的基礎類創建

declare函數定義在dojo/_base/declare模塊裏。declare接收三個參數:classNamesuperClassproperties

ClassName

className參數表示要創建的類的名字,包括命名空間。命名的類放在全局作用域內。className也可以通過命名空間表示繼承鏈。

命名類

// Create a new class named "mynamespace.MyClass"
declare("mynamespace.MyClass", null, {

    // Custom properties and methods here

});

一個名叫mynamespace.MyClass的類現在存在於應用的全局作用域。
如果用在Dojo解析器,應該只創建命名類。其他類應該忽略className參數。

“匿名”類

// Create a scoped, anonymous class
var MyClass = declare(null, {

    // Custom properties and methods here

});

MyClass現在它給出的作用域的可用。

超類

超類的參數可以是null、一個已有類或者一個已有類的數組。如果一個新類繼承自多個類,那麼列表中的第一個類將作爲基本原型,其餘的作爲“混合”。

無繼承類

var MyClass = declare(null, {

    // Custom properties and methods here

});

null意味着這個類沒有類來繼承。

單繼承的類

var MySubClass = declare(MyClass, {

    // MySubClass now has all of MyClass's properties and methods
    // These properties and methods override parent's

});

新的MySubClass將繼承MyClass的屬性和方法。一個父類的方法或屬性可以進行重寫,只要在第三個參數裏添加它的新定義的鍵值,隨後再細說。

多繼承的類

var MyMultiSubClass = declare([
    MySubClass,
    MyOtherClass,
    MyMixinClass
],{

    // MyMultiSubClass now has all of the properties and methods from:
    // MySubClass, MyOtherClass, and MyMixinClass

});

一個類數組表示多繼承。屬性和方法從左到右繼承。數組的第一個類作爲基礎原型,隨後的類混入該類。
如果一個屬性或方法在多個被繼承的類裏指定過,則使用最後一個被繼承的該屬性或方法。

屬性和方法對象

declare最後一個參數包含了類原型的方法和屬性。如果被繼承的類有同樣的屬性或方法,這個參數將會對同名的屬性和方法進行重寫。

自定義屬性和方法

// Class with custom properties and methods
var MyClass = declare(MyParentClass, {
    // Any property
    myProperty1: 12,
    // Another
    myOtherProperty: "Hello",
    // A method
    myMethod: function(){

        // Perform any functionality here

        return result;
    }
});

示例:基類的創建和繼承

下面的代碼創建一個繼承自dijit/form/Button的widget:

define([
    "dojo/_base/declare",
    "dijit/form/Button"
], function(declare, Button){
    return declare("mynamespace.Button", Button, {
        label: "My Button",
        onClick: function(evt){
            console.log("I was clicked!");
            this.inherited(arguments);
        }
    });
});

從上面的代碼,很容易得到以下結論:

  • 類名是mynamespace.Button
  • 該類可以通過全局變量mynamespace.Button來引用,或者從模塊的返回值
  • 該類繼承自dijit/form/Button(因此Button是依賴項)
  • 該類設置了幾個自定義屬性和方法

讓我們通過學習constructor方法來深入瞭解Dojo類的創建。

構造器方法

constructor方法是一個特殊的類方法。constructor方法在類實例化時觸發,在新對象的作用域內執行。這就是說this關鍵字引用該實例,而不是原始類。constructor方法也接收任意數量實例指定的參數。

// Create a new class
var Twitter = declare(null, {
    // The default username
    username: "defaultUser",

    // The constructor
    constructor: function(args){
        declare.safeMixin(this,args);
    }
});

如下創建實例:

var myInstance = new Twitter();

該實例中的username在指定設置之前都將是“defaultUser”。利用safeMixin方法提供一個username參數:

var myInstance = new Twitter({
    username: "sitepen"
});

現在該實例將username設爲sitepen

declare.safeMixin在類的創建和繼承中也很有用。如API文檔中:

這個函數用來像lang._mixin 一樣混入屬性,但是它跳過一個構造器屬性並且像dojo/_base/declare那樣修飾函數。就是說它用來和dojo/_base/declare進行類和對象的生成。和declare.safeMixin混合的函數可以想普通方法一樣使用this.inherited()。這個函數用來實現declare()產生的構造器的方法的extend()。

declare.safeMixin是創建類是的好幫手。

繼承

如上所述,declare第二個參數定義繼承。父類的屬性和方法從左到右混入類,如果屬性已定義後來的具有優先權。如下:

// Define class A
var A = declare(null, {
    // A few properties...
    propertyA: "Yes",
    propertyB: 2
});

// Define class B
var B = declare(A, {
    // A few properties...
    propertyA: "Maybe",
    propertyB: 1,
    propertyC: true
});

// Define class C
var C = declare([mynamespace.A, mynamespace.B], {
    // A few properties...
    propertyA: "No",
    propertyB: 99,
    propertyD: false
});

繼承類最後的屬性是:

// Create an instance
var instance = new C();

// instance.propertyA = "No" // overridden by B, then by C
// instance.propertyB = 99 // overridden by B, then by C
// instance.propertyC = true // kept from B
// instance.propertyD = false // created by C

理解原型繼承很重要。當讀取一個對象示例的屬性時,示例先檢查自己有沒有定義它。如果沒有則遍歷原型鏈,並返回鏈上具有該屬性的第一個對象的值。當屬性值已指定時,總是用對象實例上指定的,從來不用原型的。就是說共享一個原型的對象將返回相同原型定義的值,除非該實例上指定了該值。這在類聲明式就很容易爲原始數據類型(number、string、boolean)設定默認值,並且需要的時候可以在實例中更新它們。然而,如果你在原型的屬性上指定一個對象值(Object、Array),每個實例都將操作這個共享的值。如下:

var MyClass = declare(null, {
    primitiveVal: 5,
    objectVal: [1, 2, 3]
});

var obj1 = new MyClass();
var obj2 = new MyClass();

// both return the same value from the prototype
obj1.primitiveVal === 5; // true
obj2.primitiveVal === 5; // true

// obj2 gets its own property (prototype remains unchanged)
obj2.primitiveVal = 10;

// obj1 still gets its value from the prototype
obj1.primitiveVal === 5; // true
obj2.primitiveVal === 10; // true

// both point to the array on the prototype,
// neither instance has its own array at this point
obj1.objectVal === obj2.objectVal; // true

// obj2 manipulates the prototype's array
obj2.objectVal.push(4);
// obj2's manipulation is reflected in obj1 since the array
// is shared by all instances from the prototype
obj1.objectVal.length === 4; // true
obj1.objectVal[3] === 4; // true

// only assignment of the property itself (not manipulation of object
// properties) creates an instance-specific property
obj2.objectVal = [];
obj1.objectVal === obj2.objectVal; // false

爲了避免無意地在實例之間共享數組或對象,對象屬性應該聲明爲空並在構造器函數裏進行初始化。

declare(null, {
    // not strictly necessary, but good practice
    // for readability to declare all properties
    memberList: null,
    roomMap: null,

    constructor: function () {
        // initializing these properties with values in the constructor
        // ensures that they ready for use by other methods
        // (and are not null or undefined)
        this.memberList = [];
        this.roomMap = {};
    }
});

更多信息參考 dojo/_base/declare

this.inherited

完全重寫方法當然很有用,有時候每個類的構造器執行繼承鏈時需要保留其原始功能。這裏this.inherited(arguments)就很方便。this.inherited(arguments)調用父類的同名方法。如下:

// Define class A
var A = declare(null, {
    myMethod: function(){
        console.log("Hello!");
    }
});

// Define class B
var B = declare(A, {
    myMethod: function(){
        // Call A's myMethod
        this.inherited(arguments); // arguments provided to A's myMethod
        console.log("World!");
    }
});

// Create an instance of B
var myB = new B();
myB.myMethod();

// Would output:
//        Hello!
//        World!

this.inherited方法在子類代碼中任何時候都可以調用。有些情況你會想要在子函數中間或者末尾調用inherited()。即便如此,你不能在構造器裏調用它。

小結

declare函數是創建模塊化和重用Dojo Toolkit 類的關鍵。declare允許多重繼承和任意數量的屬性和方法來生成複雜類。更簡單的是declare易於學習並且可以讓開發者避免重複代碼。

dojo/_base/declare資源

declare和類創建的更多細節請查看一下資源:

發佈了25 篇原創文章 · 獲贊 9 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章