DOJO Dijit佈局

Layout with Dijit

Dijit佈局

Creating dynamic and interactive layouts is a challenge common to any graphical user interface. We have a lot of ability to create layout with HTML and CSS. Where CSS leaves off, Dojo picks up with a set of extensible widgets as a part of Dijit - Dojo's UI framework. In this tutorial, we'll explain how Dijit addresses common layout needs and see how easy it can be to create even complex layouts with just a few flexible widgets.

創建動態、可交互佈局對所有圖形界面開發者來說都是一種挑戰。我們可以使用HTML和CSS創建各種佈局。而dojo使用一系列的可擴展的微件而非CSS,組建其Dijit-Dojo的UI框架。在本教程中,我們會講解Dijit如何定位通用的佈局,你會發現使用很少的靈活的微件即可創建複雜佈局。

Introducing Layout Management

佈局管理介紹

"Surely CSS is the language of layout? Why is layout a problem that needs solving by JavaScript and fancy widgets?"

"CSS 是佈局語言是毫無疑問的?那爲什麼佈局的難題需要靠JavaScript代碼和精選的微件來解決?"

Layout widgets don't replace CSS for general purpose placement and flow of content on the page. Instead, they allow precise placement and management of areas of the page where we want to:

佈局組件並非要替代CSS。相反的,它能夠在我們需要實現以下效果的地方提供對界面區域更精確的管控。

  • Respond to resize events
  • 響應resize事件
  • Provide for user control over layout and how the available space is apportioned
  • 爲用戶組件提供佈局,以及控制可用空間的分配。
  • Adapt controls and/or contents to the currently available horizontal and vertical space
  • 使組件或內容適配可用區域的高或寬

Layout management is the process of actively controlling layout after a page has loaded, and responding to and propagating events, which then drive layout on the page. In Dijit, layout management is accomplished by specialized layout widgets. These are widgets whose primary purpose is to act as a container for one or more content areas or child widgets, and to control the sizing and display of those children.

佈局管理在界面加載完成後會主動的控制佈局,接收及發出事件,進而控制界面佈局。DIJIT中,佈局管理是通過佈局組件完成的。佈局組件的主要用途就是作爲 內容區域 或 其他組件的 容器,展現內部組件內容並能控制 內部組件的大小。

Getting Started;

開始學習

You can manage layout of the entire page, or just a small part of it. For this tutorial, we'll be developing a desktop application-like UI layout, with some controls and content being fixed on the page. It should end up looking like this:

可以控制整個頁面的佈局,也可以控制頁面一個小的區域的佈局。在本教程中,我們會創建一個類似 桌面應用 的界面佈局。其中包含很多控件和內容。最後的效果如下:

Application Layout

View Complete Demo

Dijit provides a small collection of flexible widgets to meet common layout requirements like this. We'll prepare the ground with some HTML and CSS, then introduce those widgets to build up a typical application layout.

Dijit提供了一個小而靈活的微件集合來實現類似的常用的佈局。我們會先列出需要的HTML和CSS,然後介紹使用這些微件構建典型的應用佈局。

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Demo: Layout with Dijit</title>
        <link rel="stylesheet" href="style.css" media="screen">
        <link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/claro/claro.css" media="screen">
    </head>
    <body class="claro">
        <div id="appLayout" class="demoLayout">
            <div class="centerPanel">
                <div>
                    <h4>Group 1 Content</h4>
                    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
                </div>
                <div>
                    <h4>Group 2 Content</h4>
                </div>
                <div>
                    <h4>Group 3 Content</h4>
                </div>
            </div>

            <div class="edgePanel">Header content (top)</div>
            <div id="leftCol" class="edgePanel">Sidebar content (left)</div>
        </div>
        <!-- load dojo and provide config via data attribute -->
        <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"
                data-dojo-config="async: 1, parseOnLoad: 1">
        </script>
    </body>
</html>

