vue頭標籤的再認識,涵蓋樣式模塊化

好好學習

rem以及自定義vue頭標籤

原來我覺得的頭標籤就只是原裝的<head></head>,而後在裏面balabala寫,結果今天才知道,它也是能夠「我想怎麼樣就怎麼樣」的~
來左邊跟我一塊兒放個logo,來右邊放一個編輯~css

效果初覽

ps:沒錯,這個草率的ele.me就是說傳說中的logo,對了,單擊<箭頭會回退喲!

先來認識rem

爲了適應不一樣的顯示器,咱們用px單位可想而知是不夠的。因此咱們用rem作到全部設備自適應。rem是css的相對單位。
html

在vue單頁項目中,如何作到設備自適應?

確定是不能寫死的,用動態,如:16rem=100%,這個就是動態寬度的100%。
16其實就是引入了柵格系統,將一行分爲16列,好比設爲8:8,它其實就是兩列左右對等佈局,4:4:4其實就是三列式佈局。那麼要怎麼作呢?要對html的fontSize進行一個計算。vue

建立一個vue項目ele

新建的項目只須要勾選babel和router便可。
html5

先從rem開始

在main.js中,先導入咱們要的rem。
import './config/rem'
大型項目中組件如何兼容? rem是第一項要考慮的。
git

項目配置目錄cofig

src/config/rem.js,在這裏手動計算rem。github

(function(doc, win){
    var docEl = doc.documentElement, //獲取html
    // docEl.style.fontSize = '23.5px'; //先寫死一個值測試一下
})(document, window) // 建一個閉包, 當即執行函數,傳兩個實參
複製代碼
  1. 閉包區域,把document和window傳進去。閉包裏面定義的變量,不會污染外界。咱們在閉包裏面動態計算咱們html的fondSize。
  2. 利用width/16,使用柵格能力(css中的等比例計算)。
  3. 寫一個專門計算rem的函數recalc:
(function(doc, win){
    var docEl = doc.documentElement, //獲取html
    
    recalc = function() {
        // 設備無差別計算出  16rem = 100% width
        var clientWidth = docEl.clientWidth; //html的整個窗口的寬度
         // console.log(clientWidth);

        if (!clientWidth) return;
        docEl.style.fontSize = 20 * clientWidth/320 + 'px';
        // console.log(clientWidth);
      };
      doc.addEventListener('DOMContentLoaded', recalc, false);
      
    // docEl.style.fontSize = '23.5px'; //先寫死一個值測試一下
})(document, window) // 建一個閉包, 當即執行函數,傳兩個實參
複製代碼
  1. 來解釋一下doc.addEventListener('DOMContentLoaded', recalc, false); 監聽DOMContentLoaded事件。在vue裏面也有生命週期,DOMContentLoaded事件比loaded事件先發生,由於loaded要等到全部圖片都加載完,整個頁面都加載完了才觸發,而DOMContentLoaded事件只要DOM結構加載完了(html結構)加載完成了,就會觸發。此時咱們就去計算fontSize的大小。,當它觸發DOMContentLoaded事件的時候,咱們去調用recalc函數,第三個參數爲false。
    關於第三個參數false:
    false是事件監聽中,究竟是從外到內(捕獲),仍是從內到外(冒泡)的選擇。爲false是內層向外層執行(冒泡),爲true是由外向內執行(捕獲)。
  2. 爲何是20 * clientWidth/320呢?
    首先,經過clientWidth計算,整個寬度分紅320份,再乘以20,恰好是16,也就是將clientWidth分紅十六份。而對於320,是有可能在最初的設計稿中,是320的設計稿,(如今通常都是750的,它的1/2是375),以前的是640的,就是兩倍於寬度,因此就是320,咱們這裏用老的設計稿的(640)。而後再湊出16。因此這裏是20。 用一個盒子來檢驗一下效果:
<div style="width:16rem;height:2rem;background-color:red;"></div>
複製代碼

當設備變化的時候,如何實現自適應呢?

好比設備可能由縱向,變成橫向,還有可能屏幕尺寸發生改變。那怎麼作呢?bash

(function(doc, win){
    var docEl = doc.documentElement, //獲取html
    // 是否換了方向,橫屏? 調整窗口寬度->resize事件
      resizeEvt = 'orientationchange' in win ? 'orientationchange': 'resize',
    
    recalc = function() {
        // 設備無差別計算出  16rem = 100% width
        var clientWidth = docEl.clientWidth; //html的整個窗口的寬度
         // console.log(clientWidth);

        if (!clientWidth) return;
        docEl.style.fontSize = 20 * clientWidth/320 + 'px';
        // console.log(clientWidth);
        // ?設備可能由縱向變模着拿 尺寸發生變化
        win.addEventListener(resizeEvt, recalc, false);
      };
      doc.addEventListener('DOMContentLoaded', recalc, false);
      
    // docEl.style.fontSize = '23.5px'; //先寫死一個值測試一下
})(document, window) // 建一個閉包, 當即執行函數,傳兩個實參
複製代碼
  1. window對象中若是發生orientationchange窗口改變事件(橫屏或豎屏),就返回orientationchange,不然返回resize事件(調整窗口寬度時)。

