国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

使用Vue自定義指令實現Select組件

2019-11-19 13:47:06
字體:
來源:轉載
供稿:網友

本篇文章教大家寫一個非常簡單的Select組件,想必很多人都寫過Select,畢竟它太常用了,但是本篇文章的示例使用到了Vue的自定義指令,如果你對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: '地三鮮'      }    ],  }}

效果是這樣:

 

下面可供選擇的options用的是絕對定位;同時input設置了readonly,使input變的不可輸入,整體布局很簡單。

二、開始添加功能

接下來,我們要添加兩個功能:

  • 點擊上面的input框,可以切換顯示下面的options
  • 選擇options里的某個選項后讓它展示在input里,同時讓選項部分消失

這兩項目功能都挺簡單,先來完成第一個,點擊input框切換顯示options,借助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 。同時,在包裹 input 的 div 上添加 click 事件來回切換 showOptions 的布爾值。

效果如下:

 

第二個,點擊下面的選項,將被選擇的展示到input里,同時讓options消失,也不難。

<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    }  }}

邏輯很簡單,在input里用value綁定一個data值,點擊選擇某個選項后,將選項的內容賦給這個data值即可,同時,隱藏整個選項內容。

效果如下:

 

從上面的效果圖中可以看到,已經可以正常選擇了,但是有一個問題,就是它選項內容展示的時候,我們希望點擊其它空白的地方也可以讓選擇內容隱藏,但是上面的代碼并沒有解決這個問題,接下來我們來用兩種辦法來解決它。

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  })}

上面的代碼有兩點:一個是在mounted后面給整個document添加了點擊事件,這樣在點擊時候就可以將options隱藏,但是,我們在點擊輸入框部分和選項內容時,我們不希望它觸發,而是讓它走我們之前寫好的邏輯,所以給兩個 click 事件都添加了 stop 修飾器來阻止冒泡,這樣,點擊到它們的時候就不會冒泡到 document 上面了。效果如下:

 

到這里基本功能都寫完了,可以通過添加 $emit 和 props 來進行數據傳遞,讓它更加通用些。但是最后關于點擊其它地方讓選項部分消失的功能,我們還可以再完善下,可以考慮使用Vue指令的方式實現。

關于Vue指令,官方文檔里有比較清楚的說明,如果不是特別明白可以點擊這里先看看!

關于Vue自定義指令,在這個例子中需要明白以下基本知識點:

它是用來操作DOM的,所以所有Vue指令都會掛在 template 里的某個元素上

它有4個鉤子函數,一是 bind ,它在指令第一次綁定到元素上調用而且只調用一次,這個鉤子很重要,我們在這個例子里會用到;第二個是 inserted ,它在元素插入到父元素的時候調用,官方文檔里給了一個 v-focus 的例子就用到了它;第三個和第四個分別是 update 和 componentUpdated ,前者是在 vNode 更新時調用,后者是在更新完成后調用;最后是 unbind ,在指令和元素解綁時調用。

這4個鉤子函數可以 都至少可以傳3個參數 ,第一是 el 就是被綁定指令的元素,第二個 binding , 它是個對象 ,而且 它的一些屬性特別有用 ,它的屬性包括 name , expression 和 value 等,當然不只這三個,但是我們這個例子要用。舉個例子: 假如我寫一個自定義指令 v-example="test" ,而這個 test 是我在 methods 里寫的一個方法,那么就可以通過 binding.name 拿到 example 字符串,可以通過 binding.value 拿到 test 函數本身并且執行。如果這里不明白沒關系接下來我們會說到。

如果仔細觀察,它們非常像 Vue 本身的生命周期鉤子函數,只是它們是作用在指令上與元素的上的。從 bind 最開始綁定到最后 unbind 解綁完成了一個完整的周期。

好了,我們把之前 mounted 寫的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 的指令,并且把它掛到了一個元素上,而且給它傳了一個 test 方法,我們來看看 console.log 出的東西都是些啥。

 

從上面的圖片可以看出當指令和元素綁定的時候即 bind 的時候,它會執行bind函數獲得很多有用的東西,上面我們講了 bind 函數里有幾個重要的參數,從打印出的結果里我們非常清楚地看到,el就是指令綁定的元素本身,binding是一個對象,它獲得了很多有用的東西,包括傳遞進來的函數。

明白了它的基本構造,我們就來繼續完善這個指令。

<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 與選項部分的ul元素綁定的時候,我們監聽document的click事件,如果點擊的元素是被指令綁定的元素的子元素或是被綁定元素本身,那就什么都不做;如果不是,那就執行傳遞進來的test函數。而test函數執行的結果就是把選項部分隱藏。

邏輯很清楚。

當然我們可以繼續完善它。我們給 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的時候,那么可以想想可不可以通過自定義指令來實現呢!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 兖州市| 眉山市| 晴隆县| 吉水县| 桂东县| 眉山市| 金昌市| 阿拉尔市| 肥西县| 龙游县| 文化| 新化县| 临湘市| 东乡族自治县| 西藏| 库伦旗| 天津市| 山阳县| 黔南| 镇远县| 南开区| 正镶白旗| 西充县| 蓝田县| 昌平区| 永宁县| 大城县| 郸城县| 保康县| 咸宁市| 洮南市| 虎林市| 江陵县| 巴林左旗| 深泽县| 博爱县| 辽阳市| 三穗县| 改则县| 高平市| 贵南县|