The markup has our top, sidebar and center content wrapped in handy divs, and we've got the Dojo script tag already in place. Also in the <head> we load the Claro theme stylesheet and our page stylesheet. In the <body>, notice the claro class which is necessary to apply the Claro CSS theme to the contents. Omitting it is a common gotcha.

我們添加了標題欄,側邊欄,主區域,都以div形式體現。我們添加了dojo JavaScript 引用。在<head>中引用了Claro以及page樣式引用。在<body>標籤中,添加了claro樣式,通過claro樣式渲染界面。該處漏掉是一個常見的錯誤。

The stylesheet has just a few rules that we'll need as we define the layout:

樣式表中包含一些定義佈局需要的規則。

html, body {
    height: 100%;
    margin: 0;
    overflow: hidden;
    padding: 0;
}

#appLayout {
    height: 100%;
}
#leftCol {
    width: 14em;
}

.claro .demoLayout .edgePanel {
    background-color: #d0e9fc;
}

#viewsChart {
    width: 550px;
    height: 550px;
}

All demos shown here also include a demo.css file, which contains a few styles for the body, button, and h1 elements. View the source of any of the demos to see the contents of this file.

本教程中的例子同時包含一個demo.css樣式文件,其中包含一些body、button、h1的樣式。可以通過查看例子的源碼來查看demo.css的內容。

To get the desired arrangement and behavior of content regions, we want the layout to fill the viewport. We explicitly set the document and the outermost element to 100% of the viewport height. overflow: hidden is used as we don't want a document scrollbar; scrolling will happen as necessary in the different regions of our layout. We've given the DIV that will become the left column a fixed width in ems. The other fixed regions will derive their size from their initial content.

爲了實現想要的佈局和效果,我們希望佈局填充視圖區域。我們將文檔和最外層的元素的高定義爲100%。添加overflow:hidden 是因爲我們不想文檔出現滾動條;滾動條在需要的時候會在我們佈局的不同的區域出現。我們給要成爲左側邊欄的div一個固定的寬度,單位是em。其他固定區域會根據其最初包含的內容設定大小。

Adding Widgets

添加微件

To implement the layout, we'll be using three widget classes from Dijit: dijit/layout/BorderContainerdijit/layout/TabContainer and dijit/layout/ContentPane.

爲了實現佈局,我們需要用到Dijit中的三個微件類:dijit/layout/BorderContainerdijit/layout/TabContainer 和 dijit/layout/ContentPane。

To get started, let's add a require call to load these dependencies.

開始之前我們通過require方法來加載這些依賴項。

<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"
        data-dojo-config="async:true, parseOnLoad:true">
</script>
<script>
    require(["dojo/parser", "dijit/layout/BorderContainer", "dijit/layout/TabContainer",
        "dijit/layout/ContentPane"]);
</script>

Notice in the data-dojo-config attribute in the Dojo script tag we've set parseOnLoad to true. This tells Dojo to run the parser automatically to "widgetize" the elements it finds. Given that we're fully relying on the parser, we have no need for dojo/domReady! or anything like that — we're just loading what we use.

注意Dojo script標籤中的data-dojo-config 屬性,我們設置parseOnLoad爲true。這樣,Dojo就會自動將發現的相應元素解析爲微件。這樣我們完全依賴解析器,不再需要dojo/domReady!或者其他類似功能-我們只需要加載我們需要的模塊。

Notice that we have also explicitly loaded the dojo/parser module. This is of monumental importance; despite popular misconception, dojo/parser does not load automatically when parseOnLoad is set to true, and never has. It happened to "just work" in many cases prior to 1.7 due to how many widgets loaded dijit/_Templated (which loads dojo/parser).

注意我們明確的加載了dojo/parser模塊。這是非常重要的;不同於常見的誤解,dojo/parser並不會因爲parseOnLoad設置爲true而自動加載,從來都不會。在Dojo1.7版本之前,有些情況下不顯式加載dojo/parser也可以正常執行,那是因爲很多微件會加載dijit/_Templated(其中引用了dojo/parser).

