網頁頂部導航欄增強(分爲左右兩部分;添加一個不被污染樣式的搜索框)

前置

本文須要對CSS,Vue,ElementUI有基本的瞭解。css

本文以ElementUI提供的導航菜單組件爲基礎。web

本文但願能在此組件基礎上實現如下內容:wordpress

  1. 中間一段空白把導航欄分爲左右兩個部分
  2. 在導航欄上加上一個搜索框,但不被 el-menu-item 的樣式污染。

先研究清楚ElementUI的css樣式

建立一個簡單的網頁,在其中使用ElementUI的導航菜單組件。工具

用Chrome之類的工具對網頁檢查(F12/Ctrl+Shift+I)後,從 Elements 標籤頁中定位到導航菜單組件在網頁中最後的實現元素。在檢查工具下方有 Styles 工具會顯示選中的元素的相關樣式。提取其中對元素位置有影響以及我不太熟悉的屬性。佈局

el-menu

提取後發現有這些和元素位置相關的設置測試

margin: 0;
padding-left: 0;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
padding-inline-start: 40px;

border-bottom: solid 1px #color;
border-right: none;

display:block;
position: relative;
-webkit-box-direction: normal;

list-style:none;

//使用了::before和::after建立了僞元素(注意,不是僞類。)
::before {
    display: table;
    content: "";
}

::after {
    display: table;
    content: "";
    clear: both;
}

對於出如今以上代碼中的但不熟悉不確認做用的屬性,以其爲關鍵詞(記得加引號以免搜索引擎錯誤解析)加css進行搜索,基本上就能找到滿意的答案。搜索引擎

margin-block-start 等屬性的做用 —— 影響不大spa

::before 和 ::after —— 僞類
clear:both
搞明白了這裏爲何要使用一個::after的僞元素,能夠預測該元素下的子元素全都是浮動元素。所以若是聽任無論的話,會形成浮動元素的高度不被父元素計算而致使父元素高度爲零直接崩掉。因此使用這樣一個僞類,因爲這個僞類不能容許左右有浮動元素,因此它會使本身的上外邊界碰着浮動元素(理想情況下應該排成一行)的那一行的下邊界,而這一行的高度(也即浮動元素的高度)就會被計算爲父元素的高度了。實際上若是這個僞類本身有高度好比60px,浮動元素那一行的最大高度爲60px,則父元素的高度就會是120px了。ssr

box-direction —— 影響不大code

在解決了有問題的樣式屬性後發現,其實整個 el-menu 的最終實現很簡單:使用positive:relative但並不帶有left top 這一類設置的屬性,因此說元素仍是留在原地。這裏設置positiverelative的理由應當是輔助以後的子元素即導航欄內部的 item 的定位(position:absolute時相對的元素如果position:static這一默認值是會被無視的)。

el-menu-item

float: left;
position: relative;
display: list-item;

margin: 0;
padding: 0 20px;
height: 60px;
line-height: 60px;
font-size:14px;
box-sizing: border-box;
text-align: -webkit-match-parent;

white-space: nowrap;
cursor: pointer;

float:leftdisplay:list-item同時使用第一時間可能想不明白,但通過本身建立更簡單的樣例進行測試,能夠這麼理解:float:left先執行肯定下本身的位置,而後執行position:relative,即relative的相對定位相對的「本來的位置」是float:left以後的位置。而之類因爲又沒有設置top left 之類的屬性,能夠認爲這是爲了在其內部再放其它組件的話輔助定位用的。

display: list-item —— 從官方文檔來看意思就是說配置這個list-item這個display屬性的元素表現出<ul>的子元素<li>的樣式,從而能夠爲它配置list-style,而且這是在沒有<ul>這種display的父元素的基礎上的。實際上它的父元素也確實是display:block

white-space —— white-space CSS 屬性是用來設置如何處理元素中的空白。

cursor —— cursor 屬性規定要顯示的光標的類型(形狀)。

那麼最基本的兩個組件最終生成的元素的CSS已經分析完了。動手試試咱們一開始的目標吧。

目標

  1. 中間一段空白把導航欄分爲左右兩個部分
  2. 在導航欄上加上一個搜索框,但不被 el-menu-item 的樣式污染。

目標1

個人第一個想法是建立一個 el-menu-item 給它寬度可是不給它內容同時讓它disable="true"

<el-menu-item index="1" v-show="!logined">淘寶網</el-menu-item>
<el-menu-item index="" disabled="true" id="el-menu-item-placeholder1"></el-menu-item>
<el-menu-item index="2">登陸</el-menu-item>
<el-menu-item index="3">註冊</el-menu-item>

