最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue下拉列表的兩種實現(xiàn)方式比較

 更新時間:2021年06月07日 17:10:22   作者:張超帥  
這篇文章主要介紹了vue下拉列表的兩種實現(xiàn)方式比較,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

vue下拉列表的兩種實現(xiàn)

第一種采用v-for的方式

  <el-select v-model="form.columeType" placeholder="字段類型">
           <el-option v-for="(item,index) in columeTypeArr" :key="index" :label="item.label" :value="item.value">
           </el-option>
  </el-select>

這種方式需要在data中定義columeTypeArr,如下

data(){
    return {
       columeTypeArr:[{
            value:'String',
            label:'字符串'
        },{
            value:'Int',
            label:'整數(shù)',
        },{
            value:'Decimal',
            label:'數(shù)值型'
        }],
    }
}

第二種采用寫死的方式

直接在select下寫死

  <el-select v-model="form.fileOrgType" placeholder="請選擇">
        <el-option label="是" value="Y"> </el-option>
        <el-option label="否" value="N"></el-option>
  </el-select>

兩種方式的比較:

兩種方式都差不多,只是第一種方式需要在data中進行配置,對于需要數(shù)據(jù)從后臺回顯的情況,明顯是第一種方法好。

對于簡單的下拉列表參數(shù)很少的情況,第二種明顯更占優(yōu)。

vue下拉菜單組件的實現(xiàn)

我們一起來實現(xiàn)一個vue的下拉菜單組件。

像這種基本UI組件,網(wǎng)上已經(jīng)有很多了,為什么要自己實現(xiàn)呢?其實并不是有意重復(fù)造輪子,而是想通過這個過程回顧一下vue組件開發(fā)的一些細節(jié)和注意事項。

為什么選擇下拉菜單組件?

因為:麻雀雖小五臟俱全,這個小小的組件涉及到了不少vue組件開發(fā)的知識點。

好了,那就開始吧!

首先創(chuàng)建一個vue-cli的項目,筆者用的是vue-cli3,創(chuàng)建過程略,然后創(chuàng)建一個vue組件:DropDownList.vue

在編寫模板之前,我們來分析一下這個組件的視圖結(jié)構(gòu)和功能。

下拉菜單組件應(yīng)該由兩部分組成:

選中項的文本

待選菜單(默認隱藏)

它的主要功能包括:

鼠標經(jīng)過下拉菜單組件,顯示待選菜單

鼠標滑出下拉菜單組件,隱藏待選菜單

鼠標點擊待選菜單中的條目,選中項文本更新,組件派發(fā)change事件

我們編寫如下這樣的模板:

<template>
  <div class="zq-drop-list" @mouseover="onDplOver($event)" @mouseout="onDplOut($event)">
        <span>選中項的文本<i></i></span>
        <ul>
            <li>北京</li>
            <li>上海</li>
            <li>廣州</li>
        </ul>
    </div>
</template>

選中項文本右側(cè)的i標簽,用來實現(xiàn)下拉菜單的三角形圖標,在下文的css中我們用背景圖來實現(xiàn)。

我們給根元素div已經(jīng)添加了鼠標經(jīng)過和滑出的回調(diào)函數(shù),具體實現(xiàn)見下文。

接下來我們?yōu)檫@個下拉菜單編寫樣式,在模板下方添加style標簽,為了防止和其他組件的樣式發(fā)生沖突,筆者建議大家在開發(fā)組件時,都給style加上scoped屬性。另外,筆者在這里用到了scss,具體代碼如下:

<style scoped lang="scss">
    .zq-drop-list{
        display: inline-block;
        min-width: 100px;
        position: relative;
        span{
            display: block;
            height: 30px;
            line-height: 30px;
            background: #f1f1f1;
            font-size: 14px;
            text-align: center;
            color: #333333;
            border-radius: 4px;
            i{
                background: url(https://www.easyicon.net/api/resizeApi.php?id=1189852&size=16) no-repeat center center;
                margin-left: 6px;
                display: inline-block;
            }
        }
        ul{
            position: absolute;
            top: 30px;
            left: 0;
            width: 100%;
            margin: 0;
            padding: 0;
            border: solid 1px #f1f1f1;
            border-radius: 4px;
            overflow: hidden;
            li{
                list-style: none;
                height: 30px;
                line-height: 30px;
                font-size: 14px;
                border-bottom: solid 1px #f1f1f1;
                background: #ffffff;
            }
            li:last-child{
                border-bottom: none;
            }
            li:hover{
                background: #f6f6f6;
            }
        }
    }
</style>

關(guān)于樣式,這里就不詳細展開了,只說其中幾個需要注意的點:

那個i元素的樣式,我用到了一個網(wǎng)絡(luò)圖片,大家可以自行更換

待選菜單ul在css里并沒有讓它隱藏,因為我們要通過js來控制,具體原因見下文

待選菜單ul使用了絕對定位,因為當它展開的時候,不應(yīng)該影響頁面上其他元素的布局

現(xiàn)在這個組件大概長這個樣子:

我們繼續(xù)為這個組件定義屬性,很顯然,待選菜單應(yīng)該作為屬性傳進來,一定不能是內(nèi)部寫死的,屬性定義如下:

<script>
export default {
    name: "DropDownList",
    props:{
        dataList:{
            type:Array,
            default(){
                return [
                    {name: "選項一"},
                    {name: "選項二"}
                ]
            }
        },
        labelProperty:{
            type:String,
            default(){ return "name" }
        }
    },
    data(){
        return {
            activeIndex:0
        }
    },
}

其中dataList就是待選菜單的數(shù)據(jù)源屬性,這里我們給這個屬性定義了默認值,這也是筆者建議大家養(yǎng)成的一個習(xí)慣,作為一個組件,最好有默認值,因為當別人使用你的組件時,可以先不設(shè)置相關(guān)屬性,就能看到一個成品的效果,也能快速查看你這個組件所需屬性的數(shù)據(jù)細節(jié)。

另外一個屬性是labelProperty,這個屬性的作用是什么?我們實際項目中的數(shù)據(jù)源,并不一定都含有name這個字段,因此就可能導(dǎo)致下拉菜單無法渲染數(shù)據(jù)的文本,于是我們定義了這個屬性用來指定實際數(shù)據(jù)源渲染文本的字段,這個字段必須是字符串。這個屬性的默認值是name,因為它需要和默認數(shù)據(jù)源保持一致。相信你還看到了一個組件內(nèi)部數(shù)據(jù),activeIndex,這個是用來表示當前選中項的索引的,我們后面會用到。

現(xiàn)在我們就可以在其他地方引入并使用這個組件了,雖然它還沒有完成,但我們不妨先讓它顯示在界面上吧:

<template>
  <div class="home">
    <DropList :dataList="dplist" labelProperty="city" @change="onDpChange($event)"></DropList>
    <p>其他文本內(nèi)容</p>
  </div>
</template>
<script>
  import DropList from '@/components/DropDownList.vue'
  //其他代碼略
</script>

這個頁面引入并使用了我們的DropDownList組件,:dataList="dplist" 綁定了當前頁面的dplist數(shù)組到組件的dataList屬性上,這個數(shù)組中的對象有一個city字段,我們希望此字段顯示在下拉菜單上,因此我們設(shè)置組件的labelProperty為city,我們還給這個組件注冊了change事件,這個組件內(nèi)部需要派發(fā)這個事件,見下文。

現(xiàn)在我們回到組件的模板部分,發(fā)現(xiàn)它都還是靜態(tài)內(nèi)容,我們把這些靜態(tài)內(nèi)容修改為通過屬性渲染。

<template>
    <div class="zq-drop-list" @mouseover="onDplOver($event)" @mouseout="onDplOut($event)">
        <span>{{dplLable}}<i></i></span>
        <ul>
            <li v-for="(item, index) in dataList" :key="index" @click="onLiClick(index, $event)">{{item[labelProperty]}}</li>
        </ul>
    </div>
</template>

其中待選菜單li的文本是 item[labelProperty] 這樣就能正確的顯示開發(fā)者指定的字段了。

我們看看選中項的文本表達式:dplLabel,我們并沒有定義這個屬性,也沒有定義這個內(nèi)部數(shù)據(jù),它是哪兒來的?選中項的文本應(yīng)該是 dataList[activeIndex][labelProperty] (這個很好理解吧,有問題請留言),但這個表達式太長了,寫在模板里不利于維護,我們就把它寫到計算屬性里吧。

computed:{
        dplLable(){
            return this.dataList[this.activeIndex][this.labelProperty]
        }
    }

于是才有了上面的dplLabel,計算屬性真的很好用呢。

現(xiàn)在下拉菜單的視圖和數(shù)據(jù)關(guān)聯(lián)部分我們已經(jīng)寫完了,接下來我們要實現(xiàn)它的功能。

第一步是先讓待選菜單默認隱藏起來,這里我們?yōu)槭裁床恢苯佑胏ss的display:none呢,然后鼠標經(jīng)過的時候display:block不就可以了嗎?因為這樣的話,我們無法實現(xiàn)點擊待選菜單條目的時候讓它隱藏,體驗不好。我們用js來控制,但vue對直接訪問dom元素支持的并不好,我們要想在組件初始化的時候訪問dom元素,有一個最方便的做法,那就是:自定義指令。