The widget classes will now load in the background, and the parser will walk over the DOM. But nothing is actually going to happen yet — we need to create those layout widgets.

微件類會在後臺加載,解析器會遍歷Dom。不過什麼都還不會發生-我們需要創建佈局微件。

For this example, we'll be using the markup or declarative way of instantiating the widgets. The data-dojo- attributes on each element provide instruction for the Dojo parser on what widget class to instantiate, and hold the properties to configure the widget instance with.

對於本例來說,我們會使用標籤或生命方式來實例化微件。元素上的data-dojo- 屬性向解析器表明該元素將要被實例化爲哪種微件,並且保存配置微件實例的屬性。

<body class="claro">
    <div
            id="appLayout" class="demoLayout"
            data-dojo-type="dijit/layout/BorderContainer"
            data-dojo-props="design: 'headline'">
        <div
                class="centerPanel"
                data-dojo-type="dijit/layout/ContentPane"
                data-dojo-props="region: 'center'">
            <div>
                <h4>Group 1 Content</h4>
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
            </div>
            <div>
                <h4>Group 2 Content</h4>
            </div>
            <div>
                <h4>Group 3 Content</h4>
            </div>
        </div>
        <div
                class="edgePanel"
                data-dojo-type="dijit/layout/ContentPane"
                data-dojo-props="region: 'top'">Header content (top)</div>
        <div
            id="leftCol" class="edgePanel"
            data-dojo-type="dijit/layout/ContentPane"
            data-dojo-props="region: 'left', splitter: true">Sidebar content (left)</div>
    </div>
</body>

View Demo

The outer appLayout element has been configured as a BorderContainer, and the child divs are each ContentPanes. This gives us a full-screen flexible layout. Go ahead and try resizing your Demo window, to see how the left region stays a fixed width, while the center/right region sizes to fit. You may also notice a handle on the vertical divider, between the left and center regions, which allows you to manually set their relative widths.

最外層的appLayout元素被聲明爲一個BorderContainer,子div都被聲明爲ContentPane。這是一個全屏幕的靈活的佈局。你可能還注意到一個處理垂直的splitter,在左邊欄和中心區域之間,用來手動調節相對寬度。

This is what we mean by dynamic and interactive layout. We'll get to adding in the tab-strip shown in the initial demo, but first let's back up and look a bit closer at the individual layout widgets and their use.

這就是我們所說的動態和交互式佈局。我們將會添加最初的例子中展示的tab頁,不過在此之前我們還是返回來仔細看一下各個佈局微件及其使用。

BorderContainer

帶邊框容器

BorderContainer example

If you've used layout managers and containers in other GUI toolkits, dijit/layout/BorderContainer should be pretty familiar to you, and if not we can soon catch you up.

如果你用過其他的圖形用戶界面工具包中的佈局管理器和容器。dijit/layout/BorderContainer 對你來說應該很熟悉,如果沒用過,那也不要緊很快就會熟悉。

BorderContainer allows you to define a layout subdivided into regions. The center region is always flexible and auto-sized, while the other regions are fixed in size: "top", "bottom", "leading", "trailing", "left" or "right".

All Dijit widgets support internationalization (i18n), so Dijit can't assume left-to-right flow of content and controls on the page. For left-to-right locales, the leading section will be on the left, and the trailing section on the right. For right-to-left locales (e.g. Arabic, Hebrew), it is reversed. That being said, you can use left and right as appropriate to ensure that sections are always on the side of your choosing, regardless of locale. Use what fits your content logically.

BorderContainer允許你定義被分成多個區域的佈局。中心區域一般是可以改變大小的,其他區域則的大小則是固定的: "top", "bottom", "leading", "trailing", "left" 或 "right"。所有的Dijit微件都支持國際化,因此Dojo並不假設頁面或組件是從左到右順序的。對於本地化語言從左到右順序的情況,leading 區域會顯示在左邊,trailing 區域顯示在右邊。而對於從右到左的情況(例如:Arabic,Hebrew),正好是相反的。因此,你可以使用left 和 right 來確保區域在你想要的位置,而無論本地化是怎樣的。看哪種適合你的邏輯。

