Vueカスタムディレクティブを使用してSelectコンポーネントを実装する

1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...

この記事では非常にシンプルなSelectコンポーネントを書くことを教えてくれますが、おそらく多くの人がSelectを書いているのはあまり一般的ではありませんが、この記事の例ではVueのカスタム指示を使っていますあなたがそれに慣れているなら、この記事はあなたに何かを得るかもしれません!

完了したレンダリングは次のとおりです。

まず、簡単にレイアウトしましょう:


<template>
<div class="select">
<div class="inner">
<div class="inputWrapper">
<input type="text" readonly placeholder="请选择菜品">
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options">
<li v-for="(item, index) in options" :key="index">{{item.value}}</li>
</ul>
</div>
</div>
</template> 
......
data() {
return {
options: [
{
value: '西红柿鸡蛋'
},
{
value: '青椒抱鸡蛋'
},
{
value: '回锅肉'
},
{
value: '宫保鸡丁'
},
{
value: '地三鲜'
}
],
}
}

その効果は次のとおりです。

以下のオプションは絶対配置ですが、同時に入力は読み取り専用に設定されているため、入力は入力できません。全体のレイアウトは非常に簡単です。

次に、機能を追加する

次に、2つの機能を追加します。

上の入力ボックスをクリックして、以下のオプション間を切り替えます。
オプションでオプションを選択し、オプションを部分的に消したまま入力に表示させます。

これらの2つのプロジェクトの機能は非常に単純です、最初のものを完了して、入力ボックスをクリックしてv-showでオプションを表示するように切り替えます。


<div class="inputWrapper" @click="showOptions = !showOptions">
<input type="text" readonly placeholder="请选择菜品">
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options" v-show="showOptions" v-show="showOptions"> //添加v-show
<li v-for="(item, index) in options" :key="index">{{item.value}}</li>
</ul>
......
data() {
showOptions: false
}

上記のように、 v-show="showOptions"オプションに追加し、showOptionsをfalseに初期化します。 同時に、パーセル入力のdivにclickイベントを追加して、showOptionsのブール値を切り替えます。

その効果は次のとおりです。

2番目のオプションは、以下のオプションをクリックして入力に選択され、オプションが消えるようにします。難しくありません。


<div class="inputWrapper" @click="showOptions = !showOptions">
<input type="text" readonly placeholder="请选择菜品" :value="selected"> //这里用value绑定一个data值selected
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options" v-show="showOptions">
<li v-for="(item, index) in options" :key="index" @click="choose(item.value)">{{item.value}}</li>
</ul>
......
data() {
return {
......
showOptions: false
selected: ''
}
},
methods: {
choose(value) {
this.showOptions = false
if (value !== this.selected) {
this.selected = value
}
}
}

ロジックは非常に単純で、データ値を入力値にバインドし、オプションをクリックして選択し、オプションの内容をデータ値に割り当て、オプション内容全体を非表示にします。

その効果は次のとおりです。

上記のレンダリングからわかるように、既に選択可能ですが、オプションのコンテンツが表示されているときに、選択を隠すために他の空白の場所をクリックしても問題はありませんが、上記のコードは解決されません。この質問を解決するには、2つの方法を使用します。

3、従来のDOM操作VS Vueカスタム命令

実際、この機能を実装するのは難しくありませんが、DOMを操作して解決する必要があります。


<div class="inputWrapper" @click.stop="showOptions = !showOptions"> //注意这里的stop修饰器
<input type="text" readonly placeholder="请选择菜品" :value="selected">
<span class="iconfont icon-zhankaishangxia"></span>
</div>
<ul class="options" v-show="showOptions">
<li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li> //还有这里的stop修饰器
</ul>
...
data() {
return {
......
showOptions: false
}
}
mounted() {
let that = this
document.addEventListener('click', function() {
that.showOptions = false
})
}

上記のコードには2つのポイントがあります.1つは、インストール後にドキュメント全体にクリックイベントを追加することです。オプションをクリックすると非表示にすることができますが、入力ボックスの部分とオプションの内容をクリックするとトリガしないようにします。これは私が前に書いたロジックになるようにするためです。クリックイベントをクリックすると、バブルが発生しないように、バブルを防ぐためにストップデコレータを両方のクリックイベントに追加しました。 その効果は次のとおりです。

基本的な関数が書かれたので、$ emitとpropsを追加してデータを追加してより一般的なものにすることができます。 しかし、結局、オプションを部分的に消すために他の場所をクリックする機能、それを改良することもできます.Vue命令の使用を検討することもできます。

Vueコマンドについては、公式ドキュメントにはっきりと説明があります。理解できない場合は、ここをクリックして最初に確認してください!

Vueのカスタム指示については、この例の次の基本的な点を理解する必要があります。