我們?yōu)橄吕藛谓M件添加局部自定義指令,代碼如下:

directives:{
        dpl:{
            bind(el){
                el.style.display = "none";
            }
        }
    },

這個dpl就是自定義指令啦,請忽略我笨拙的命名哈!然后我們在自定義指令的鉤子函數(shù)bind方法中,訪問el元素,控制它的style屬性display:none; 最后,把這個自定義指令加到模板里面的ul標簽上。別忘了要加v-,現(xiàn)在看看效果,待選菜單已經(jīng)隱藏了。

<ul v-dpl>

我們利用自定義指令鉤子函數(shù)訪問dom元素,實現(xiàn)了對dom的控制,這一點非常實用!

讓我們繼續(xù)實現(xiàn)最開始為下拉菜單定義的鼠標經(jīng)過和鼠標滑出的監(jiān)聽,實現(xiàn)待選菜單的顯示與隱藏。

onDplOver(event){
    let ul = event.currentTarget.childNodes[1];
    ul.style.display = "block";
},
onDplOut(event){
    let ul = event.currentTarget.childNodes[1];
    ul.style.display = "none";
},

我們在鼠標事件中,訪問event的currentTarget對象,為什么不是target?因為下拉菜單的子元素也會觸發(fā)這個事件,如果訪問target,可能不會是我們預(yù)期的頂層元素。

最后一步,我們實現(xiàn)待選菜單條目的點擊事件,點擊后,待選菜單隱藏,修改內(nèi)部狀態(tài),派發(fā)change事件。

onLiClick(index){
    let path = event.path || (event.composedPath && event.composedPath()) //兼容火狐和safari
    path[1].style.display = "none";
    this.activeIndex = index;
    this.$emit("change", {
        index:index,
        value:this.dataList[index]
    })
}

這里有一個細節(jié)需要注意,我們要通過li元素找到外層ul元素,但path不支持火狐和safari,好在這兩個瀏覽器支持composedPath,因此才有了第一行代碼的兼容寫法。然后通過修改內(nèi)部數(shù)據(jù)activeIndex實現(xiàn)選中項文本的更新,最后調(diào)用emit方法向父元素派發(fā)change事件,別忘了把事件對象封裝好傳出去。

完整的代碼如下:

<template>
    <div class="zq-drop-list" @mouseover="onDplOver($event)" @mouseout="onDplOut($event)">
        <span>{{dplLable}}<i></i></span>
        <ul v-dpl>
            <li v-for="(item, index) in dataList" :key="index" @click="onLiClick(index, $event)">{{item[labelProperty]}}</li>
        </ul>
    </div>
