1. 程式人生 > 程式設計 >Vue元件化開發之通用型彈出框的實現

Vue元件化開發之通用型彈出框的實現

本文主要分享關於元件化開發的理解,讓剛入門的小夥伴少走一些彎路,提高開發效率,作者本人也是新手,如有不當之處,請大佬指出,感謝。

相信很多剛入門的小夥伴,經常會寫很多重複的程式碼,而這些程式碼一般情況下也都是大同小異,在這種情況下,如何讓開發和學習變得更加高效,元件化的思想就顯得尤為重要。這裡通過設計一個簡單的彈出框,給小夥伴們分享元件化的應用。

元件&元件化

元件化是對某些可以進行復用的功能進行封裝的標準化工作。元件一般會內含自身的內部UI元素、樣式和JS邏輯程式碼,它可以很方便的在應用的任何地方進行快速的嵌入。元件內部可以使用其他元件來構成更復雜的元件。

在實際的開發中,我們應該避免去編寫重複的程式碼,將精力放在更加核心的部分,因此就需要將這些重複的程式碼抽取出來,封裝成公共的元件,提高開發效率,但同時也要注意元件的健壯性和可複用性,讓它能夠儘可能適應更多的場景。

基本結構

首先是彈出框的基本結構

<div class="modal">
   <div class="mask"></div>
   <div class="modal-dialog">
    <div class="modal-header">
     <span>標題</span>
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="icon-close"></a>
    </div>
    <div class="modal-body">
     <slot name="body"></slot>
    </div>
    <div class="modal-footer">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn">確定</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-default">取消</a>
     </div>
    </div>
   </div>
  </div>

​基本結構很簡單,稍微注意一點的就是slot 插槽,如果沒有提供name屬性,它將有一個隱含的名字default,並且在父元件如果沒有指定slot 的v-slot 屬性的話,內容會傳給default插槽。

在這裡定義了slot 的name屬性body ,這種的叫做具名插槽,會匹配v-slot:body 的內容。

注意,在父元件中呼叫需要用<template> 包裹,並且<template> 元素中的所有內容都將被傳入相應的插槽。

給彈出框加點樣式

.modal {
 position: fixed;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 .mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #000000;
  opacity: 0.5;
 }
 .modal-dialog {
  position: absolute;
  top: 40%;
  left: 50%;
  width: 560px;
  height: auto;
  background-color: #ffffff;
  transform: translate(-50%,-50%);
  .modal-header {
   height: 60px;
   background-color: #F5F5F5;
   padding: 0 25px;
   line-height: 60px;
   font-size: 16px;
   .icon-close {
    position: absolute;
    top: 23px;
    right: 25px;
    width: 14px;
    height: 14px;
    background: url("/static/img/icon-close.png") no-repeat center;
    background-size: contain;
   }
  }
  .modal-body {
   padding: 42px 40px 54px;
   font-size: 14px;
  }
  .modal-footer {
   height: 82px;
   line-height: 82px;
   text-align: center;
   background-color: #F5F5F5;
  }
 }
}

我這裡使用的是scss ,使用的時候別忘了安裝node-sass 和sass-loader ,現在我們的頁面是這個樣子了

Vue元件化開發之通用型彈出框的實現

雖然還是不太美觀,但是已經基本上是一個彈出框的雛形了,並且我沒有給a 標記樣式,原因在後面。

SCSS函式

回過頭再看看上面的css 程式碼,這裡重複寫了4次固定定位的程式碼,而且隨著專案的推進,肯定還有更多類似的程式碼,何不將這些部分抽取出來,進行封裝呢?scss 提供了這個功能,將css 封裝成函式,這裡的函式直接會返回函式體。我們在遇到類似的情況時,就能夠直接複用。

在assets 目錄下新建scss 資料夾並在裡面新建mixin.scss ,在裡面新建position 函式,程式碼如下:

@mixin position($pos: absolute,$top: 0,$left: 0,$w: 100%,$h: 100%) {
 position: $pos;
 top: $top;
 left: $left;
 width: $w;
 height: $h;
}

接著我們引入mixin.scss ,用position 函式替換我們原先的程式碼

通過@include方式使用scss 函式:@include position(fixed); 括號裡面的是引數。

關於按鈕

每一個網站都有很多按鈕,不過,同一個網站的按鈕風格大多都是一樣,無非是大小不一。因此可以單獨在scss 檔案下新建button.scss 然後在App.vue 裡面引入這個檔案,在後面除了一些特別的樣式,其它就不需要給按鈕定義樣式了,這樣也便於維護。這裡給出我的button 檔案,可以參考一下。