Each region is represented by a child widget, as we saw in the App Layout example. All Dijit widgets support the regionproperty, so in principle, you can use any widget in these positions, though clearly some will work better than others. The fixed-size regions (all but center) can have a end-user-moveable divider associated with them by setting a splitterproperty.

每個區域代表一個子微件,像我們看到的App Layout例子,所有的Dijit微件都支持region屬性,因此,原則上在這些位子你可以使用任意的微件,固定大小的區域(除center之外的)可以通過設置splitter屬性包含一個divider。

When using BorderContainer, the initial sizes of regions are specified in the normal manner using CSS — using rules in a stylesheet or as inline style. Note that although you can set an initial size of say, 50%, it will be converted to px as it renders, so relative proportions in percentage units are not maintained as the BorderContainer is resized. The center region should not be given style height or width; it will always occupy whatever space remains.

使用BorderContainer時,其初始大小使用CSS控制-使用嵌入式CSS或者樣式表文件。注意,儘管你可以設置初始大小爲百分比樣式,如50%,但在渲染時會被轉換爲px單位的值,因此BorderContainer大小變化時,不會保存相對大小。中心區域不能設置高和寬;它會佔據剩餘的空間。

Up to now as we've been building our layout, all the regions were ContentPanes - a very general purpose content-loading and content-containing widget, but as we saw in the first App Layout where a TabContainer occupied the center region, that needn't be so. In fact, BorderContainer works quite happily as a region in a BorderContainer. Here's an example of nesting BorderContainers to achieve a more complex layout.

到目前爲止我們一直在構建我們的佈局,所有的區域都是ContentPane微件-一個一般用途的內容組件-加載和包容-包含微件,不過正如我們在第一個App Layout例子中看到的那樣,中心區域是一個TabContainer,使用ContentPane不是必須的。事實上,BorderContainer 就經常用作BorderContainer中的某一區域。下面是一個使用嵌套BorderContainer的例子實現複雜佈局的例子。

<div class="demoLayout" style="height: 300px; width: 300px" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="design: 'headline'">
    <div class="centerPanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">center</div>
    <div class="demoLayout" style="height: 50%" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region: 'top', splitter: true, design: 'headline'">
        <div class="centerPanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">center</div>
        <div class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'bottom'">bottom</div>
    </div>
    <div class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="splitter: true, region: 'left'">left</div>
    <div class="demoLayout" style="width: 50%" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region: 'right', design: 'headline'">
        <div class="centerPanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">center</div>
        <div class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'left'">left</div>
    </div>
    <div class="edgePanel" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="splitter: true, region: 'bottom'">bottom</div>
</div>

View Demo

See the BorderContainer documentation for more details on the different options for BorderContainer and its use.

閱讀 BorderContainer 文檔 查看BorderContainer的不同選項及其使用的更多細節。

Making the Tabs

添加Tab組件

A layout widget's job is to layout and display its contents in the space it has available. Most expect their contents to be one or more child widgets. A common requirement is to display only one of those child widgets at once, and treat them as a stack that the user can move through. This maximizes the use of space and also allows for interesting possibilities like not loading content until that entry in the stack is selected. Dijit provides alternatives on this theme, in the form of StackContainer, TabContainer and AccordionContainer.

佈局組件的作用是在獲得的區域中展示其內容。大多數情況他們包含一個或多個子組件。一種常見的需求是一次只展示一個子組件,將所有子組件作爲一個集合,用戶可以選擇展示某一項。這樣最大限度的利用空間並且支持一些有趣的特性比如知道用戶選擇了相應的項之後才加載其中的內容。Dijit提供了多種候選項:StackContainer, TabContainer 和AccordionContainer。