#el-menu-item-placeholder1 {
    width: 80%;
}

在此狀態下建立的導航欄中間確實有了很大一塊空白做爲區隔,但仍然有以下問題:

  • 鼠標懸停在空白上時由於:disabled="true"致使鼠標會變成一個禁止通行的圖標。
  • 頁面縮小到1000px左右時就已經會讓右邊的「登陸」「註冊」新開一行,把整個佈局弄得很糟糕。

對於第一個問題,能夠經過cursor屬性解決?設置cursor: default;於咱們自定義的做爲佔位符的空白格 el-menu-item 樣式中,就解決了。

對於第二個問題,三個組件總共寬度爲218px,佔據20%的寬度,則要求100%寬度大於1090px纔會不崩盤。因此能夠設置 el-menu 的類的樣式解決這個問題

.el-menu {
    min-width: 1090px;
}
#el-menu-item-placeholder1 {
    width: 80%;
    max-width: 80%;
    cursor: default;
}

目標2

在解決目標1的基礎上,其實已經有了目標2的思路:設置一個:disable="true"的 el-menu-item 來放置一個 el-input 輸入框。對這個 el-menu-item 標記 id 屬性,而後經過id選擇器設置cursor:default

實際測試時發現整個輸入框被導航欄的背景色給灰濛濛地上了一層。顯然這一反作用是因爲將起禁用而致使的。(對比不由用時的輸入框很正常)。因此用檢查工具查看此時的元素,發現其class屬性多了一個is-disabled,從而引入了 ElementUI 自帶的樣式中的 opacity: 0.25 才致使的。那經過id選擇器進一步將其覆蓋便可。

最終代碼以下:

<el-menu-item index="1" v-show="!logined">淘寶網</el-menu-item>
<el-menu-item :disabled="true" id="el-menu-item-placeholder1"></el-menu-item>
<el-menu-item id="el-menu-item-searchinput-container" :disabled="true">
    <el-input v-model="input" placeholder="搜索欄"></el-input>
</el-menu-item>

<el-menu-item index="2">登陸</el-menu-item>
<el-menu-item index="3">註冊</el-menu-item>

.el-menu {
    min-width: 1090px;
}
#el-menu-item-placeholder1 {
    width: 80%;
    max-width: 80%;
    cursor: default;
}
#el-menu-item-searchinput-container {
    cursor: default;
    opacity: 1;
}

最初的兩個目標基本都實現了。

最後

存一下本身寫的東西

<template>
  <el-menu
    :default-active="activeIndex"
    class="el-menu-demo"
    mode="horizontal"
    background-color="#6e2142"
    text-color="#ffd692"
    active-text-color="#ffd692"
    @select="handleSelect"
  >
    <el-menu-item index="1" v-show="!logined">淘寶網</el-menu-item>
    <el-menu-item :disabled="true" id="el-menu-item-placeholder1"></el-menu-item>
    <el-menu-item id="el-menu-item-searchinput-container" :disabled="true">
        <el-input v-model="input" placeholder="搜索欄"></el-input>
    </el-menu-item>

    <el-menu-item index="2">登陸</el-menu-item>
    <el-menu-item index="3">註冊</el-menu-item>


  </el-menu>
</template>

<script>
export default {
  data() {
    return {
      activeIndex: "1",
      logined: false,
      input: null,
    };
  },
  methods: {
    handleSelect(key, keyPath) {
      console.log(key, keyPath);
    }
  }
};
</script>

<style scoped>
    .el-menu {
        min-width: 800px;
        padding-left: 20px;
    }
    #el-menu-item-placeholder1 {
        width: 60%;
        max-width: 60%;
        cursor: default;
    }
    .el-menu > .el-menu-item {
        min-width: 5%;
        padding: 0 5px;
        box-sizing: content-box;
        text-align: center;
    }

    #el-menu-item-searchinput-container {
        cursor: default;
        opacity: 1;
        margin: 0 20px;
    }

</style>

通過此次經歷,我算是有點理解到是人在用組件,而不是組件在用人。組件雖說是一個個已經封裝好的成熟的,但絕大部分樣式最終實現仍是依靠CSS。所以若是能抓住其最終實現的CSS樣式進行解析,就能本身進一步自定義化組件了。

分析組件時要注意樣式變化時對應元素的先後變化,好比被 disabled 的 el-menu-item 使得白白淨淨很好看的內部的 el-input 蒙上了一層背景色,這個時候首先看 el-menu-item 是否多出和 disabled 這件事有關的樣式,而後去看 el-input 繼承的樣式而沒必要關心本來的樣式,由於本來的表現是正常的。

是人用組件,而不是組件用人。

相關文章
相關標籤/搜索