接下來看header組件

來到App.vue,先定義一個組件:babel

export default {
  components: { //組件聲明
    // 不能與標籤名字header重合,怎麼解決?
    // head-top是在頁面上的標籤名  Header是類名
    "head-top": Header
  }  
}
複製代碼

將咱們自定義的header封裝:
import Header from './components/header/header'; //封裝這個組件閉包

構建components/header/header組件

在components下建一個header/header.vue 下面先展現一個錯誤的:less

<template>
    <header id="head_top">
        header
    </header>
</template>
複製代碼
  1. 咱們的標籤名字,不能跟html5的標籤名字同樣,由於會先解析html的標籤。當名字不同時,解析時它就不會去找html標籤,而是去組件聲明裏面找組件,因此寫成"head-top": Header,其中"head-top"就是咱們在頁面上寫的佔位符(標籤名)。而Header實際上是類名。
  2. 因此修改一下:
<template>
    <head-top id="編輯地址">
        header
    </head-top>
</template>
複製代碼

給組件傳遞一個標題和logo

<head-top headTitle="編輯地址">
      <span class="head_logo" >ele.me</span>
</head-top>
複製代碼

進行header的封裝

來到header.vue

  1. 先打理標題參數。
<script>
export default {
  props: ['headTitle']
}
</script>
複製代碼
  1. 將logo放置在左邊。使用span和slot,在組件之間插槽插入。 App.vue中先放好了span,如今直接在header.vue中:
<header id="head_top">
    <!-- slot在{{headTitle}}前面,因此就插好了 用一個name -->
    <slot name="logo"></slot>
    <!-- section是一個區塊 這裏寫了兩個類名 -->
    <!--用戶傳了headTitle咱們才輸出,不然不輸出-->
    <section class="title_head ellipsis" v-if="headTitle">
      <span class="title_text">
        {{headTitle}}
      </span>
    </section>
</header>
複製代碼
  1. 寫點樣式。 header.vue中:
<style lang="styl" scoped>
@import "../../style/mixin.styl";
/* $blue是定義的stylus變量 
position fixed固定定位*/
#head_top
  background-color $blue
  position fixed
  z-index 100
  left 0
  top 0
  wh(100%, 1.95rem)
  .title_head
    center()
    width 50%
    color #fff
    text-align center
    .title_text
      sc(0.8rem, #fff)
      text-align center
      font-weight bold
  .head_goback
    left 0.4rem
    wh(0.6rem, 1rem)
    line-height 2.2rem
    margin-left 0.4rem 

</style>
複製代碼

咱們用的是stylus,因此記得先install一下,在終端中yarn add stylus stylus-loader
import導入樣式文件時必定必定記得加分號!
4. 在這裏面咱們複用了樣式,寫在了mixin.styl文件中,注意看哦!

<!--定義了一個超級變量blue-->
$blue = #3190e8;

wh($width, $height)
  width $width
  height $height

center()
  top 50%
  left 50%
  position absolute
  transform translate(-50%, -50%)

sc($size, $color)
  font-size $size
  color $color

ct()
  top 50%
  position absolute
  transform translateY(-50%)
複製代碼

再加上右邊的編輯

一樣用slot方式插在標題右邊:

<section class="title_head ellipsis" v-if="headTitle">
      <span class="title_text">
        {{headTitle}}
      </span>
</section>
<slot name="edit"></slot>
複製代碼

  1. 解釋一下slot,由於咱們插入的slot比較多,放左邊仍是右邊就容易被夾在一塊兒。那麼如何區分呢?給slot加上name就好啦~(具名插槽) 而後<span>中就寫成這樣: App.vue
<head-top head-title="編輯地址" go-back="true">
      <span class="head_logo" slot="logo">ele.me</span>
      <!-- slot的name來區分編輯和logo的不一樣位置 -->
      <span class="edit" slot="edit">編輯</span>
</head-top>
複製代碼

最後加上一個返回上一步

header.vue中

<!-- section是一個區塊 -->
    <section class="head_goback" v-if="goBack" @click="$router.go(-1)">
      <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
        <polyline points="12,18 4,9 12,0" style="fill:none;stroke:rgb(255,255,255);stroke-width:2"/>
      </svg>
 </section>
複製代碼

就是這個小箭頭。
其中 @click="$router.go(-1)"能夠實現單擊後返回上一層。

這裏是結尾

簡單的一個關於rem,和header,以及css模塊化的小例子就分享到這了,喜歡的點個start~
github戳這裏

相關文章
相關標籤/搜索