vueプルダウンリストの2つの実装方法の比較


vueプルダウンリストの2つの実装
一つ目は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でcolumeTypearを定義する必要があります。以下の通りです。

data(){
    return {
       columeTypeArr:[{
            value:'String',
            label:'   '
        },{
            value:'Int',
            label:'  ',
        },{
            value:'Decimal',
            label:'   '
        }],
    }
}
二つ目は死を書く方式を採用します。
直接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で構成する必要があります。バックグラウンドからデータを戻す必要がある場合、明らかに第一の方法がいいです。
簡単なプルダウンリストパラメータが少ない場合には、2番目のものが明らかにより有利である。
vueプルダウンメニューコンポーネントの実現
私たちは一緒にVueのプルダウンメニューコンポーネントを実現します。
このような基本的なUIコンポーネントは、インターネット上にすでにたくさんあります。なぜ自分で実現しますか?車輪を繰り返して作るつもりはないですが、この過程を通して、vueコンポーネントの開発の細部と注意事項を振り返ってみたいです。
なぜプルダウンメニューのセットを選んだのですか?
なぜなら、スズメは小さいが、五臓がそろっていますが、この小さい部品は多くのvueコンポーネントの開発の知識点に関連しています。
じゃ、始めましょう。
まず、vue-cliのプロジェクトを作成します。私はvue-cli 3を使って、作成の過程を簡単にして、vueコンポーネントを作ります。DropDownList.vue
テンプレートを作成する前に、このコンポーネントのビュー構造と機能を分析します。
プルダウンメニューコンポーネントは二つの部分から構成されるべきです。
選択項目のテキスト
選択したいメニュー(標準非表示)
その主な機能は以下を含む。
マウスはドロップダウンメニューのコンポーネントを通して、選択するメニューを表示します。
マウスはプルダウンメニューのセットをスライドして、選択メニューを隠します。
選択したメニューの項目をマウスでクリックして、選択したテキストを更新し、コンポーネントが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>
テキストの右側のiタグを選択して、プルダウンメニューの三角形アイコンを実現します。以下のcssで背景図を使って実現します。
ルート要素divにマウスを追加しました。後に参照してください。
次に、このプルダウンメニューのスタイルを作成し、テンプレートの下にスタイルラベルを追加します。他のコンポーネントとのスタイルの衝突を防ぐために、私たちはコンポーネントを開発する時に、スタイルに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>
スタイルについてはここで詳しく展開しません。その中のいくつかの注意すべき点を言います。
そのi元素のデザインはネット画像を使っています。みんな自分で変えられます。
注文したメニューのulはcssに隠れてはいません。jsを通じてコントロールします。具体的な原因は以下の通りです。
選択されたメニューulは、ページ上の他の要素のレイアウトに影響を与えるべきではないので、絶対位置を使用します。
今のこのセットは大体このように長いです。

私たちはこのコンポーネントの属性を定義し続けています。明らかに選択されたメニューは属性として入ってきます。内部書き込みの死ではなく、属性は次のように定義されています。

<script>
export default {
    name: "DropDownList",
    props:{
        dataList:{
            type:Array,
            default(){
                return [
                    {name: "   "},
                    {name: "   "}
                ]
            }
        },
        labelProperty:{
            type:String,
            default(){ return "name" }
        }
    },
    data(){
        return {
            activeIndex:0
        }
    },
}
その中のdataListは選択メニューのデータソースの属性です。ここではこの属性にデフォルト値を定義しました。これも筆者が身につけた習慣です。コンポーネントとしては、デフォルト値が一番いいです。他の人があなたのコンポーネントを使う時は、先に属性を設定しないと完成品の効果が見られます。あなたのこのコンポーネントに必要な属性のデータの詳細も速く確認できます。
もう一つの属性はLabel Propertyです。この属性の役割は何ですか?私達の実際のプロジェクトのデータソースは必ずしもnameというフィールドを含んでいませんので、プルダウンメニューでデータのテキストをレンダリングできなくなる可能性があります。この属性を定義して、実際のデータソースを指定してテキストをレンダリングするフィールドを指定しました。このフィールドは文字列でなければなりません。この属性のデフォルト値はnameで、デフォルトのデータソースと一致する必要があるためです。また、コンポーネントの内部データを見ました。activeIndexは現在選択されている項目のインデックスを表しています。後で使います。
今は他のところでこの部品を導入して使うことができます。まだ完成していませんが、先にそれを界面に表示させてもいいです。