</template>
<script>
export default {
    name: "DropDownList",
    data(){
        return {
            activeIndex:0
        }
    },
    props:{
        dataList:{
            type:Array,
            default(){
                return [
                    {name: "選項一"},
                    {name: "選項二"}
                ]
            }
        },
        labelProperty:{
            type:String,
            default(){ return "name" }
        }
    },
    directives:{
        dpl:{
            bind(el){
                el.style.display = "none";
            }
        }
    },
    methods:{
        onDplOver(event){
            let ul = event.currentTarget.childNodes[1];
            ul.style.display = "block";
        },
        onDplOut(event){
            let ul = event.currentTarget.childNodes[1];
            ul.style.display = "none";
        },
        onLiClick(index){
            let path = event.path || (event.composedPath && event.composedPath()) //兼容火狐和safari
            path[1].style.display = "none";
            this.activeIndex = index;
            this.$emit("change", {
                index:index,
                value:this.dataList[index]
            })
        }
    },
    computed:{
        dplLable(){
            return this.dataList[this.activeIndex][this.labelProperty]
        }
    }
}
</script>
<style scoped lang="scss">
    .zq-drop-list{
        display: inline-block;
        min-width: 100px;
        position: relative;
        span{
            display: block;
            height: 30px;
            line-height: 30px;
            background: #f1f1f1;
            font-size: 14px;
            text-align: center;
            color: #333333;
            border-radius: 4px;
            i{
                background: url(https://www.easyicon.net/api/resizeApi.php?id=1189852&size=16) no-repeat center center;
                margin-left: 6px;
                display: inline-block;
            }
        }
        ul{
            position: absolute;
            top: 30px;
            left: 0;
            width: 100%;
            margin: 0;
            padding: 0;
            border: solid 1px #f1f1f1;
            border-radius: 4px;
            overflow: hidden;
            li{
                list-style: none;
                height: 30px;
                line-height: 30px;
                font-size: 14px;
                border-bottom: solid 1px #f1f1f1;
                background: #ffffff;
            }
            li:last-child{
                border-bottom: none;
            }
            li:hover{
                background: #f6f6f6;
            }
        }
    }
</style>

以上為大家展示了vue如何實現(xiàn)一個下拉菜單組件,雖然比較簡單,但也基本涉及到了組件開發(fā)常用的一些特性。希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決vue單頁面多個組件嵌套監(jiān)聽瀏覽器窗口變化問題

    解決vue單頁面多個組件嵌套監(jiān)聽瀏覽器窗口變化問題

    這篇文章主要介紹了解決vue單頁面多個組件嵌套監(jiān)聽瀏覽器窗口變化問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Vue動態(tài)改變css樣式的3種方法總結(jié)

    Vue動態(tài)改變css樣式的3種方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Vue動態(tài)改變css樣式的3種方法,在Vue.js中我們經(jīng)常需要根據(jù)特定的條件或事件來動態(tài)地修改CSS樣式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • Vue qiankun微前端實現(xiàn)詳解

    Vue qiankun微前端實現(xiàn)詳解

    這篇文章主要為大家介紹了Vue qiankun微前端實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Vue.js實現(xiàn)的購物車功能詳解

    Vue.js實現(xiàn)的購物車功能詳解

    這篇文章主要介紹了Vue.js實現(xiàn)的購物車功能,結(jié)合實例形式分析了vue.js購物車的原理、數(shù)值計算及頁面元素屬性動態(tài)操作相關(guān)實現(xiàn)技巧,需要的朋友可以參考下
    2019-01-01
  • 談?wù)剬ue?Router的理解

    談?wù)剬ue?Router的理解

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,適合用于構(gòu)建單頁面應(yīng)用,這篇文章主要介紹了對Vue?Router的理解,需要的朋友可以參考下
    2022-11-11
  • Vue的elementUI實現(xiàn)自定義主題方法

    Vue的elementUI實現(xiàn)自定義主題方法

    下面小編就為大家分享一篇Vue的elementUI實現(xiàn)自定義主題方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • Vue?項目性能優(yōu)化方案分享

    Vue?項目性能優(yōu)化方案分享

    本文是作者通過實際項目的優(yōu)化實踐進行總結(jié)而來,希望讀者讀完本文,有一定的啟發(fā)思考,從而對自己的項目進行優(yōu)化起到幫助
    2022-08-08
  • Vue3 全局使用按鈕截流指令示例代碼

    Vue3 全局使用按鈕截流指令示例代碼

    這篇文章主要介紹了Vue3 全局使用按鈕截流指令示例代碼,Vue2與Vue3中的自定義指令實現(xiàn)方式略有不同,但實現(xiàn)的按鈕截流功能是類似的,本文通過示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-05-05
  • vue+F2生成折線圖的方法

    vue+F2生成折線圖的方法

    這篇文章主要為大家詳細介紹了vue+F2生成折線圖的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • vuex中的5個屬性使用方法舉例講解

    vuex中的5個屬性使用方法舉例講解

    vuex是專門為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式,下面這篇文章主要給大家介紹了關(guān)于vuex中5個屬性使用方法的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-04-04

最新評論

沾化县| 屏边| 裕民县| 和田市| 玉林市| 筠连县| 积石山| 利津县| 祁门县| 多伦县| 平和县| 应城市| 新乡市| 福清市| 云南省| 连云港市| 郁南县| 广南县| 玉田县| 阿克陶县| 鹿泉市| 崇信县| 芦溪县| 讷河市| 梁平县| 九寨沟县| 江山市| 子洲县| 光山县| 米易县| 日照市| 行唐县| 阳原县| 普格县| 梁山县| 理塘县| 天祝| 丘北县| 余干县| 登封市| 秦皇岛市|