一、實踐
1.分析
一個抽屜組件的z-index必定是在當前頁面之上的,在抽屜主體之外的區域還會有一層半透明的遮罩層,知道這些就很容易了
//drawer.vue<template><pclass="mask"></p><pclass="drawer"><pclass="drawer_body"></p></p></template><stylescoped>.drawer{position:absolute;height:100vh;top:0;bottom:0;right:0;left:0;z-index:1000000!important;}.drawer.drawer_body{height:100%;position:absolute;z-index:1000001;background-color:#fff;}.mask{height:100vh;width:100vw;position:absolute;z-index:1000000;top:0;left:0;background-color:#000;opacity:0.5;}</style>
現在已經是我們想要的樣子了,接下來是給drawer_body添加樣式
作為一個靈活的組件庫,我們希望樣式是可以隨時定制的,所以,接下要添加的樣式都 使用props
動態綁定的
參考iview的樣式,除了抽屜的寬度,還需要設置抽屜的方向,當我們需要抽屜時讓它顯示出來,不需要時隱藏它,或者為了更加顯眼,甚至給抽屜更換背景色......,這些都是可以實現的,看下面的代碼
<script>exportdefault{props:{//是否顯示drawerdrawerVisible:Boolean,//drawer方向direction:{type:String,validator(val){return["right","left"].indexOf(val)!==-1;}},//drawer寬度width:{type:Number,default:400},//drawer背景色background:{type:String,default:"#ffffff"},//是否顯示遮罩層mask:{type:Boolean,default:true}}};</script>
對于寬度和背景色,你還需要額外的處理下
<pclass="drawer_body":style="{'right':direction=='right'?'0':'auto','left':direction=='left'?'0':'auto','width':width+'px','background':background}">drawer</p>
你只需在使用的地方引入組件,然后提供你想修改的props值
//index.vue<template><p>...<el-buttonsize="mini"@click="visible">顯示抽屜</el-button><Drawer:drawerVisible="drawerVisible"direction="right":mask="true"background="aquamarine"></Drawer></p></template><script>exportdefault{data(){return{drawerVisible:false};},methods:{//打開抽屜visible(){this.drawerVisible=true;}}}</script>
2.關閉抽屜
在點擊遮罩層的時候,我們希望可以關閉已經打開的抽屜組件,這里如果你直接修改父組件傳過來的drawerVisible值,會報錯如下
vue.esm.js:629 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders. Instead, use a data or computed property based on the
prop's value. Prop being mutated: "drawerVisible"
這是因為vue是單向數據流的,如果想改變父元素的值,必須使用監聽事件的方式,但是2.3.0之后添加了.sync修飾符,所以,正確的做法是使用.sync修飾符
...<pv-if="drawerVisible"class="mask"></p><transition:name="this.direction=='left'?'slide-right':'slide-left'"><pv-if="drawerVisible"@click.stop="closeBtn?'':close"class="drawer"><pclass="drawer_body":style="{'right':direction=='right'?'0':'auto','left':direction=='left'?'0':'auto','width':width+'px','background':background}"></p></p></transition>...methods:{close(){this.$emit("update:drawerVisible",false);}}
另外,我們還希望在關閉抽屜組件時,我們可以監聽到這個事件然后做出反應
methods:{close(){this.$emit("update:drawerVisible",false);this.$emit("close");}}
此時需要在抽屜組件上添加
<Drawer:drawerVisible.sync="drawerVisible"@close="close"></Drawer>methods:{close(){//關閉抽屜組件時你要做的事}}
2.動畫
動畫是UI的靈魂,所以接下來給抽屜組件的顯示和隱藏添加動畫,我們使用transition的css動畫做動畫過度效果
//drawer.vue<pclass="drawer"><pclass="mask"></p><!--不同方向使用不用的動畫名稱,如果抽屜在左邊,則進入方向是朝→--><transition:name="this.direction=='left'?'slide-right':'slide-left'"><pclass="drawer_body"v-if="drawerVisible":style="{'right':direction=='right'?'0':'auto','left':direction=='left'?'0':'auto','width':width+'px','background':background}">drawer</p></transition></p></template><stylescoped>/**...*這里省略了寫過的樣式*/.slide-right-enter-active,.slide-right-leave-active,.slide-left-enter-active,.slide-left-leave-active{will-change:transform;transition:transform300ms;position:absolute;width:100vw;height:100vh;overflow:hidden;}.slide-right-enter,.slide-right-leave-active{transform:translate(-100%,0);}.slide-left-leave-active,.slide-left-enter{transform:translate(100%,0);}</style>
雖然現在已經完全實現了抽屜的功能,但是本著更加精美的原則,我還打算使用slot給它添加辯題和頁腳
3.添加標題
標題solt的name值是header
添加標題的目的是為了讓抽屜組件看起來更加清楚,此外,除了添加標題,我還想添加個關閉按鈕
//需要添加幾個props屬性<script>exportdefault{props:{//drawer標題title:String,//是否顯示關閉按鈕closeBtn:{type:Boolean,default:false},}};</script>
你可以選擇是否添加標題,是否添加關閉按鈕,值的注意的是如果添加了關閉按鈕,點擊遮罩層就不會自動關閉抽屜組件了
<!--這里要啰嗦下布局,如果你只選擇開啟關閉按鈕,那justify-content布局是flex-end如果兩者都開啟,那justify-content布局是space-between--><slotname="header"><pv-if="title||closeBtn":class="title"><pv-if="title">{{title}}</p><el-buttonv-if="closeBtn"circlesize="mini"icon="el-icon-close"@click="close"></el-button></p></slot>
我是這么做到禁用遮罩層點擊事件的
<pv-if="drawerVisible"@click.stop="closeBtn?'':close"class="mask"></p>
當然這些你可以使用具名插槽自定義的
<Drawer:width="400"direction="right":mask="true"title="抽屜組件"><pv-slot:header>這里是自定義標題</p><p></p></Drawer>
4.添加頁腳
頁腳solt的name值是footer
為了使得頁腳和標題有一定的距離,我給主體內容添加了最小高度
<p><slot></slot></p>
方法是很類似的,只是我多添加了兩個監聽事件,確定和取消
//drawer.vue<slotname="footer"><pclass="footer"><el-buttonsize="mini"type="primary"@click="footerOk">確認</el-button><el-buttonsize="mini"@click="footerCal">取消</el-button></p></slot>
//引入的頁面<Drawer:width="400"direction="right":mask="true"title="抽屜組件":footer-ok="footerOk":footer-cal="footerCal"></Drawer>
還需要在props中添加對應的值
props:{footerOk:Function,footerCal:Function},
關于頁腳的布局是這樣的
.footer{border-top:0.1pxsolid#ddd;display:flex;justify-content:flex-end;padding-top:10px;}
當然這些你也是可以使用具名插槽自定義的
<Drawer:width="400"direction="right":mask="true"title="抽屜組件"><pv-slot:header>這里是自定義標題</p><p></p><pv-slot:footer>這里是自定義頁腳</p></Drawer>
5.主體是否可以滾動
前面說過給主體添加了最小高度,但是超過最小高度,可能會被撐開布局,所以我給它添加了滾動功能
//props添加//是否開啟滾動scroll:{type:Boolean,default:false}
在drawer_body的樣式末尾追加overflow-y樣式
<pclass="drawer_body":style="{'right':direction=='right'?'0':'auto','left':direction=='left'?'0':'auto','width':width+'px','background':background,'overflow-y':scroll?'scroll':'hidden'}"></p>
scroll默認是不開啟的,如果你的抽屜要放的內容少,就不用理這個屬性,但是當內容撐開抽屜時記得手動開啟這個功能復制代碼
6.細節的優化
這里說下自己的不足之處,并且如何改進它
a.滾動條bug
當選擇抽屜在右邊時,動畫過程中會出現滾動條,看起來讓我的UI組件大打折扣,針對這個問題我打算在組件中監聽drawerVisible,當它需要被展示時禁用body的滾動效果,當它不需要被展示時,還原body的展示效果
watch:{drawerVisible(n,o){if(n==true){document.documentElement.style.overflowY="hidden";document.documentElement.style.overflowX="hidden";}}},
b.向下冒泡bug
在點擊抽屜以外的區域可以正常關閉抽屜,但是我發現當我點擊抽屜非按鈕區域時,也會關閉抽屜,這是向下冒泡的bug,這個bug我的解決方案是在drawer_body上添加個無意義的事件,并阻止向上冒泡
<p@click.stop="clickBg_"//注意這里class="drawer_body":style="{'right':direction=='right'?'0':'auto','left':direction=='left'?'0':'auto','width':width+'px','background':background,'overflow-y':scroll?'scroll':'hidden'}"></p>
二、API文檔
1.屬性
屬性 | 描述 | 類型 | 默認 |
---|---|---|---|
drawerVisible | 是否顯示drawer | Boolean | false |
direction | drawer方向 | String | left |
width | drawer寬度 | Number | 400 |
background | drawer背景色 | String | #ffffff |
mask | 是否顯示遮罩層 | Boolean | true |
title | drawer標題 | Boolean | true |
closeBtn | 是否顯示關閉按鈕 | String | --- |
scroll | 是否開啟滾動 | Boolean | false |
2.事件
事件 | 描述 | 返回值 |
---|---|---|
close | 監聽關閉事件 | 無 |
footerOk | 頁腳確認綁定事件,使用默認頁腳時有效 | 無 |
footerCal | 頁腳取消綁定事件,使用默認頁腳時有效 | 無 |
3.slot
name | 描述 |
---|---|
header | 頁頭插槽名稱 |
default | 抽屜主體部分,可省略 |
footer | 頁腳插槽名稱 |
注意:插槽里的按鈕都是使用element內置的組件,如果你的項目里沒有引入element庫
那最好請使用具名插槽重寫頁頭和頁腳部分
感謝各位的閱讀!關于“怎樣給element添加一個抽屜組件”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
uv是訪客數還是瀏覽量?uv是訪客數。一定時間內,一臺設備可以在一個網站上制造多次PV,但一般只能制造一次UV,淘寶瀏覽量統計的是一天之內,客戶訪問的網店頁面的數量,瀏覽量越高。說明客戶對我們店鋪產品越喜歡。而淘寶pv就是淘寶瀏覽量,它和淘寶uv是不同的概念,大家千萬不要搞混了,這兩個可是評定店鋪好壞最基礎的數據。淘寶店鋪訪客和瀏覽量是什么比例?因為每個商家選擇的類目和商品不同,因此訪客和瀏覽量的...
黃金24k和999純金的區別在哪里?24K就是純金,通常將含金量達到99.96%以上的黃金稱之為24K金或者是純金, 24K金和999 黃金的區別是:1、含金量不同: 24K金為純金,含金量在99.96%以上,而999黃金是含金量達到99.9%的黃金;2、價格不同: 999黃金的價格要比24K金高;3、999黃金柔韌性和延展性比24K金更差,因為24K金在制造中加了其它金屬。周大生的黃金純不純?周...
全國統一大市場是什么意思?國內統一大市場指的是在全國范圍內,在充分競爭以及由此形成的社會分工基礎上,各地區市場間、各專業市場間形成了相互依存、相互補充、相互開放、相互協調的有機的市場體系。在這種市場體系下,商品和要素,在各行業、各地區間自由地、無障礙地流通或流動,市場封鎖、地方保護等現象基本消除,從而實現資源在全國范圍內順暢流動和優化配置。就目前來看,引起市場分割的因素有很多,主要包括自然和人為兩...