Qt Creator中提供了各種快捷鍵來加快開發進程。
如果需要查看或自定義快捷鍵,選擇工具->選項->環境->鍵盤??旖萱I按類別列出,可以在過濾器(Filter)處輸入命令名稱、標簽名稱或快捷鍵名稱,來快速定位想要查找的快捷鍵。
以紅顏色顯示的快捷鍵與某些功能相關聯。Qt Creator可以在當前上下文中執行該功能。如果幾個功能用同一個快捷鍵,那么就會產生沖突,Qt Creator不會執行任何功能。
鍵盤快捷鍵也可能與窗口管理器使用的快捷鍵沖突。這種情況下,Qt Creator的快捷鍵就不會起作用。通常,可以在窗口管理器中配置快捷鍵,但如果不行,則可以改變Qt Creator的快捷鍵。例如,在Ubuntu 11.10窗口管理器中使用了F10,因此默認的Qt Creator的鍵盤快捷鍵F10(單步調試)就不會在該系統上運行。
選擇工具->選項->環境->鍵盤。
從列表中選擇一個命令。
在快捷鍵設置的”Key sequence”處,有以下選擇:
(1) 輸入與選定命令關聯的快捷鍵。
(2) 選擇”Record”,按下要設置的快捷鍵,選擇”Stop Recording”來完成錄制。
恢復默認的快捷鍵,選擇”Reset”。
Qt Creator允許使用不同的鍵盤快捷鍵映射方案:
要導入鍵盤快捷鍵映射方案,單擊”Import…”,然后選擇要導入的快捷鍵映射方案.kms文件。
要導出鍵盤快捷鍵映射方案,單擊”Export…”,然后選擇要導出.kms文件的位置。
默認快捷鍵
下表列出了默認的快捷鍵,它們是由動作進行分類。
【領QT開發教程學習資料,點擊→「鏈接」←莬費領取,先碼住不迷路~】
動作 | 快捷鍵 |
打開文件或項目(O)… | Ctrl+O |
新建文件或項目(N)… | Ctrl+N |
在外部編輯器中打開 | Alt+V, Alt+I |
全選(A) | Ctrl+A |
刪除 | Del |
剪切(T) | Ctrl+X |
復制(C) | Ctrl+C |
粘貼 | Ctrl+V |
撤銷 | Ctrl+Y |
打印 | Ctrl+P |
保存 | Ctrl+S |
保存所有文件(L)… | CTRL+Shift+S |
關閉窗口 | Ctrl+W |
關閉所有文件 | Ctrl+Shift+W |
關閉當前文件 | Ctrl+F4 |
后退 | Alt+Left |
前進 | Alt+Right |
跳轉行(G)… | Ctrl+L |
歷史中下個打開的文件 | Ctrl+Shift+Tab |
切換到其他分欄 | Ctrl+E, O |
歷史中先前打開的文件 | Ctrl+Tab |
激活定位器 | Ctrl+K |
切換到歡迎模式 | Ctrl+1 |
切換到編輯模式 | Ctrl+2 |
切換到設計模式 | Ctrl+3 |
切換到調試模式 | Ctrl+4 |
切換到項目模式 | Ctrl+5 |
切換到分析模式 | Ctrl+6 |
切換到幫助模式 | Ctrl+7 |
切換問題窗口 | Alt+1 (Cmd+1 on OS X) |
切換搜索結果窗口 | Alt+2 (Cmd+2 on OS X) |
切換應用程序輸出窗口 | Alt+3 (Cmd+3 on OS X) |
切換編譯輸出窗口 | Alt+4 (Cmd+4 on OS X) |
切換其它輸出窗口 | Alt+編號 (Cmd+編號 on OS X) 編號為”輸出窗口”中的編號 |
激活書簽窗口 | Alt+M |
激活文件系統窗口 | Alt+Y |
激活打開文檔窗口 | Alt+O |
最大化輸出窗口 | Alt+9 |
輸出窗口-下一項 | F6 |
輸出窗口-上一項 | Shift+F6 |
激活項目窗口 | Alt+X |
全屏 | Ctrl+Shift+F11 |
切換側邊欄 | Alt+0 (Cmd+0 on OS X) |
撤銷 | Ctrl+Z |
移動到編輯模式。在編輯模式下:第一次按下將焦點移動到編輯器中,第二次按下關閉輔助窗口 | Esc |
退出Qt Creator | Ctrl+Q |
動作 | 快捷鍵 |
自動縮進 | Ctrl+I |
折疊 | Ctrl+< |
展開 | Ctrl+> |
在此范圍內觸發完成 | Ctrl+Space |
復制行 | Ctrl+Ins |
復制到行下 | Ctrl+Alt+Down |
復制到行上 | Ctrl+Alt+Up |
查看剪切板歷史 | Ctrl+Shift+V |
剪切行 | Shift+Del |
追加行 | Ctrl+J |
在當前行上方插入新行 | Ctrl+Shift+Enter |
在當前行下方插入新行 | Ctrl+Enter |
減小字體大小 | Ctrl+- (Ctrl+鼠標滾輪向下) |
增加字體大小 | Ctrl++ (Ctrl+鼠標滾輪向上) |
重置字體大小 | Ctrl+0 |
切換Vim的編輯風格 | Alt+V, Alt+V |
分欄 | Ctrl+E, 2 |
左右分欄 | Ctrl+E, 3 |
刪除所有分割 | Ctrl+E, 1 |
刪除當前分割 | Ctrl+E, 0 |
全選 | Ctrl+A |
跳轉至塊結尾 | Ctrl+] |
跳轉至塊開始 | Ctrl+[ |
跳轉至以}結尾的塊 | Ctrl+} |
跳轉至以{開始的塊 | Ctrl+{ |
向下移動當前行 | Ctrl+Shift+Down |
向上移動當前行 | Ctrl+Shift+Up |
在此范圍激活重構 | Alt+Enter |
重新包裝段 | Ctrl+E, R |
選擇當前塊,第二次按下選擇父塊 | Ctrl+U |
啟用文本換行 | Ctrl+E, Ctrl+W |
注釋選中的內容 | Ctrl+/ |
可視化的空白 | Ctrl+E, Ctrl+V |
調整大小 | Ctrl+J |
網格布局 | Ctrl+G |
水平布局 | Ctrl+H |
垂直布局 | Ctrl+L |
預覽 | Alt+Shift+R |
編輯信號和槽 | F4 |
切換書簽 | CTRL+M |
下個書簽 | Ctrl+. |
上個書簽 | Ctrl+, |
取得代碼片段 | Alt+C, Alt+F |
粘貼代碼片段 | Alt+C, Alt+P |
查找所有引用 | Ctrl+Shift+U |
跟隨鼠標下的符號 | F2 |
重命名光標所在符號 | Ctrl+Shift+R |
切換函數聲明/定義 | Shift+F2 |
打開類型層次窗口 | Ctrl+Shift+T |
切換頭文件/源文件 | F4 |
選中的文本變小寫 | Alt+U |
選中的文本變大寫 | Alt+Shift+U |
在JavaScript中執行靜態檢查來查找共同問題 | Ctrl+Shift+C |
查找和替換 | Ctrl+F |
向下查找 | F3 |
向上查找 | Shift+F3 |
查找選中文本下一次出現 | Ctrl+F3 |
查找選中文本上一次出現 | Ctrl+Shift+F3 |
替換和查找下一個 | Ctrl+= |
打開高級搜索 | Ctrl+Shift+F |
錄制宏 | Alt+( |
停止錄制宏 | Alt+) |
播放最近的宏 | Alt+R |
顯示Qt Quick工具欄 | Ctrl+Alt+Space |
在FakeVim模式執行用戶行為 | Alt+V, n, 其中n是用戶動作的數量, 從1到9 |
動作 | 快捷鍵 |
切換背景 | Ctrl+[ |
顯示輪廓線 | Ctrl+] |
放大 | Ctrl++ |
縮小 | Ctrl+- |
適應屏幕 | Ctrl+= |
原始大小 | Ctrl+0 |
動作 | 快捷鍵 |
打開定義所選組件的QML文件 | F2 |
切換代碼編輯器/可視化編輯器 | F4 |
切換左側側邊欄 | Ctrl+Alt+0 |
切換右側側邊欄 | Ctrl+Alt+Shift+0 |
動作 | 快捷鍵 |
開始/繼續調試 | F5 |
停止調試 | Shift+F5 |
單步跳過 | F10 |
單步進入 | F11 |
單步跳出 | Shift+F11 |
切換斷點 | F9 |
運行到選擇的函數 | Ctrl+F6 |
執行到行 | Ctrl+F10 |
相反方向 | F12(暫無) |
動作 | 快捷鍵 |
構建項目 | Ctrl+B |
構建所有項目 | Ctrl+Shift+B |
新建項目… | Ctrl+Shift+N |
載入項目… | Ctrl+Shift+O |
選擇構建套件(Kit)構建和運行項目 | Ctrl+T |
運行 | Ctrl+R |
動作 | 快捷鍵 |
上下文相關幫助 | F1 |
在幫助模式下激活內容 | Ctrl+T(暫無) |
添加書簽 | Ctrl+M |
在幫助模式下激活索引 | Ctrl+I(暫無) |
重置字體大小 | Ctrl+0(暫無) |
在幫助模式下激活查找 | Ctrl+S(暫無) |
言
當我們拿到一個 PC 端頁面的設計稿的時候,往往會發現頁面的布局并不是隨意的,而是遵循的一定的規律:行與行之間會以某種方式對齊。對于這樣的設計稿,我們可以使用柵格布局來實現。
早在 Bootstrap 一統江湖的時代,柵格布局的概念就已深入人心,整個布局就是一個二維結構,包括列和行, Bootstrap 會把屏幕分成 12 列,還提供了一些非常方便的 CSS 名讓我們來指定每列占的寬度百分比,并且還通過媒體查詢做了不同屏幕尺寸的適應。
element-ui 也實現了類似 Bootstrap 的柵格布局系統,那么基于 Vue 技術棧,它是如何實現的呢?
需求分析
和 Bootstrap 12 分欄不同的是,element-ui 目標是提供的是更細粒度的 24 分欄,迅速簡便地創建布局,寫法大致如下:
<el-row> <el-col>aaa</el-col> <el-col>bbb</el-col> </el-row> <el-row> ... </el-row> 復制代碼
這就是二維布局的雛形,我們會把每個列的內容寫在 <el-col></el-col> 之間,除此之外,我們還需要支持控制每個 <el-col> 所占的寬度自由組合布局;支持分欄之間存在間隔;支持偏移指定的欄數;支持分欄不同的對齊方式等。
了解了 element-ui Layout 布局組件的需求后,我們來分析它的設計和實現。
設計和實現
組件的渲染
回顧前面的例子,從寫法上看,我們需要設計 2 個組件,el-row 和 el-col 組件,分別代表行和列;從 Vue 的語法上看,這倆組件都要支持插槽(因為在自定義組件標簽內部的內容都分發到組件的 slot 中了);從 HTML 的渲染結果上看,我們希望模板會渲染成:
<div class="el-row"> <div class="el-col">aaa</div> <div class="el-col">bbb</div> </div> <div class="el-row"> ... </div> 復制代碼
想達到上述需求,組件的模板可以非常簡單。
el-row 組件模板代碼如下:
<div class="el-row"> <slot></slot> </div> 復制代碼
el-col 組件代碼如下:
<div class="el-col"> <slot></slot> </div> 復制代碼
這個時候,新需求來了,我希望 el-row 和 el-col 組件不僅能渲染成 div,還可以渲染成任意我想指定的標簽。 那么除了我們要支持一個 tag 的 prop 之外,僅用模板是難以實現了。
我們知道 Vue 的模板最終會編譯成 render 函數,Vue 的組件也支持直接手寫 render 函數,那這個需求用 render 函數實現就非常簡單了。
el-row 組件:
render(h) { return h(this.tag, { class: [ 'el-row', ] }, this.$slots.default); } 復制代碼
el-col 組件:
render(h) { return h(this.tag, { class: [ 'el-col', ] }, this.$slots.default); } 復制代碼
其中,tag 是定義在 props 中的,h 是 Vue 內部實現的 $createElement 函數,如果對 render 函數語法還不太懂的同學,建議去看 Vue 的官網文檔 render 函數部分。
了解了組件是如何渲染之后,我們來給 Layout 組件擴展一些 feature 。
分欄布局
Layout 布局的主要目標是支持 24 分欄,即一行能被切成 24 份,那么對于每一個 el-col ,我們想要知道它的占比,只需要指定它在 24 份中分配的份數即可。
于是我們給剛才的示例加上一些配置:
<el-row> <el-col :span="8">aaa</el-col> <el-col :span="16">bbb</el-col> </el-row> <el-row> ... </el-row> 復制代碼
來看第一行,第一列 aaa 占 8 份,第二列 bbb 占 16 份??偣矊挾仁?24 份,經過簡單的數學公式計算,aaa 占總寬度的 1/3,而 bbb 占總寬度的 2/3,進而推導出每一列指定 span 份就是占總寬度的 span/24。
默認情況下 div 的寬度是 100% 獨占一行的,為了讓多個 el-col 在一行顯示,我們只需要讓每個 el-col 的寬占一定的百分比,即實現了分欄效果。設置不同的寬度百分比只需要設置不同的 CSS 即可實現,比如當某列占 12 份的時候,那么它對應的 CSS 如下:
.el-col-12 { width: 50% } 復制代碼
為了滿足 24 種情況,element-ui 使用了 sass 的控制指令,配合基本的計算公式:
.el-col-0 { display: none; } @for $i from 0 through 24 { .el-col-#{$i} { width: (1 / 24 * $i * 100) * 1%; } } 復制代碼
所以當我們給 el-col 組件傳入了 span 屬性的時候,只需要給對應的節點渲染生成對應的 CSS 即可,于是我們可以擴展 render 函數:
render(h) { let classList = []; classList.push(`el-col-${this.span}`); return h(this.tag, { class: [ 'el-col', classList ] }, this.$slots.default); } 復制代碼
這樣只要指定 span 屬性的列就會添加 el-col-${span} 的樣式,實現了分欄布局的需求。
分欄間隔
對于柵格布局來說,列與列之間有一定間隔空隙是常見的需求,這個需求的作用域是行,所以我們應該給 el-row 組件添加一個 gutter 的配置,如下:
<el-row :gutter="20"> <el-col :span="8">aaa</el-col> <el-col :span="16">bbb</el-col> </el-row> <el-row> ... </el-row> 復制代碼
有了配置,接下來如何實現間隔呢?實際上非常簡單,想象一下,2 個列之間有 20 像素的間隔,如果我們每列各往一邊收縮 10 像素,是不是看上去就有 20 像素了呢。
先看一下 el-col 組件的實現:
computed: { gutter() { let parent = this.$parent; while (parent && parent.$options.componentName !== 'ElRow') { parent = parent.$parent; } return parent ? parent.gutter : 0; } }, render(h) { let classList = []; classList.push(`el-col-${this.span}`); let style = {}; if (this.gutter) { style.paddingLeft = this.gutter / 2 + 'px'; style.paddingRight = style.paddingLeft; } return h(this.tag, { class: [ 'el-col', classList ] }, this.$slots.default); } 復制代碼
這里使用了計算屬性去計算 gutter,其實是比較有趣的,它通過 $parent 往外層查找 el-row,獲取到組件的實例,然后獲取它的 gutter 屬性,這樣就建立了依賴關系,一旦 el-row 組件的 gutter 發生變化,這個計算屬性再次被訪問的時候就會重新計算,獲取到新的 gutter。
其實,想在子組件去獲取祖先節點的組件實例,我更推薦使用 provide/inject 的方式去把祖先節點的實例注入到子組件中,這樣子組件可以非常方便地拿到祖先節點的實例,比如我們在 el-row 組件編寫 provide:
provide() { return { row: this }; } 復制代碼
然后在 el-col 組件注入依賴:
inject: ['row'] 復制代碼
這樣在 el-col 組件中我們就可以通過 this.row 訪問到 el-row 組件實例了。
使用 provide/inject 的好處在于不論組件層次有多深,子孫組件可以方便地訪問祖先組件注入的依賴。當你在編寫組件庫的時候,遇到嵌套組件并且子組件需要訪問父組件實例的時候,避免直接使用 this.$parent,盡量使用 provide/inject,因為一旦你的組件嵌套關系發生變化,this.$parent 可能就不符合預期了,而 provide/inject 卻不受影響(只要祖先和子孫的關系不變)。
在 render 函數中,我們會根據 gutter 計算,給當前列添加了 paddingLeft 和 paddingRight 的樣式,值是 gutter 的一半,這樣就實現了間隔 gutter 的效果。
那么這里能否用 margin 呢,答案是不能,因為設置 margin 會占用外部的空間,導致每列的占用空間變大,會出現折行的情況。
render 過程也是有優化的空間,因為 style 是根據 gutter 計算的,那么我們可以把 style 定義成計算屬性,這樣只要 gutter 不變,那么 style 就可以直接拿計算屬性的緩存,而不用重新計算,對于 classList 部分,我們同樣可以使用計算屬性。組件 render 過程的一個原則就是能用計算屬性就用計算屬性。
再來看一下 el-row 組件的實現:
computed: { style() { const ret = {}; if (this.gutter) { ret.marginLeft = `-${this.gutter / 2}px`; ret.marginRight = ret.marginLeft; } return ret; } }, render(h) { return h(this.tag, { class: [ 'el-row', ], style: this.style }, this.$slots.default); } 復制代碼
由于我們是通過給每列添加左右 padding 的方式來實現列之間的間隔,那么對于第一列和最后一列,左邊和右邊也會多出來 gutter/2 大小的間隔,顯然是不符合預期的,所以我們可以通過設置左右負 margin 的方式填補左右的空白,這樣就完美實現了分欄間隔的效果。
偏移指定的欄數
如圖所示,我們也可以指定某列的偏移,由于作用域是列,我們應該給 el-col 組件添加一個 offset 的配置,如下:
<el-row :gutter="20"> <el-col :offset="8" :span="8">aaa</el-col> <el-col :span="8">bbb</el-col> </el-row> <el-row> ... </el-row> 復制代碼
直觀上我們應該用 margin 來實現偏移,并且 margin 也是支持百分比的,因此實現這個需求就變得簡單了。
我們繼續擴展 el-col 組件:
render(h) { let classList = []; classList.push(`el-col-${this.span}`); classList.push(`el-col-offset-${this.offset}`); let style = {}; if (this.gutter) { style.paddingLeft = this.gutter / 2 + 'px'; style.paddingRight = style.paddingLeft; } return h(this.tag, { class: [ 'el-col', classList ] }, this.$slots.default); } 復制代碼
其中 offset 是定義在 props 中的,我們根據傳入的 offset 生成對應的 CSS 添加到 DOM 中。element-ui 同樣使用了 sass 的控制指令,配合基本的計算公式來實現這些 CSS 的定義:
@for $i from 0 through 24 { .el-col-offset-#{$i} { margin-left: (1 / 24 * $i * 100) * 1%; } } 復制代碼
對于不同偏移的分欄數,會有對應的 margin 百分比,就很好地實現分欄偏移需求。
對齊方式
當一行分欄的總占比和沒有達到 24 的時候,我們是可以利用 flex 布局來對分欄做靈活的對齊。
對于不同的對齊方式 flex 布局提供了 justify-content 屬性,所以對于這個需求,我們可以對 flex 布局做一層封裝即可實現。
由于對齊方式的作用域是行,所以我們應該給 el-row 組件添加 type 和 justify 的配置,如下:
<el-row type="flex" justify="center"> <el-col :span="8">aaa</el-col> <el-col :span="8">bbb</el-col> </el-row> <el-row> ... </el-row> 復制代碼
由于我們是對 flex 布局的封裝,我們只需要根據傳入的這些 props 去生成對應的 CSS,在 CSS 中定義 flex 的布局屬性即可。
我們繼續擴展 el-row 組件:
render(h) { return h(this.tag, { class: [ 'el-row', this.justify !== 'start' ? `is-justify-${this.justify}` : '', { 'el-row--flex': this.type === 'flex' } ], style: this.style }, this.$slots.default); } 復制代碼
其中 type 和 justify 是定義在 props 中的,我們根據它們傳入的值生成對應的 CSS 添加到 DOM 中,接著我們需要定義對應的 CSS 樣式:
@include b(row) { position: relative; box-sizing: border-box; @include utils-clearfix; @include m(flex) { display: flex; &:before, &:after { display: none; } @include when(justify-center) { justify-content: center; } @include when(justify-end) { justify-content: flex-end; } @include when(justify-space-between) { justify-content: space-between; } @include when(justify-space-around) { justify-content: space-around; } } } 復制代碼
element-ui 在編寫 sass 的時候主要遵循的是 BEM 的命名規則,并且編寫了很多自定義 @mixin 來配合樣式名的定義。
這里我們來花點時間來學習一下它們,element-ui 的自定義 @mixin 定義在 pacakages/theme-chalk/src/mixins/ 目錄中,我并不會詳細解釋這里面的關鍵字,如果你對 sass 還不熟悉,我建議在學習這部分內容的時候配合 sass 的官網文檔看。
mixins/config.scss 中定義了一些全局變量:
$namespace: 'el'; $element-separator: '__'; $modifier-separator: '--'; $state-prefix: 'is-'; 復制代碼
mixins/mixins.scss 中定義了 BEM 的自定義 @mixin,先來看一下定義組件樣式的 @mixin b:
@mixin b($block) { $B: $namespace+'-'+$block !global; .#{$B} { @content; } } 復制代碼
這個 @mixin 很好理解,$B 是內部定義的變量,它的值通過 $namespace+'-'+$block 計算得到,注意這里有一個 !global 關鍵字,它表示把這個局部變量變成全局的,意味著你也可以在其它 @mixin 中引用它。
通過 @include 我們就可以去引用這個 @mixin,結合我們的 case 來看:
@include b(row) { // xxx content } 復制代碼
會編譯成:
.el-row { // xxx content } 復制代碼
再來看表示修飾符的 @mixin m:
@mixin m($modifier) { $selector: &; $currentSelector: ""; @each $unit in $modifier { $currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","}; } @at-root { #{$currentSelector} { @content; } } } 復制代碼
這里是允許傳入的 $modifier 有多個,所以內部用了 @each,& 表示父選擇器,$selector 和 $currentSelector 是內部定義的 2 個局部變量,結合我們的 case 來看:
@mixin b(row) { @include m(flex) { // xxx content } } 復制代碼
會編譯成:
.el-row--flex { // xxx content } 復制代碼
有同學可能會疑問,難道不是:
.el-row { .el-row--flex { // xxx content } } 復制代碼
其實并不是,因為我們在該 @mixin 的內部使用了 @at-root 指令,它會把樣式規則定義在根目錄下,而不是嵌套在其父選擇器下。
最后來看一下表示同級樣式的 @mixin when:
@mixin when($state) { @at-root { &.#{$state-prefix + $state} { @content; } } } 復制代碼
這個 @mixin 也很好理解,結合我們的 case 來看:
@mixin b(row) { @include m(flex) { @include when(justify-center) { justify-content: center; } } } 復制代碼
會編譯成:
.el-row--flex.is-justify-center { justify-content: center; } 復制代碼
關于 BEM 的 @mixin,常用的還有 @mixin e,用于定義組件內部一些子元素樣式的,感興趣的同學可以自行去看。
再回到我們的 el-row 組件的樣式,我們定義了幾種flex 布局的對齊方式,然后通過傳入不同的 justify 來生成對應的樣式,這樣我們就很好地實現了靈活對齊分欄的需求。
響應式布局
element-ui 參照了 Bootstrap 的響應式設計,預設了五個響應尺寸:xs、sm、md、lg 和 xl。
允許我們在不同的屏幕尺寸下,設置不同的分欄配置,由于作用域是列,所以我們應該給 el-col 組件添加 xs xs、sm、md、lg 和 xl 的配置,如下:
<el-row type="flex" justify="center"> <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">aaa</el-col> <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">bbb</el-col> <el-col :xs="4" :sm="6" :md="8" :lg="9" :xl="11">ccc</el-col> <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="1">ddd</el-col> </el-row> <el-row> ... </el-row> 復制代碼
同理,我們仍然是通過這些傳入的 props 去生成對應的 CSS,在 CSS 中利用媒體查詢去實現響應式。
我們繼續擴展 el-col 組件:
render(h) { let classList = []; classList.push(`el-col-${this.span}`); classList.push(`el-col-offset-${this.offset}`); ['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => { classList.push(`el-col-${size}-${this[size]}`); }); let style = {}; if (this.gutter) { style.paddingLeft = this.gutter / 2 + 'px'; style.paddingRight = style.paddingLeft; } return h(this.tag, { class: [ 'el-col', classList ] }, this.$slots.default); } 復制代碼
其中,xs、sm、md、lg 和 xl 是定義在 props 中的,實際上 element-ui 源碼還允許傳入一個對象,可以配置 span 和 offset,但這部分代碼我就不介紹了,無非就是對對象的解析,添加對應的樣式。
我們來看一下對應的 CSS 樣式,以 xs 為例:
@include res(xs) { .el-col-xs-0 { display: none; } @for $i from 0 through 24 { .el-col-xs-#{$i} { width: (1 / 24 * $i * 100) * 1%; } .el-col-xs-offset-#{$i} { margin-left: (1 / 24 * $i * 100) * 1%; } } } 復制代碼
這里又定義了表示響應式的 @mixin res,我們來看一下它的實現:
@mixin res($key, $map: $--breakpoints) { // 循環斷點Map,如果存在則返回 @if map-has-key($map, $key) { @media only screen and #{inspect(map-get($map, $key))} { @content; } } @else { @warn "Undefeined points: `#{$map}`"; } } 復制代碼
這個 @mixns 主要是查看 $map 中是否有 $key,如果有的話則定義一條媒體查詢規則,如果沒有則拋出警告。
$map 參數的默認值是 $--breakpoints,定義在 pacakges/theme-chalk/src/common/var.scss 中:
$--sm: 768px !default; $--md: 992px !default; $--lg: 1200px !default; $--xl: 1920px !default; $--breakpoints: ( 'xs' : (max-width: $--sm - 1), 'sm' : (min-width: $--sm), 'md' : (min-width: $--md), 'lg' : (min-width: $--lg), 'xl' : (min-width: $--xl) ); 復制代碼
結合我們的 case 來看:
@include res(xs) { .el-col-xs-0 { display: none; } @for $i from 0 through 24 { .el-col-xs-#{$i} { width: (1 / 24 * $i * 100) * 1%; } .el-col-xs-offset-#{$i} { margin-left: (1 / 24 * $i * 100) * 1%; } } } 復制代碼
會編譯成:
@media only screen and (max-width: 767px) { .el-col-xs-0 { display: none; } .el-col-xs-1 { width: 4.16667% } .el-col-xs-offset-1 { margin-left: 4.16667% } // 后面循環的結果太長,就不貼了 } 復制代碼
其它尺寸內部的樣式定義規則也是類似,這樣我們就通過媒體查詢定義了各個屏幕尺寸下的樣式規則了。通過傳入 xs、sm 這些屬性的值不同,從而生成不同樣式,這樣在不同的屏幕尺寸下,可以做到分欄的占寬不同,很好地滿足了響應式需求。
基于斷點的隱藏類
Element 額外提供了一系列類名,用于在某些條件下隱藏元素,這些類名可以添加在任何 DOM 元素或自定義組件上。
我們可以通過引入單獨的 display.css:
import 'element-ui/lib/theme-chalk/display.css'; 復制代碼
它包含的類名及其含義如下:
我們來看一下它的實現,看一下 display.scss:
.hidden { @each $break-point-name, $value in $--breakpoints-spec { &-#{$break-point-name} { @include res($break-point-name, $--breakpoints-spec) { display: none !important; } } } } 復制代碼
實現很簡單,對 $--breakpoints-spec 遍歷,生成對應的 CSS 規則,$--breakpoints-spec 定義在 pacakges/theme-chalk/src/common/var.scss 中:
$--breakpoints-spec: ( 'xs-only' : (max-width: $--sm - 1), 'sm-and-up' : (min-width: $--sm), 'sm-only': "(min-width: #{$--sm}) and (max-width: #{$--md - 1})", 'sm-and-down': (max-width: $--md - 1), 'md-and-up' : (min-width: $--md), 'md-only': "(min-width: #{$--md}) and (max-width: #{$--lg - 1})", 'md-and-down': (max-width: $--lg - 1), 'lg-and-up' : (min-width: $--lg), 'lg-only': "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})", 'lg-and-down': (max-width: $--xl - 1), 'xl-only' : (min-width: $--xl), ); 復制代碼
我們以 xs-only 為例,編譯后生成的 CSS 規則如下:
.hidden-xs-only { @media only screen and (max-width:767px) { display: none !important; } } 復制代碼
本質上還是利用媒體查詢定義了這些 CSS 規則,實現了在某些屏幕尺寸下隱藏的功能。
總結
其實 Layout 布局還支持了其它一些特性,我不一一列舉了,感興趣的同學可以自行去看。Layout 布局組件充分利用了數據驅動的思想,通過數據去生成對應的 CSS,本質上還是通過 CSS 滿足各種靈活的布局。
學習完這篇文章,你應該徹底弄懂 element-ui Layout 布局組件的實現原理,并且對 sass 的 @mixin 以及相關使用到的特性有所了解,對組件實現過程中可以優化的部分,應該有自己的思考。
把不會的東西學會了,那么你就進步了,如果你覺得這類文章有幫助,也歡迎把它推薦給你身邊的小伙伴。
HTML5確實非常強大,小編之前也分享過很多基于HTML5 Canvas的動畫特效。但是你是否知道我們可以利用純CSS制作一些很酷的動畫效果?對,CSS3可以做到。2D炫酷動效是需要技術積累的,這里有4個重點大家可以著重掌握一下:
CSS3 2D炫酷動效
1. 了解canvas動效原理
就是不斷清除畫布再繪制,清除再繪制。
2. 一定的JS基本功
了解實例對象的屬性如何獲取,以及上下文this指代什么;如何有效地遍歷以及數據存儲等等。
3. 知道如何運用一些動畫算法
4. 了解canvas所有API,尤其基本的繪圖API
如何使用canvas繪制線條,繪制圓,繪制不規則圖形;如何描邊,如何填充,如何控制透明度等等,都是必須要牢固掌握的。因為,無論是是圓圈圈,還是角星星,都離不開這些基礎的API繪制。還需要了解圖像繪制API,例如,本demo的星星,實際上還可以基于圖片資源繪制,難度會稍微降低些,但可能要犧牲點效果。
css3選擇器的用途與重要性
css3選擇器是基于css2的一種創新,在css2的基礎上增加了目標偽類選擇器、語言偽類選擇器、UI元素狀態偽類選擇器、結構偽類選擇器、否定偽類選擇器。
大致有以下三點作用:
1.網頁代碼更簡潔,結構更清晰。
2.免除起名的煩惱。
3.避免css式樣不生效。
在主頁制作時采用css3技術,可以有效地對頁面的布局、字體、顏色、背景和其它效果實現更加精確的控制。只要對相應的代碼做一些簡單的修改,就可以改變同一頁面的不同部分,或者頁數不同的網頁的外觀和格式。css3提供了非常多新途徑去改善的設計工作,且做了不少重要的變化。
css3將完全向后兼容,所以沒有必要修改現在的設計來讓它們繼續運作。網絡瀏覽器也還將繼續支持css2。對我們來說,css3主要的影響是將可以使用新的可用的選擇器和屬性,這些會允許實現新的設計效果(譬如動態和漸變),而且可以很簡單的設計出現在的設計效果(比如說使用分欄)。
與css相比,使用css3有什么好處呢?最明顯的就是css3能讓頁面看起來非常炫、非常酷,使網站設計錦上添花,但它的好處遠遠不止這些。在大多數情況下,使用css3不僅有利于開發與維護,還能提高網站的性能。與此同時,還能增加網站的可訪問性、可用性,使網站能適配更多的設備,甚至還可以優化網站SEO,提高網站的搜索排名結果。
現在網站重視的更多的是用戶體驗,而優秀的動效則能使你的應用更具交互性,從而吸引更多用戶的使用。在網站中加入一些動效會讓整個頁面看起來很有動感。但是如果你對CSS3中定義動效還不熟練,就需要多加學習、多加練習。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。