整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          干貨詳解:三向合并和 Git 的合并策略,手把手教你Git 合并

          者:lzaneli,騰訊 TEG 前端開發工程師

          “合并前文件還在的,合并后就不見了”、“我遇到 Git 合并的 bug 了” 是兩句經常聽到的話,但真的是 Git 的 bug 么?或許只是你的預期不對。本文通過講解三向合并和 Git 的合并策略,step by step 介紹 Git 是怎么做一個合并的,讓大家對 Git 的合并結果有一個準確的預期,并且避免發生合并事故。

          故事時間

          在開始正文之前,先來聽一下這個故事。

          如下圖,小明從節點 A 拉了一條 dev 分支出來,在節點 B 中新增了一個文件 http.js,并且合并到 master 分支,合并節點為 E。這個時候發現會引起線上 bug,趕緊撤回這個合并,新增一個 revert 節點 E'。過了幾天小明繼續在 dev 分支上面開發新增了一個文件 main.js,并在這個文件中 import 了 http.js 里面的邏輯,在 dev 分支上面一切運行正常。可當他將此時的 dev 分支合并到 master 時候卻發現,http.js 文件不見了,導致 main.js 里面的邏輯運行報錯了。但這次合并并沒有任何沖突。他又得重新做了一下 revert,并且迷茫的懷疑是 Git 的 bug。

          兩句經常聽到的話:

          —— ”合并前文件還在的,合并后就不見了“

          —— ”我遇到 Git 的 bug 了“

          相信很多同學或多或少在不熟悉 Git 合并策略的時候都會發生過類似上面的事情,明明在合并前文件還在的,為什么合并后文件就不在了么?一度還懷疑是 Git 的 bug。這篇文章的目的就是想跟大家講清楚 Git 是怎么去合并分支的,以及一些底層的基礎概念,從而避免發生如故事中的問題,并對 Git 的合并結果有一個準確的預期。

          如何合并兩個文件

          在看怎么合并兩個分支之前,我們先來看一下怎么合并兩個文件,因為兩個文件的合并是兩個分支合并的基礎。

          大家應該都聽說過“三向合并”這個詞,不知道大家有沒有思考過為什么兩個文件的合并需要三向合并,只有二向是否可以自動完成合并。如下圖

          很明顯答案是不能,如上圖的例子,Git 沒法確定這一行代碼是我修改的,還是對方修改的,或者之前就沒有這行代碼,是我們倆同時新增的。此時 Git 沒辦法幫我們做自動合并。

          所以我們需要三向合并,所謂三向合并,就是找到兩個文件的一個合并 base,如下圖,這樣子 Git 就可以很清楚的知道說,對方修改了這一行代碼,而我們沒有修改,自動幫我們合并這兩個文件為 Print("hello")。

          接下來我們了解一下什么是沖突?沖突簡單的來說就是三向合并中的三方都互不相同,即參考合并 base,我們的分支和別人的分支都對同個地方做了修改。

          Git 的合并策略

          了解完怎么合并兩個文件之后,我們來看一個使用 git merge 來做分支合并。如上圖,將 master 分支合并到 feature 分支上,會新增一個 commit 節點來記錄這次合并。

          Git 會有很多合并策略,其中常見的是 Fast-forward、Recursive 、Ours、Theirs、Octopus。下面分別介紹不同合并策略的原理以及應用場景。默認 Git 會幫你自動挑選合適的合并策略,如果你需要強制指定,使用git merge -s <策略名字>

          了解 Git 合并策略的原理可以讓你對 Git 的合并結果有一個準確的預期。

          Fast-forward

          Fast-forward 是最簡單的一種合并策略,如上圖中將 some feature 分支合并進 master 分支,Git 只需要將 master 分支的指向移動到最后一個 commit 節點上。

          Fast-forward 是 Git 在合并兩個沒有分叉的分支時的默認行為,如果不想要這種表現,想明確記錄下每次的合并,可以使用git merge --no-ff。

          Recursive

          Recursive 是 Git 分支合并策略中最重要也是最常用的策略,是 Git 在合并兩個有分叉的分支時的默認行為。其算法可以簡單描述為:遞歸尋找路徑最短的唯一共同祖先節點,然后以其為 base 節點進行遞歸三向合并。說起來有點繞,下面通過例子來解釋。

          如下圖這種簡單的情況,圓圈里面的英文字母為當前 commit 的文件內容,當我們要合并中間兩個節點的時候,找到他們的共同祖先節點(左邊第一個),接著進行三向合并得到結果為 B。(因為合并的 base 是“A”,下圖靠下的分支沒有修改內容仍為“A”,下圖靠上的分支修改成了“B”,所以合并結果為“B”)。

          但現實情況總是復雜得多,會出現歷史記錄鏈互相交叉等情況,如下圖:

          當 Git 在尋找路徑最短的共同祖先節點的時候,可以找到兩個節點的,如果 Git 選用下圖這一個節點,那么 Git 將無法自動的合并。因為根據三向合并,這里是是有沖突的,需要手動解決。(base 為“A“,合并的兩個分支內容為”C“和”B“)

          而如果 Git 選用的是下圖這個節點作為合并的 base 時,根據三向合并,Git 就可以直接自動合并得出結果“C”。(base 為“B“,合并的兩個分支內容為”C“和”B“)

          作為人類,在這個例子里面我們很自然的就可以看出來合并的結果應該是“C”(如下圖,節點 4、5 都已經是“B”了,節點 6 修改成“C”,所以合并的預期為“C”)

          那怎么保證 Git 能夠找到正確的合并 base 節點,盡可能的減少沖突呢?答案就是,Git 在尋找路徑最短的共同祖先節點時,如果滿足條件的祖先節點不唯一,那么 Git 會繼續遞歸往下尋找直至唯一。還是以剛剛這個例子圖解。

          如下圖所示,我們想要合并節點 5 和節點 6,Git 找到路徑最短的祖先節點 2 和 3。

          因為共同祖先節點不唯一,所以 Git 遞歸以節點 2 和節點 3 為我們要合并的節點,尋找他們的路徑最短的共同祖先,找到唯一的節點 1。

          接著 Git 以節點 1 為 base,對節點 2 和節點 3 做三向合并,得到一個臨時節點,根據三向合并的結果,這個節點的內容為“B”。

          再以這個臨時節點為 base,對節點 5 和節點 6 做三向合并,得到合并節點 7,根據三向合并的結果,節點 7 的內容為“C”

          至此 Git 完成遞歸合并,自動合并節點 5 和節點 6,結果為“C”,沒有沖突。

          Recursive 策略已經被大量的場景證明它是一個盡量減少沖突的合并策略,我們可以看到有趣的一點是,對于兩個合并分支的中間節點(如上圖節點 4,5),只參與了 base 的計算,而最終真正被三向合并拿來做合并的節點,只包括末端以及 base 節點。

          需要注意 Git 只是使用這些策略盡量的去幫你減少沖突,如果沖突不可避免,那 Git 就會提示沖突,需要手工解決。(也就是真正意義上的沖突)。

          Ours & Theirs

          Ours 和 Theirs 這兩種合并策略也是比較簡單的,簡單來說就是保留雙方的歷史記錄,但完全忽略掉這一方的文件變更。如下圖在 master 分支里面執行git merge -s ours dev,會產生藍色的這一個合并節點,其內容跟其上一個節點(master 分支方向上的)完全一樣,即 master 分支合并前后項目文件沒有任何變動。

          而如果使用 theirs 則完全相反,完全拋棄掉當前分支的文件內容,直接采用對方分支的文件內容。

          這兩種策略的一個使用場景是比如現在要實現同一功能,你同時嘗試了兩個方案,分別在分支是 dev1 和 dev2 上,最后經過測試你選用了 dev2 這個方案。但你不想丟棄 dev1 的這樣一個嘗試,希望把它合入主干方便后期查看,這個時候你就可以在 dev2 分支中執行git merge -s ours dev1。

          Octopus

          這種合并策略比較神奇,一般來說我們的合并節點都只有兩個 parent(即合并兩條分支),而這種合并策略可以做兩個以上分支的合并,這也是 git merge 兩個以上分支時的默認行為。比如在 dev1 分支上執行git merge dev2 dev3。

          他的一個使用場景是在測試環境或預發布環境,你需要將多個開發分支修改的內容合并在一起,如果不用這個策略,你每次只能合并一個分支,這樣就會導致大量的合并節點產生。而使用 Octopus 這種合并策略就可以用一個合并節點將他們全部合并進來。

          Git rebase

          git rebase 也是一種經常被用來做合并的方法,其與 git merge 的最大區別是,他會更改變更歷史對應的 commit 節點。

          如下圖,當在 feature 分支中執行 rebase master 時,Git 會以 master 分支對應的 commit 節點為起點,新增兩個全新的 commit 代替 feature 分支中的 commit 節點。其原因是新的 commit 指向的 parent 變了,所以對應的 SHA1 值也會改變,所以沒辦法復用原 feature 分支中的 commit。(這句話的理解需要這篇文章的基礎知識)

          對于合并時候要使用 git merge 還是 git rebase 的爭論,我個人的看法是沒有銀彈,根據團隊和項目習慣選擇就可以。git rebase 可以給我們帶來清晰的歷史記錄,git merge 可以保留真實的提交時間等信息,并且不容易出問題,處理沖突也比較方便。唯一有一點需要注意的是,不要對已經處于遠端的多人共用分支做 rebase 操作。

          我個人的一個習慣是:對于本地的分支或者確定只有一個人使用的遠端分支用 rebase,其余情況用 merge。

          rebase 還有一個非常好用的東西叫 interactive 模式,使用方法是git rebase -i。可以實現壓縮幾個 commit,修改 commit 信息,拋棄某個 commit 等功能。比如說我要壓縮下圖 260a12a5、956e1d18,將他們與 9dae0027 合并為一個 commit,我只需將 260a12a5、956e1d18 前面的 pick 改成“s”,然后保存就可以了。

          限于篇幅,git rebase -i 還有很多實用的功能暫不展開,感興趣的同學可以自己研究一下。

          總結

          現在我們再來看一下文章開頭的例子,我們就可以理解為什么最后一次 merge 會導致 http.js 文件不見了。根據 Git 的合并策略,在合并兩個有分叉的分支(上圖中的 D、E‘)時,Git 默認會選擇 Recursive 策略。找到 D 和 E’的最短路徑共同祖先節點 B,以 B 為 base,對 D,E‘做三向合并。B 中有 http.js,D 中有 http.js 和 main.js,E’中什么都沒有。根據三向合并,B、D 中都有 http.js 且沒有變更,E‘刪除了 http.js,所以合并結果就是沒有 http.js,沒有沖突,所以 http.js 文件不見了。

          這個例子理解原理之后解決方法有很多,這里簡單帶過兩個方法:1. revert 節點 E'之后,此時的 dev 分支要拋棄刪除掉,重新從 E'節點拉出分支繼續工作,而不是在原 dev 分支上繼續開發節點 D;2. 在節點 D 合并回 E’節點時,先 revert 一下 E‘節點生成 E’‘(即 revert 的 revert),再將節點 D 合并進來。

          Git 有很多種分支合并策略,本文介紹了 Fast-forward、Recursive、Ours/Theirs、Octopus 合并策略以及三向合并。掌握這些合并策略以及他們的使用場景可以讓你避免發生一些合并問題,并對合并結果有一個準確的預期。

          希望這篇文章對大家有用,感興趣的同學可以逛一逛我的博客 www.lzane.com 或看看我的其他文章。

          參考

          • 三向合并 http://blog.plasticscm.com/2016/02/three-way-merging-look-under-hood.html
          • Recursive 合并【視頻】https://www.youtube.com/watch?v=Lg1igaCtAck
          • 書籍 Scott Chacon, Ben Straub - Pro Git-Apress (2014)
          • 書籍 Jon Loeliger, Matthew McCullough - Version Control with Git, 2nd Edition - O’Reilly Media (2012)

          天的主要分享的是一些最基本、最常用的標簽:<img/>、<a></a>、<table></table>、<ul></ul>,以及文件路徑。

          首先,先來了解一下<img/>標簽,它表示圖片標簽,在頁面中會出現很多的圖像,主要的編碼方式就是通過<img/>來實現的;那是怎么實現的呢?它通過一些自己的屬性來規定了這個圖像的樣式,要實現一個圖像最基本的屬性有 src屬性、width屬性、height屬性、alt屬性,詳解一下他們的屬性分別是做什么的,是實現圖像的哪一個部分的?

          src屬性:就是你要放置圖像,該圖像的文件路徑,你的文件是放在C盤里面的文件還是D盤里面的文件,那么src就是這個圖像的路徑;

          width屬性:就是你的圖像的寬度,同理height就是圖像的高度;

          alt屬性:是指一種提示,比如你的鼠標在移動到你的圖片的時候或有文字提示、或者因為某種原因圖片不能正常顯示的時候,會有直接文字提示;

          完整的語法:<img src="圖像路徑" width="100px" height="100px" alt="提示"/>

          接下來,我們分享<a></a>鏈接標簽,它是一個能夠實現跳轉的標簽,在小編還是沒有完全總結<a>標簽的情況下,可以先簡單的可以理解為從一個頁面跳轉到另外一個頁面。要實現一個跳轉也是需要它自有的一些屬性來完成,href屬性,target屬性,name屬性。解一下他們的屬性分別是做什么的,是實現跳轉的哪一個部分的?

          href屬性:就是你要跳轉到哪個頁面,就是這個頁面的路徑;

          target屬性:就是你要跳轉的網頁的打開方式,它有自己的備選答案,其中_blank代表在新的標簽中打開,_self代表在當前頁面中打開(這個是缺省值)

          name屬性:就是定義錨點名稱(只有當<a>標簽當做錨點使用時需要該屬性)

          完整的語法:<a href="網頁路徑" target=“_blank”></.a>

          總結一下<a>標簽常用的表現形式(作用)

          1、網頁面間跳轉

          <a href="頁面路徑"></a>

          2、頁面上的文檔(資源)下載

          <a href="資源路徑"></a> 其中:資源路徑是指非html,htm,txt的資源,一般常見有為壓縮包形式 <a href="xxx.rar">下載</a>

          3、返回頁面頂部的空連接

          <a href="#">返回頂部</a> 跳轉到本頁(一般在開發、測試階段使用)

          4、電子郵件鏈接

          <a href="mailto:zhaoxu@tarena.com.cn"></a>

          5、鏈接到Javascript

          <a href="javascript:js代碼段落"></a> 就是在點擊<a>標簽的時候,執行一段js代碼

          錨點:就是在頁面的任意位置處定義一個標識,隨時隨地的都可以跳轉到這個標識上;如果你想要在同一個頁面中,快速的到達某個點,這時候用錨點的方式是非常好的。

          錨點的使用方式(2步驟):

          1、定義錨點 <a name="anchorName"></a>

          2、鏈接到錨點 <a href="#anchorName">文本 或 圖像</a> 或者 <a href="url#anchorName"></a>

          第三、關于<table>表格標簽

          表格:有行有列,按照一定的格式(從左到右,從上到下)排列里面的內容;它能組織結構化的信息,按照一定的格式來進行數據顯示

          要想創建表格:

          1.定義表格:<table></table>

          2. 定義行:<tr></tr>

          3.創建列(單元格):<td></td>

          注意:原始的表格中,每行的列數全部都是統一的。

          在一些情況下,表格會有:表頭,表主體,表尾

          表頭:<thead></thead>

          表主體:<tbody></tbody>

          表尾:<tfoot></tfoot>

          實戰:創建一個表格,有4行3列

          <table>

          <tr>

          <td></td>

          <td></td>

          <td></td>

          </tr>

          <tr>

          <td></td>

          <td></td>

          <td></td>

          </tr>

          <tr>

          <td></td>

          <td></td>

          <td></td>

          </tr>

          <tr>

          <td></td>

          <td></td>

          <td></td>

          </tr>

          </table>

          表格的屬性:表格也是通過自己的屬性來形成自己風格的table

          width:寬度

          height:高度

          align:水平對齊方式(left,center,right)

          border:設置表格的變寬,以px(像素)為單位

          cellpadding:內邊距,(單元格邊框與內容之間的距離)

          cellspacing:外邊距,(單元格與單元格之間的距離)

          bgcolor:表格背景顏色

          align:設置該行內容的水平對齊方式(left,center,right)

          valign:設置該行內容的垂直對齊方式(top,middle,bottom)

          colspan:單元格跨列(向右合并單元格)

          rowspan:單元格跨行(向下合并單元格)

          表格標題:即表格第一行,文字加粗 語法:<caption>標題</caption>

          <table>

          <caption></caption>

          <tr>

          <td></td>

          </tr>

          </table>

          表格除了中規中矩,還有復雜應用,可以形成不規則的表格,實現不規則表格主要是通過跨列:colspan、跨行:rowspan

          第四:關于列表<ul>

          列表根據使用情景,可以分為:有序列表、無序列表、自定義列表,其中

          1、有序列表

          語法:<ol><li></li> 列表項</ol>

          常用屬性:

          type : 列表類型,取值可以為:

          1 :表示數字(默認值)

          a : 表示小寫字母

          A : 表示大寫字母

          i : 表示小寫羅馬數字

          I : 表示大寫羅馬數字

          start : 起始編號

          2、無序列表

          語法:<ul><li></li></ul>

          屬性: type 取值可以為:

          disc : 實心圓(默認)

          circle : 空心圓

          square : 實心矩形

          3、自定義列表

          <dl> 定義列表

          <dt></dt> 列表內容標題

          <dd></dd> 列表數據

          </dl>

          有序、無序使用場景:

          1、從上到下,只有一列顯示數據

          2、從左到右,只有一行顯示數據(導航)

          自定義列表使用場景:做圖文混排的布局

          最后是關于文件路徑,即URL

          目錄結構的表示方式

          URL : Uniform Resource Locator , 統一資源定位器 ,俗稱,路徑

          作用:用來標識網絡中的資源位置

          http://www.baidu.com

          images/logo.gif

          URL的三種形式: 絕對路徑 相對路徑 根相對路徑

          1、絕對路徑

          文件從最高級目錄開始的完整的路徑

          絕對路徑就是完整的URL

          1、從本機目錄結構查找,從盤符開始

          C:\xxx\xxx.jpg

          2、網絡資源目錄結構開始查找

          協議、主機、目錄路徑、文件名稱

          http://www.baidu.com/images/logo.jpg

          2、相對路徑

          相對于當前文件的位置,查找資源文件

          1、同級目錄(直接找)

          直接輸入資源文件名稱即可

          2、子級目錄(先進入)

          先進入到指定文件夾,再查找資源文件

          3、父級目錄(先返回)

          先返回到指定的父級目錄出,再查找指定資源文件

          ../ : 表示返回上一級

          ../../images/logo.png

          3、根相對路徑

          file:///C:/zhaoxu/ ........ 本地訪問

          http://www.baidu.com

          http://localhost/ ...... 從服務器訪問數據

          三部分 附錄(因為暫時不支持插入超鏈接所以部分內容無法顯示


          附錄一 DIV命名規范


          • 企業DIV使用頻率高的命名方法
          • 網頁內容類
          • 標題: title
          • 摘要: summary
          • 箭頭: arrow
          • 商標: label
          • 網站標志: logo
          • 轉角/圓角:corner
          • 橫幅廣告: banner
          • 子菜單: subMenu
          • 搜索: search
          • 搜索框: searchBox
          • 登錄: login
          • 登錄條:loginbar
          • 工具條: toolbar
          • 下拉: drop
          • 標簽頁: tab
          • 當前的: current
          • 列表: list
          • 滾動: scroll
          • 服務: service
          • 提示信息: msg
          • 熱點:hot
          • 新聞: news
          • 小技巧: tips
          • 下載: download
          • 欄目標題: title
          • 熱點: hot
          • 加入:joinus
          • 注冊: regsiter
          • 指南: guide
          • 友情鏈接: friendlink
          • 狀態: status
          • 版權: copyright
          • 按鈕: btn
          • 合作伙伴: partner
          • 投票: vote
          • 左右中:left right center


          • 注釋的寫法: /* Footer */ 內容區/* End Footer */
          • id的命名:
          • 頁面結構
          • 容器: container
          • 頁頭:header
          • 內容:content/container
          • 頁面主體:main
          • 頁尾:footer
          • 導航:nav
          • 側欄:sidebar
          • 欄目:column
          • 頁面外圍控制整體布局寬度:wrapper
          • 左右中:left right center

          • 導航
          • 導航:nav
          • 主導航:mainbav
          • 子導航:subnav
          • 頂導航:topnav
          • 邊導航:sidebar
          • 左導航:leftsidebar
          • 右導航:rightsidebar
          • 菜單:menu
          • 子菜單:submenu
          • 標題: title
          • 摘要: summary

          • 功能
          • 標志:logo
          • 廣告:banner
          • 登陸:login
          • 登錄條:loginbar
          • 注冊:regsiter
          • 搜索:search
          • 功能區:shop
          • 標題:title
          • 加入:joinus
          • 狀態:status
          • 按鈕:btn
          • 滾動:scroll
          • 標簽頁:tab
          • 文章列表:list
          • 提示信息:msg
          • 當前的:current
          • 小技巧:tips
          • 圖標: icon
          • 注釋:note
          • 指南:guild
          • 服務:service
          • 熱點:hot
          • 新聞:news
          • 下載:download
          • 投票:vote
          • 合作伙伴:partner
          • 友情鏈接:link
          • 版權:copyright

          • class的命名:
          • 顏色:使用顏色的名稱或者16進制代碼,如
          • .red { color: red; }
          • .f60 { color: #f60; }
          • .ff8600 { color: #ff8600; }
          • 字體大小,直接使用”font+字體大小”作為名稱,如
          • .font12px { font-size: 12px; }
          • .font9px {font-size: 9pt; }
          • 對齊樣式,使用對齊目標的英文名稱,如
          • .left { float:left; }
          • .bottom { float:bottom; }
          • 標題欄樣式,使用”類別+功能”的方式命名,如
          • .barnews { }
          • .barproduct { }

          • 注意事項::
          • 一律小寫;
          • 盡量用英文;
          • 不加中杠和下劃線;
          • 盡量不縮寫,除非一看就明白的單詞.


          • 推薦的 CSS 書寫順序:
          • 顯示屬性
          • display
          • list-style
          • position
          • float
          • clear
          • 自身屬性
          • width
          • height
          • margin
          • padding
          • border
          • background
          • 文本屬性
          • color
          • font
          • text-decoration
          • text-align
          • vertical-align
          • white-space
          • other text
          • content

          附錄二 CSS精靈


          • CSS精靈原理以及應用
          • CSS雪碧的基本原理是把你的網站上用到的一些圖片整合到一張單獨的圖片中,從而減少你的網站的HTTP請求數量。
          • 該圖片使用CSS background和background-position屬性渲染,這也就意味著你的標簽變得更加復雜了,圖片是在CSS中定義,而非<img>標簽。
          • 一個簡單的例子:
          • 一張圖片作出一個按鈕的三個狀態
          • 一個鏈接用CSS做成按鈕的樣式,我們可以使用同一張圖片,完成按鈕的三個狀態,a:link,a:hover,a:active <a class="button" href="#">鏈接</a>
          • 加入右側的圖片為:200px 65px的三個按鈕圖拼合而成的圖片button.png,從上到下一次為按鈕的普通、鼠標滑過、鼠標點擊的狀態。則可以使用CSS進行定義。
          a {
           display:block; 
           width:200px; 
           height:65px; 
           line-height:65px; /*定義狀態*/
           text-indent:-2015px; /*隱藏文字*/
           background-image:url(button.png); /*定義背景圖片*/
           background-position:0 0;
           /*定義鏈接的普通狀態,此時圖像顯示的是頂上的部分*/
          }
          a:hover {
           background-position:0 -66px;
           /*定義鏈接的滑過狀態,此時顯示的為中間部分,向下取負值*/
          }
          a:active {
           background-position:0 -132px; 
           /*定 義鏈接的普通狀態,此時顯示的是底部的部分,向下取負值*/
          }
          
          • 更多的CSS雪碧,圖片更復雜,背景定位更精確。可能會用到大量的數值
          • 如:background:url(nav.png) -180px 24pxno-repeat; 來達到更精確的定位
          • 優點:
          • 減少加載網頁圖片時對服務器的請求次數
          • 可以合并多數背景圖片和小圖標,方便在任何位置使用,這樣不同位置的請求只需要調用一個圖片,從而減少對服務器的請求次數,降低服務器壓力,同時提高了頁面的加載速度,節約服務器的流量。
          • 提高頁面的加載速度
          • sprite技術的其中一個好處是圖片的加載時間(在有許多 sprite 時,單張圖片的加載時間)。由所需圖片拼成的一張 GIF圖片的尺寸會明顯小于所有圖片拼合前的大小。單張的 GIF只有相關的一個色表,而單獨分割的每一張 GIF 都有自己的一個色表,這就增加了總體的大小。因此,單獨的一張 JPEG 或者 PNGsprite 在大小上非常可能比把一張圖分成多張得來的圖片總尺寸小。
          • 減少鼠標滑過的一些bug
          • IE6不會主動預加載鼠標滑過即a:hover中的背景圖片,所以,如果使用多張圖片,鼠標滑過會出現閃白的現象。使用CSS雪碧,由于一張圖片即可,所以不會出現這種現象。
          • 不足:
          • CSS雪碧的最大問題是內存使用
          • 影響瀏覽器的縮放功能
          • 拼圖維護比較麻煩
          • 使CSS的編寫變得困難
          • CSS 雪碧調用的圖片不能被打印
          • 錯誤得使用 Sprites 影響可訪問性

          附錄三 一些tips解決方案


          頁面優化實踐


          • 從下面的幾個方面可以進行頁面的優化:
          • 減少請求數
          • 圖片合并
          • CSS文件合并
          • 減少內聯樣式
          • 避免在 CSS中使用 import
          • 減少文件大小
          • 選擇適合的圖片格式
          • 圖片壓縮
          • CSS 值縮寫(Shorthand Property)
          • 文件壓縮
          • 頁面性能
          • 調整文件加載順序
          • 減少標簽數量
          • 調整選擇器長度
          • 盡量使用CSS 制作顯示表現
          • 增強代碼可讀性與可維護性
          • 規范化
          • 語義化
          • 模塊化

          寫DIV+CSS 的一些常識


          • 不要使用過小的圖片做背景平鋪
          • 這就是為何很多人都不用 1px 的原因,這才知曉。寬高 1px 的圖片平鋪出一個寬高 200px 的區域,需要 200200=40, 000 次,占用資源
          • 無邊框
          • 推薦的寫法是 border:none;,哈哈,我一直在用這個。 border:0; 只是定義邊框寬度為零,但邊框樣式、顏色還是會被瀏覽器解析,占用資源
          • 慎用 通配符
          • 所謂通配符,就是將CSS 中的所有標簽均初始化,不管用的不用的,過時的先進的,一視同仁,這樣,大大的占用資源。要有選擇的初始化標簽。
          • CSS的十六進制顏色代碼縮寫
          • 習慣了縮寫及小寫,這才知道,原來不是推薦的寫法,為的是減少解析所占用的資源。但同時會增加文件體積。孰優孰劣,有待仔細考證。
          • 樣式放頭上,腳本放腳下。不內嵌,只外鏈
          • 堅決不用 CSS表達式
          • 使用 引用樣式表,而不是通過@import 導入。
          • 一般來說,PNG比 GIF 要小,小得多。再者,GIF 中有多少顏色是被浪費的,很值得優化。
          • 千萬不要在 HTML中縮放圖片,一者不好看,二者占資源。
          • 正文字體最好用偶數
          • 12px、14px、16px,效果非常好。特例,15px。
          • block、ul、ol等上下留出至少一倍行距,左側至少兩倍行距,右側隨意。
          • 段落之間,至少要有一倍行距
          • 強行指定某些元素的 line-height,正文 1.6倍于文字大小,標題1.3倍。
          • 中文標點用全角
          • 英文夾雜在中文中,左右空格,半角。
          • 中文字體的粗體和斜體,遠離較好

          常用代碼片段


          • 雅虎工程師提供的CSS初始化示例代碼【僅供參考】
          • 可以在html頭文件中直接引用,從而避免瀏覽器的不兼容帶來的錯誤。
          body,
          div,
          dl,
          dt,
          dd,
          ul,
          ol,
          li,
          h1,
          h2,
          h3,
          h4,
          h5,
          h6,
          pre,
          code,
          form,
          fieldset,
          legend,
          input,
          button,
          textarea,
          p,
          blockquote,
          th,
          td { 
           margin:0; padding:0; 
          }
          body {
           background:#fff; 
           color:#555; 
           font-size:14px; 
           font-family: Verdana, Arial, Helvetica, sans-serif; 
          }
          td,
          th,
          caption { 
           font-size:14px;
          }
          h1, 
          h2, 
          h3, 
          h4, 
          h5, 
          h6 { 
           font-weight:normal; 
           font-size:100%; 
          }
          address, 
          caption,
          cite, 
          code, 
          dfn, 
          em, 
          strong,
          th, 
          var { 
           font-style:normal; 
           font-weight:normal;
          }
          a { 
           color:#555; 
           text-decoration:none; 
          }
          a:hover { 
           text-decoration:underline; 
          }
          img {
           border:none;
          }
          ol,ul,li { 
           list-style:none; 
          }
          input, 
          textarea, 
          select, 
          button { 
           font:14px Verdana,Helvetica,Arial,sans-serif; 
          }
          table { 
           border-collapse:collapse; 
          }
          html {
           overflow-y: scroll;
          } 
          .clearfix:after {
           content: "."; 
           display: block; 
           height:0; 
           clear:both; 
           visibility: hidden;
          }
          .clearfix { 
           *zoom:1; 
          }
          
          • mobile meta標簽
          <meta name=”viewport” content=”width=320,target-densitydpi=dpi_value,initial-scale=1, user-scalable=no”/>
          
          • 表格不被撐開
          table-layout: fixed; word-break: break-all;;border-collapse: collapse
          
          • 不設寬高居中
          <div id=”abc” style=”display:table;text-align:center;width:100%;height:100%;”>
           <span style=”background:#f00; display:table-cell; vertical-align:middle;”>
           <input type=”button” value=”item1″ />
           </span>
          </div>
          
          • 透明度的兼容代碼
          filter:alpha(opacity=50); /*1-100*/
          -moz-opacity:0.5; /*0-1.0*/
          -khtml-opacity:0.5; /*0-1.0*/
          opacity:0.5; /*0-1.0*/
          
          • 文字溢出點點省略
          white-space:nowrap;
          text-overflow:ellipsis;
          overflow:hidden;
          
          • 清除浮動的幾種方法
          • 方法一:投機取巧法 – 不推薦
          • 直接一個放到當作最后一個子標簽放到父標簽那兒,此方法屢試不爽,兼容性強
          • 方法二:overflow + zoom方法 –不推薦
          • .fix{overflow:hidden; zoom:1;}
          • 此方法優點在于代碼簡潔,涵蓋所有瀏覽器
          • 方法三:after + zoom方法 -推薦–此方法可以說是綜合起來最好的方法了
          • clearfix只應用在包含浮動子元素的父級元素上
          .fix{zoom:1;}
          .fix:after{
           display:block; 
           content:'clear'; 
           clear:both;
           line-height:0; 
           visibility:hidden;
          }
          
          • 更多代碼片段詳情
          • 實用的60個CSS代碼片段

          一些總結


          • 自動繼承屬性:
          • color
          • font
          • text-align
          • list-style
          • 非繼承屬性:
          • background
          • border
          • position
          • 具有破壞性的元素:
          • float
          • display:none;
          • position:absoblute/fixed/sticky;
          • 具有包裹性的元素:
          • display:inline-block/table-cell
          • position:absolute/fixed/sticky
          • overflow:hidden/scroll
          • 消除圖片底部間隙的方法
          • 圖片塊狀化-無基線對齊
          • img{display:block;}
          • 圖片底線對齊
          • img{vertical-align:bottom;}
          • 行高足夠小 - 基線位置上移
          • .box{line-height:0;}

          一些概念


          • BFC
          • BFC全稱”Block Formatting Context” 中文為“塊級格式化上下文”
          • 記住這么一句話:BFC元素特性表現原則就是,內部子元素再怎么翻江倒海,翻云覆雨都不會影響外部的元素
          • BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此
          • 優雅降級(graceful degradation)
          • 一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容
          • 漸進增強 progressive enhancement:
          • 是在瀏覽器開啟JavaScript功能后,如果瀏覽器版本不支持某些 JavaScript 能力,我們解決這種問題的方式
          • 平穩退化
          • 是在瀏覽器沒有JavaScript功能,或沒有開啟JavaScript功能情況下,我們解決這種問題的方式;

          學習從來不是一個人的事情,要有個相互監督的伙伴,想要學習或交流前端問題的小伙伴可以私信“學習”小明加群獲取2019web前端最新入門資料,一起學習,一起成長!


          主站蜘蛛池模板: 日韩亚洲一区二区三区| 国产精品成人一区二区| 无码日韩精品一区二区三区免费| 91秒拍国产福利一区| 中字幕一区二区三区乱码| 怡红院AV一区二区三区| 一区在线观看视频| 日本一区中文字幕日本一二三区视频| 精品国产不卡一区二区三区| 亚洲色偷精品一区二区三区| 精品视频一区二区三三区四区| 日韩人妻不卡一区二区三区 | 国产美女视频一区| 精品少妇ay一区二区三区| 久久久国产精品一区二区18禁| 精品国产区一区二区三区在线观看 | 亚洲日韩精品无码一区二区三区 | 无码人妻精品一区二区三区久久 | 91一区二区三区四区五区| 精品国产亚洲一区二区在线观看| 乱色熟女综合一区二区三区| 中文字幕一区二区三匹| 中文字幕亚洲乱码熟女一区二区| 国产精品亚洲专一区二区三区| 一区二区三区四区视频| 日韩精品一区二区三区中文 | 久久精品国内一区二区三区| 亚洲AV无码一区二区三区牲色| 无码乱人伦一区二区亚洲一| 美女毛片一区二区三区四区| 中文字幕VA一区二区三区| 国产麻豆精品一区二区三区v视界 国产美女精品一区二区三区 | 精品国产福利一区二区| 无码人妻少妇色欲AV一区二区| 亚洲Av高清一区二区三区| 国产精品视频一区二区三区无码| 色国产精品一区在线观看| 久久综合精品不卡一区二区| 亚洲日韩国产一区二区三区在线| 精品国产AV一区二区三区| 国产伦精品一区二区|