用戶界面是由一系列組件組合而成,組件將數據和交互封裝在內,僅保留必要的接口與其餘組件進行通訊。html
從抽象的角度來看,任何用戶界面都是由組件
、數據
和交互
組成的。前端
組件是一個具備必定功能的獨立單元,不一樣的組件能夠組合在一塊兒,構成功能更強大的組件,組件是網頁的器官
。
組件的概念要和HTML標籤的概念區分開來,HTML標籤是網頁的基本單元,而組件是基於HTML標籤的、包含特定功能的獨立單元,能夠簡單理解爲組件是HTML標籤的一個超集。
組件內部封裝的是數據和交互,對外暴露必要的接口,以與其餘組件進行通訊。react
用戶界面中包含不少數據,有不變的靜態數據,也有隨時間和交互改變的動態數據,它們大多來自於後臺數據庫。
組件內部包含數據,組件之間傳遞的也是數據,數據是網頁的核心
。
在前端開發中,數據主要以JSON格式進行存儲和傳遞。git
交互是用戶的操做,主要經過鼠標和鍵盤等計算機外設觸發,點擊一次按鈕、在文本框中輸入一些字符、按下回車鍵等都是交互。
在網頁中,全部的交互都是經過事件的方式進行響應的。
交互是網頁的靈魂
,不能進行交互的網頁就像乾涸的河流,了無生氣。github
一個設計良好的組件應該包含如下特性:
複用性(Reuseability)
、組合性(Composability)
和擴展性(Scalability)
。數據庫
組件做爲一個獨立的單元,除了自身的特定功能以外,不該該包含任何業務相關的數據。
組件應該可以複用到任何業務中,只要該業務須要用到組件所包含的功能。
組件應該是資源獨立的,以加強組件的複用能力。antd
組件與組件之間能夠像積木同樣進行組合,組合以後的組件擁有子組件的全部功能,變得更強大。
組合的方式能夠是包裹別的組件,也能夠是做爲參數傳入別的組件中。函數
能夠基於現有的組件進行擴展,開發功能更加定製化的組件,以知足業務需求。
組件的可擴展能力依賴於接口的設計,接口要儘量的靈活,以應對不斷變化的需求。佈局
經過props
將數據傳遞到組件內部,以供組件自身或其子組件使用。
props是不可變的,這意味着咱們沒法在組件內部修改props的原始值,也意味着只有外部傳入了props,才能在組件內部獲取和使用它。spa
能夠經過兩種方式將組件內部的數據傳遞到組件外,一是經過ref
屬性(組件實例的引用),二是經過事件回調
(好比:onClick)
能夠經過全局context
的方式進行雙向通訊。
父組件聲明context對象,那麼其下全部的子組件,無論嵌套多深,均可以使用該對象的數據,而且能夠經過回調函數的方式將子組件的數據傳遞出來供父組件使用。
經過事件訂閱的方式能夠實現多個組件之間互相通訊。
經過自定義事件(Custom Event)
,任何組件均可以與其餘組件進行通信,採用的是發佈/訂閱模式,經過向事件對象上添加監聽和觸發事件來實現組件間通訊。
接下來經過廣告詳情頁面的開發來演示如何用積木理論來構建網頁。
設計圖以下:
將設計圖拆分紅有層次的積木結構。
最頂層拆分紅四個大積木:
其中的div標籤是爲了佈局方便加入的。
每一個大積木又能夠拆分紅若干小積木,中間層有些是不可拆分的原子積木,好比:Button、Checkbox;有些是由原子積木組合而成的複合積木,好比:DateRangePicker、Table。層次結構以下:
最底層的積木都是不可拆分的原子積木。
已經將積木的層次結構設計出來,接下來就要考慮每一個層次的積木怎麼製造的問題。
因爲廣告詳情涉及的積木衆多,這裏僅舉日期選擇組件(DatePicker)的例子來講明製造積木的方法,具體見如下連接:
日期選擇組件
對應的代碼:
<div className="ad-detail-container"> <Header /> <div className="content"> <div className="chart-detail-block"> <ChartBlock /> <DetailBlock /> </div> <TableBlock /> </div> </div>
Header對應的代碼:
<div className="header"> <div className="breadcrumb-area"> <div className="breadcrumb-current">gary audio</div> <div className="breadcrumb-from">From: <Breadcrumb className="breadcrumb" separator=""> <BreadcrumbItem href="http://www.qq.com">Campaign List</BreadcrumbItem> <span className="breadcrumb-seprator">> </span> <BreadcrumbItem href="http://www.qq.com">gary audio test</BreadcrumbItem> </Breadcrumb></div> </div> <div className="operation-area"> <Button icon="mail" className="flat" onClick={() => { console.log('You click "Send Report Email" button'); }}>Send Report Email</Button> <DateRangePicker onChange={(selectedDate) => { console.log('selected date:', selectedDate); }} /> </div> </div>
須要注意的是:爲了方便闡述積木理論的核心思想,這裏的原子組件大多都是已經造好的(使用antd組件庫),也能夠選擇本身製造,後面會舉例如何本身製造組件。
ChartBlock對應的代碼:
<div className="chart-block"> <Tabs defaultActiveKey="1"> <TabItem tab={<div className="tab-title">Ad performance</div>} key="1"> <LineChart /> </TabItem> <TabItem tab={<div className="tab-title">Audience</div>} key="2"> <BarChart /> </TabItem> </Tabs> </div>
DetailBlock對應的代碼:
<div className="detail-block"> <div className="detail-header"> <div className="detail-title">Ad detail</div> <div className="detail-operation"> <Button icon="edit" className="flat" onClick={() => { console.log('You click "Edit" button'); }}>Edit</Button> <Button icon="delete" className="flat" onClick={() => { console.log('You click "Delete" button'); }}>Delete</Button> <Button icon="eye" className="flat" onClick={() => { console.log('You click "Preview" button'); }}>Preview</Button> </div> </div> <List data={adDetail} config={detailConfig} /> </div>
TableBlock對應的代碼:
<div className="table-block"> <div className="table-operation-bar"> <Checkbox onChange={(event) => { console.log('Your checked status: ', event.target.checked); }}>Has delivery</Checkbox> <Select className="select-table-column" defaultValue="1" onChange={(value) => { console.log('You selected: ', value); }}> <Option value="1">Performance</Option> <Option value="2">Customize</Option> </Select> <Button icon="export" onClick={() => { console.log('You click "Export Data" button'); }}>Export Data</Button> </div> <Table dataSource={adsList} columns={columns} /> </div>
因爲篇幅緣由,這個案例並無包含交互的部分,不過基本可以闡述清楚積木理論的核心思想。
案例源碼:
前端開發積木理論案例