<template>
  <div class="home">
    <DropList :dataList="dplist" labelProperty="city" @change="onDpChange($event)"></DropList>
    <p>      </p>
  </div>
</template>
<script>
  import DropList from '@/components/DropDownList.vue'
  //     
</script>
このページは我々のDropDownListコンポーネントを導入して使用しています。data List=「dplist」は現在のページのdplist配列をコンポーネントのdata List属性に結びつけています。この配列の中のオブジェクトはcityフィールドがあります。このフィールドはプルダウンメニューに表示されることを望んでいます。したがって、私たちはコンポーネントのlabelPropertyを設定します。このコンポーネントの内部にはこのイベントを送る必要があります。以下を参照してください。
コンポーネントのテンプレート部分に戻ります。いずれも静的な内容であることが分かりました。これらの静的な内容を属性によってレンダリングするように修正しました。

<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[label Property]であり、開発者が指定したフィールドを正確に表示することができる。
選択した項目のテキスト表式を見てみます。dplLabelはこの属性を定義していません。また内部データを定義していません。どこから来ましたか?選択した項目のテキストはdataList[activeIndex][label Property]ですが、この表式は長すぎて、テンプレートに書いておくと維持には不利です。計算属性に記入します。

computed:{
        dplLable(){
            return this.dataList[this.activeIndex][this.labelProperty]
        }
    }
上のdplLabelがあって、属性を計算するのは本当に使いやすいです。
プルダウンメニューの表示とデータの関連部分はもう書き終わりました。これからその機能を実現します。
第一歩は先に選択したいメニューをデフォルトで隠します。ここではどうして直接cssのdisplay:noneを使わないですか?そしてマウスが通る時display:blockでいいですか?このようにすると、選択されたメニューの項目をクリックして隠すことができません。私たちはjsでコントロールしますが、vueは直接dom元素にアクセスするのはよくないです。コンポーネント初期化の時にdom元素にアクセスしたいです。一番便利な方法があります。
私たちはプルダウンメニューのコンポーネントに局所的なカスタムコマンドを追加しました。コードは以下の通りです。

directives:{
        dpl:{
            bind(el){
                el.style.display = "none";
            }
        }
    },
このdplはカスタムコマンドです。下手なネーミングを無視してください。そして、私たちはカスタムコマンドのフック関数bind方法で、el要素にアクセスして、そのstyle属性display:noneを制御します。最後に、このカスタムコマンドをテンプレート内のulラベルに追加します。忘れずにvをかけてください。効果を見てください。メニューはもう隠されています。

<ul v-dpl>
私たちはカスタムコマンドのフック関数を使ってdom要素にアクセスし、domの制御を実現しました。これはとても実用的です。
最初にドロップダウンメニューに定義したマウスの経過とマウスの滑り出しのモニターを引き続き実現し、選択待ちメニューの表示と非表示を実現します。

onDplOver(event){
    let ul = event.currentTarget.childNodes[1];
    ul.style.display = "block";
},
onDplOut(event){
    let ul = event.currentTarget.childNodes[1];
    ul.style.display = "none";
},
私たちはマウスのイベントで、イベントのcurrent Targetオブジェクトにアクセスしましたが、なぜtargetではないですか?プルダウンメニューのサブ要素もこのイベントをトリガしますので、ターゲットにアクセスすれば、私たちが期待するトップレベルの要素ではないかもしれません。
最後のステップは、選択したいメニュー項目のクリックイベントを実現します。クリックした後、メニューを隠して、内部状態を修正し、イベントを配布します。

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]
    })
}
ここで注意が必要です。私たちはli元素を通して外側のレイヤーのul要素を見つけますが、Pathはフォックスとsafariをサポートしていません。幸いこの二つのブラウザはcompsedPathをサポートしています。そのため、最初の行のコードの互換性の書き方があります。その後、内部データのactiveIndexを修正することによって、選択されたテキストの更新を実現し、最後にeitメソッドを呼び出して父要素に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がどのようにプルダウンメニューのコンポーネントを実現するかを示しました。簡単ですが、コンポーネント開発によく使われるいくつかの特性にも関連しています。参考にしていただければと思いますが、どうぞよろしくお願いします。