The layout we are trying to create had each of the different "group" divs displayed as tabbed panels, with a tab strip at the bottom of the center region. This is a common, intuitive UI pattern dating back to analog filing systems. The dijit/layout/TabContainer widget implements this pattern. It represents the child widgets it contains as tabs in the tab strip (the tab controller), and displays their contents one at a time in the remaining space.

我們將要創建的佈局包含多組div,每個div會被展示位一個tab頁,包含一個tab標題在中心區域的下方。這是一種常見的、直觀的用戶界面模式可以追溯到模擬文件系統。dijit/layout/TabContainer 也是這種模式。它將子微件展示爲一個個的tab頁,每次只在顯示區展示一個子微件的內容。

<div class="centerPanel"
        data-dojo-type="dijit/layout/TabContainer"
        data-dojo-props="region: 'center', tabPosition: 'bottom'">
    <div
            data-dojo-type="dijit/layout/ContentPane"
            data-dojo-props="title: 'Group 1'">
        <h4>Group 1 Content</h4>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </div>
    <div
            data-dojo-type="dijit/layout/ContentPane"
            data-dojo-props="title: 'Group Two'">
        <h4>Group 2 Content</h4>
    </div>
    <div
            data-dojo-type="dijit/layout/ContentPane"
            data-dojo-props="title: 'Long Tab Label for this One'">
        <h4>Group 3 Content</h4>
    </div>
</div>

To make the "group" sections tabs in a TabContainer, we first make the containing element a TabContainer. This widget is itself a child of the BorderContainer, so it still needs the region property. TabContainer provides a number of options for configuring how the tabs and their content are displayed; here we indicate we want the tab-strip at the bottom by setting the tabPosition property. TabContainer is another container widget - it manages child widgets - so we need to wrap each of our section blocks in a suitable widget. They don't need to do anything fancy, so a ContentPane is a good choice. Notice that each provides a "title" property. The title is what TabContainer uses as the label in the corresponding tab it creates for each child widget.

爲了展示TabContainer,我們首先將容器元素設置爲TabContainer。這個微件本事也是BorderContainer的子微件,因此需要添加一個region屬性。TabContainer包含很多選項用來配置標籤頁標題和內容如何顯示;本例中我們通過設置tabPosition來表明我們希望tab標籤展示在下方。TabContainer也是一個容器微件-它被用來管理子微件-因此我們需要將每個tab頁中的內容放到合適的微件中。他們不需要多華麗,ContentPane就夠了。注意每個tab頁都有一個“title”屬性。TabContainer 會將title屬性作爲tab頁的標題。

View Demo

StackContainer and Friends

StackContainer 和朋友們


The result completes our layout, but to understand how to vary this recipe and make your own layouts - and even your own layout widgets - we need to look under the hood a little. TabContainer is actually a sub-class of dijit/layout/StackContainer; it borrows most of its functionality from StackContainer (which in turn is an extension of dijit/layout/_LayoutWidget.) Where TabContainer is specific about how the panels of content should be arranged and represented, StackContainer is a more general-purpose widget. There is no intrinsic controller to provide UI to navigate the stack of child widgets, but dijit/layout/StackController is available as a simple example. Here's how our layout looks if we swap out the TabContainer for the StackContainer, and put the controller widget in a new bottom region. To get everything to line up, we've also changed the BorderContainer to use the sidebar design layout here.

以上已經完成了我們的佈局,但是爲了更好的理解如何改變佈局及創建自己的佈局-甚至創建自定義的佈局微件-我們需要再深入一點。TabContainer其實是dijit/layout/StackContainer的一個子類;它從StackContainer集成了絕大部分功能(StackContainer 的父類是dijit/layout/_LayoutWidget)。相對於TabContainer 具體設置了其子面板具體如何安排及展現,StackContainer 是一個更通用的微件。沒有固定的controller來提供界面瀏覽StackContainer子微件,但是dijit/layout/StackController可用做簡單示例。下面是我們將TabContainer 替換爲StackContainer,並且將controller微件放在新增的bottom區域的效果。爲了整齊,我們也將BorderContainer 替換爲側邊欄佈局。