これはDOMを操作するために使用されるため、すべてのVue命令はテンプレートの要素にハングします。

これは4つのフック関数を持ち、1つはバインドであり、命令が最初に要素にバインドされ、1回だけ呼び出されるときに呼び出されます。このフックは非常に重要で、この例では使用し、2つ目は挿入します。この要素は、親要素に挿入されたときに呼び出されます。これはvフォーカスの例の公式ドキュメントで使用され、3番目と4番目はupdateとcomponentUpdated、前者はvNodeの更新時に呼び出され、後者は更新が完了した後に呼び出され、最後にアンバインドされ、命令と要素がアンバンドルされたときに呼び出されます。

これらの4つのフック関数は、少なくとも3つのパラメータをすべて渡すことができます。最初は、バインドされた命令の要素であり、2番目のバインディングはオブジェクトであり、いくつかのプロパティは特に便利です。もちろん、価値観などは、これらの3つだけでなく、この例を使用します。 例:v-example = "test"というカスタムディレクティブを記述し、このテストがメソッドで記述したメソッドである場合、binding.nameを介してサンプルの文字列を取得できます。これはbinding.valueを介して渡すことができますテスト関数自体を取得して実行します。 あなたがここでそれを理解していなければ、それは大丈夫です、私たちはそれについて話します。

詳しく見ると、Vue自身のライフサイクルフック機能に非常によく似ていますが、命令や要素に作用する点が異なります。 バインドの開始から最後のアンバインド解除までバインドすると、完全なサイクルが完了します。

さて、以前にマウントされていたDOM操作に関連するすべてを削除して、カスタムコマンドを書き始めましょう。


<ul class="options" v-show="showOptions" v-clickOut="test"> //这里使用了下面的自定义指令,并将一个test方法传递进去了
<li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li>
</ul>
...
methods: {
......
test() {       //test函数,它作为参数传递给了指令
console.log('这是一个测试函数')
}
}, 
directives: {       //这里是自定义指令
clickOut: {       // 这里是自定义的v-clickOut指令
bind: function(el, binding) {    // bind钩子函数,当它与元素绑定的时候就会执行
console.log('el===>', el)
console.log('binding.name===>', binding.name)
console.log('binding.expression===>', binding.expression)
console.log('binding.value===>', binding.value)
}
}
}

上記のコードには明確なコメントがあります。私たちはclickOutディレクティブをカスタマイズして要素にフックし、テストメソッドを渡しました。console.logの内容を見てみましょう。ねえ。

上記の図から、命令が要素にバインドされると、バインド関数が実行されて多くの有用なものが得られることがわかります。 elは命令バインディング自体の要素であり、バインディングはオブジェクトであり、渡された関数を含む多くの有用なものが得られることが非常にはっきりとわかります。

基本的な構造を理解し、私たちはこの指導を改善し続けます。


<ul class="options" v-show="showOptions" v-clickOut="test">
<li v-for="(item, index) in options" :key="index" @click.stop="choose(item.value)">{{item.value}}</li>
</ul>
...
methods: {
test() {
this.showOptions = false  
}
},
directives: {
clickOut: {
bind: function(el, binding) {
document.addEventListener('click', function(e) {
if (el.contains(e.target)) return false
if (binding.expression) {
binding.value()
}
})
}
}

上に書かれたコードを見て? 論理を言う:カスタムv-clickOutがoptionsセクションのul要素にバインドされているとき、クリックされた要素がディレクティブまたはバインドされた要素によってバインドされている要素の子である場合、ドキュメントのclickイベントを待ち受けます。それ自身では何もしないでください。そうでなければ、渡されたテスト関数を実行します。 テスト関数の実行結果は、オプションを部分的に隠すことです。

論理は明らかです。

もちろん、私たちはそれを改善し続けることができます。 document.addEventListenerを与えて、適切な時にremoveEventListenerを呼び出すこともできます。これは、必要に応じてunbindフック関数です。

それで完璧にできる:


......
directives : {
clickOut: {
bind: function(el, binding) {
function handler(e) {
if (el.contains(el.target)) return false
if (binding.expression) {
binding.value()
}
}
el.handler = handler
document.addEventListener('click', el.handler)
},
unbind: function(el) {
document.removeEventListener('click', el.handler)
}    
}
}

コードは上記のとおりですが、その効果は次のとおりです。

簡単にまとめてみましょう:DOMを操作する必要があるため、これは非常に単純な例です。カスタムを使用して完了するように選択したので、もちろん他の方法も使用できます。 ただし、Vueを使用する場合は、DOMを操作する必要がある場合は、カスタム命令を使用して考えることができます。


1 Star2 Stars3 Stars4 Stars5 Stars (まだ評価されていません)
Loading...
      この投稿は審査処理中  | 元のサイトへ