.btn {
 display: inline-block;
 width: 110px;
 line-height: 30px;
 text-align: center;
 background-color: #FF6600;
 color: #ffffff;
 border: none;
 cursor: pointer;
}
.btn-default {
 background-color: #b0b0b0;
 color: #d7d7d7;
}
.btn-large {
 width: 202px;
 height: 50px;
 line-height: 50px;
 font-size: 18px;
}
.btn-huge {
 width: 300px;
 height: 54px;
 line-height: 54px;
 font-size: 16px;
}
.btn-group {
 .btn {
  margin-right: 20px;
  &:last-child {
   margin-right: 0;
  }
 }
}

為了複用

當前這個彈出框還只是一個固定的結構,它並不能在其他地方複用,需要進行一些處理,將所有可變部分抽取出來,例如標題,按鈕,內容。因為有插槽,所以內容就不用考慮,需要關注的是標題和按鈕,因為標題有可能是提示,警告等等,按鈕也有可能是確定、取消的一個或兩個都有。而這些資訊都是從父元件傳遞過來,需要用props 接收。

在props 裡面新增如下程式碼,並給某些屬性指定預設值:

props: {
  // 彈框標題
  title: String,// 按鈕型別: 1:確定按鈕 2:取消按鈕 3:確定取消
  btnType: String,// 按鈕文字
  sureText: {
   type: String,default: "確定"
  },cancleText: {
   type: String,default: "取消"
  },showModal: Boolean
 }

新增完之後,還需重新改寫程式碼

<div class="modal" v-show="showModal">
   <div class="mask"></div>
   <div class="modal-dialog">
    <div class="modal-header">
     <span>{{title}}</span>
     <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="icon-close" @click="$emit('cancle')"></a>
    </div>
    <div class="modal-body">
     <slot name="body"></slot>
    </div>
    <div class="modal-footer">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" v-if="btnType==1"@click="$emit('submit')"{{sureText}}</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" v-if="btnType==2"@click="$emit('cancle')">{{cancleText}}</a>
     <div class="btn-group" v-if="btnType==3">
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn" @click="$emit('submit')">{{sureText}}</a>
      <a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" class="btn btn-default" @click="$emit('submit')">{{cancleText}}</a>
     </div>
    </div>
   </div>
  </div>

通過父元件傳遞的引數,來實現程式碼的重用,並且使用$emit 來向外丟擲自定義事件,然後在父元件實現自己的業務邏輯。

在Home.vue 裡面引入這個元件並呼叫

<modal
  title="小星星"
  sureText="確定"
  btnType="1"
  :showModal="showModal"
  @submit="go"
  @cancle="showModal=false"
 >
  <template v-slot:body>
   <p>給個小星星吧</p>
  </template>
 </modal>

這裡的@submit 和@cancle 就是我們在元件裡面自定義的事件

最終效果如下

Vue元件化開發之通用型彈出框的實現

實現完之後,感覺有點彈出時生硬,沒關係,我們給它加點動畫,在css3中有transform 和transition 可以實現動畫效果,但是我們這裡使用vue 內建元件<transition> ,讓彈出框有一個從上面彈出的效果。

transition元件

transition 元件可以為元素或元件新增過渡效果,只會把過渡效果應用到其包裹的內容上,而不會額外渲染 DOM 元素,也不會出現在可被檢查的元件層級中。它可以通過多種方式進行過渡,在這裡應用 class的方式過渡。

Vue元件化開發之通用型彈出框的實現

這幅圖是Vue 官方給出的圖,簡單來說,v-enter是動畫開始的狀態,v-enter-active進入過渡生效時的狀態,v-enter-to是過渡的結束狀態,leave同理,具體細節大家可以去https://cn.vuejs.org/v2/guide/transitions.html檢視。

當沒有指定的name屬性時,過渡的類名會預設以v作為字首,這裡給transition指定name為

slide並用它包裹modal元件

<transition name="slide">
  <div class="modal" v-show="showModal">
   ...
   ...
  </div>
 </transition>

在style程式碼裡面modal後面加上

&.slide-enter-active {
  top: 0;
 }
 &.slide-leave-active {
  top: -100%;
 }
 &.slide-enter {
  top: -100%;
 }

並且給modal指定需要過渡的屬性

transition: top 0.5s;

加完這個之後,彈出框就會有一個滑上滑下的動畫啦。

到此,我們的彈出框就完成啦。

你也可以根據自己的需求去做適當的調整,開發出適合自己專案的彈出框。

最後

在實際開發中,元件化是尤為重要的,它能夠幫助我們寫出更高質量的程式碼,也能夠讓我們的程式碼更易於維護,儘早的樹立元件化的思想,對寫程式碼也是非常有幫助的。

附上https://github.com/anpeier/shop-online

到此這篇關於Vue元件化開發之通用型彈出框的實現的文章就介紹到這了,更多相關Vue 彈出框內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!