Layout with StackContainer

StackContainer Demo

Dijit also provides a dijit/layout/AccordionContainer that drops in as easily, and in dojox/layout there are other StackContainer subclasses that may fit your requirements. Similarly, our vanilla ContentPane can be replaced with a dojox/layout/ExpandoPane to provide for collapsible panels in a layout. As always, it's worth familiarizing yourself with the options provided to you before you start thinking about customizing.

Dijit 還提供了一個dijit/layout/AccordionContainer 微件,用起來也很簡單,在dojox/layout中還有其他的StackContainer 的子類可能符合你的需求。類似的,ContentPane可以被替換爲dojox/layout/ExpandoPane 以提供可摺疊的佈局面板。同樣的,熟悉在開始考慮自定義之前熟悉各種配置是很有必要的。

Startup and Resize

啓動重置大小

So far we've been happily assembling layouts in markup, and leaning on the Dojo parser to coordinate instantiation and the startup sequence for us. That gets you a long way and might be all you ever need to really know about layout with Dijit. However, if you need to create and insert widgets programmatically, that voodoo won't do. We need to understand a bit more about how and when layout happens.

到目前爲止,我們一直在使用標籤設置佈局,依賴Dojo 解析器爲我們處理實例化及啓動的順序。這會妨礙你掌握Diji佈局的核心知識。不過,如果你能通過編碼方式創建及嵌套微件,就沒問題了。我們來更深入一些的瞭解佈局作用的原理。

Let's review. We know that:

複習一下。我們知道:

  • Creating widgets involves a sequence of well defined steps
  • 創建微件包含一些列的預定義步驟
  • Layout is intrinsically linked to the measurement of available space
  • 佈局與可用空間的測量有着內在的聯繫
  • A widget's domNode can't be guaranteed to be in the DOM until startup happens
  • 微件的domNode屬性直到微件調用startup後才能確保在Dom中存在。
  • Layout widgets actively lay out their child widgets
  • 佈局微件會自動佈局它們的子微件。

When creating widgets programmatically, we have to complete the sequence by calling the startup method. This step includes anything that can only happen once a widget is in the DOM - which includes measurement and sizing. Layout widgets will call startup on their children, so it's sufficient to start the ball rolling from the top-most widget.

By definition, all layout widgets have a resize method. This method gets called during startup, and also whenever there's a change that might require adjustment of dimensions - such as a window resize, or adding a new child widget. Like startupresize also propagates down a hierarchy, allowing each widget in a layout to adjust, and pass along new dimensions to its children.

當使用代碼創建微件時,我們需要調用startup方法來完成微件初始化序列。這個步驟包含了所有需要在微件添加到界面之後執行一次的內容-其中包括量測和大小分配。佈局微件會調用子微件的startup方法,這樣就能夠從頂層微件啓動逐層調用startup的機制。

按照定義,每個不微件都有一個resize方法。這個方法會在startup過程中調用,在需要調整尺寸的變化發生時也會調用-例如頁面大小改變,或者新增子微件。像startup方法一樣,resize方法也會逐層傳遞調用,使得佈局中的每個微件都可以調整大小,並且向子微件傳遞自身的尺寸。

With this in mind, lets look at some code. Here's the basic outline:

瞭解了這些,我們再來看一些代碼。下面是基本的輪廓。

<head>
    <script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"
        data-dojo-config="async:1">
    </script>
    <script>
    require(["dijit/registry", "dijit/layout/BorderContainer",
            "dijit/layout/TabContainer", "dijit/layout/ContentPane", "dojo/domReady!"],
        function(registry, BorderContainer, TabContainer, ContentPane){
            // create the main appLayout BorderContainer創建appLayout BorderContainer
            // create the TabContainer創建TabContainer
            // create the BorderContainer edge regions創建BorderContainer 側邊欄
        });
    </script>
</head>
<body class="claro">
    <div id="appLayout" class="demoLayout"></div>
</body>

Here we've omitted parseOnLoad, which defaults to false; the gloves are off. Instead, we use dojo/domReady! which will wait for the DOM to load.

這裏我們去掉了parseOnLoad設置,該設置默認爲false;魔術手套去掉了。作爲替代,我們使用dojo/domReady!來等待Dom加載完成。

// create the BorderContainer and attach it to our appLayout div創建BorderContainer 將其綁定appLayout div
var appLayout = new BorderContainer({
    design: "headline"
}, "appLayout");

// create the TabContainer 創建TabContainer 
var contentTabs = new TabContainer({
    region: "center",
    id: "contentTabs",
    tabPosition: "bottom",
    "class": "centerPanel"
});

// add the TabContainer as a child of the BorderContainer 將TabContainer 作爲BorderContainer 的子元素
appLayout.addChild( contentTabs );

// create and add the BorderContainer edge regions 創建並添加BorderContainer 側邊欄
appLayout.addChild(
    new ContentPane({
        region: "top",
        "class": "edgePanel",
        content: "Header content (top)"
    })
);
appLayout.addChild(
    new ContentPane({
        region: "left",
        id: "leftCol", "class": "edgePanel",
        content: "Sidebar content (left)",
        splitter: true
    })
);

// Add initial content to the TabContainer 爲TabContainer添加初始內容
contentTabs.addChild(
    new ContentPane({
        href: "contentGroup1.html",
        title: "Group 1"
    })
);

// start up and do layout 啓動並分配佈局
appLayout.startup();

View Demo

Each widget is instantiated with the equivalent properties we were defining before in the data-dojo-props attributes. Rather than the implicit containment we get from the markup, each widget is explicitly added to its parent using its addChildmethod.

每個微件都使用之前我們定義在 data-dojo-props 中的值進行了實例化。不同於標籤方式的隱式包含,每個微件都通過顯式的調用addChild方法添加到父微件上。

Notice that only when all the widgets are added does the startup method of the appLayout get called. Until startup happens, addChild simply registers the widget as a child. After startup, addChild represents a potential layout change, so it would trigger resize on the parent, and all other children.

注意,只有所有的微件都添加之後,appLayout的startup方法纔會調用。在startup方法之前,調用addChild方法只是將微件註冊爲一個子微件,startup方法之後,調用addChild則會導致佈局變化,會觸發父微件的resize事件,以及其他兄弟微件的resize事件。

We can see this in action, by adding a new child after the layout is rendered. Here's a quick function to test that:

我們可以在佈局渲染完成後向其中添加一個新的子微件來測試。下面的是一個簡單的測試用例:

function addTab(name) {
    var pane = new ContentPane({
        title: name,
        content: "<h4>" + name + "</h4>"
    });
    // add the new pane to our contentTabs widget爲Tab頁添加新的pane
    registry.byId("contentTabs").addChild(pane);
}

View Demo

Conclusion

We've looked at the building blocks Dijit provides to create dynamic layouts and how they can be snapped together using the declarative markup style, as well as creating them programmatically. This approach allows you the full range of options for how you define and assemble your UIs. You'll find the same flexibility as we explore more of Dijit. We can multiply our options further by creating our own layout widgets, building on the infrastructure Dijit provides. These are topics for future tutorials.

總結:

我們學習了Dijit創建動態的佈局基礎內容,以及通過標籤及編碼方式實現佈局。這爲我們定義和裝配界面提供了充分的選擇範圍。深入瞭解Dijit之後你會發現其他內容同樣靈活。我們可以基於Dijit提供的框架創建自定義的佈局微件來進一步豐富我們的選擇範圍。這些內容會出現在後續教程中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章