###### tags: `Vue` `autocomplate`
{%hackmd BJrTq20hE %}
# Vue店商網頁-AutoComplate功能製作
autoComplate是一種自動將輸入至input的關鍵字自動補齊並完成輸入的功能。這裡的製作思路是把autoComplate當成一個compontne,然後在SerarchBar這個component使用。
## 1.AutoComplate的邏輯與資料運作
```javascript=
<script>
// 使用pinia做狀態管理,productStore,也是產品資料的來源。
import { mapState } from 'pinia'
import productStore from '@/stores/products'
export default {
// 由searchBar傳進來的input關鍵字資料與input有沒有focus
props: ['inputData', 'isFocus'],
// sendAutoCompleteResult將關鍵字與productStore比較後的結果送出,sendInfoBlank則是未達條件送出空字串
emits: ['sendAutoCompleteResult', 'sendInfoBlank'],
data () {
return {
// 用來儲存比較關鍵字後的結果
inFoList: [],
// 使用鍵盤上下鍵控制AutoComplate的index
listIndex: 0,
// mousein狀態紀錄
isMouseIn: false
}
},
computed: {
// pinia接收porductStore資料的方式
...mapState(productStore, ['guestProduct'])
},
watch: {
// 監控inputData如果是空字串則清空inFoList,如果有資料則執行autoComplete()
inputData: {
handler (newValue) {
if (newValue === '') {
this.inFoList = []
} else {
this.autoComplete(newValue)
}
}
}
},
methods: {
// mouseoverHover v-bind滑鼠事件mouseover
mouseoverHover (index) {
// listIndex為null 這樣子由鍵盤控制的樣式才不會顯示
this.listIndex = null
this.isMouseIn = true
// 當mouseover到第index的list時,list加入autoBackground這個樣式
const chosen = document.querySelectorAll('.auto')
chosen[index].classList.add('autoBackground')
},
// 為滑鼠離開始取消list的autoBackground樣式
mouseleaveCancelHover (index) {
const chosen = document.querySelectorAll('.auto')
this.isMouseIn = false
chosen[index].classList.remove('autoBackground')
},
// 將關鍵字與products內的資料作搜尋,並且只把product title存成陣列
autoComplete (info) {
if (info !== '') {
const infoArr = info.split(' ')
if (this.guestProduct !== undefined) {
this.guestProduct.forEach((item) => {
infoArr.forEach((i) => {
if (item.title.indexOf(i) !== -1 || item.category.indexOf(i) !== -1 || item.content.indexOf(i) !== -1 || item.description.indexOf(i) !== -1) {
this.inFoList.push(item.title)
this.inFoList = [...new Set(this.inFoList)]
}
})
})
}
// 如果輸入一樣的關鍵字就不顯示
if (this.inFoList.length > 0) {
this.inFoList = this.inFoList.filter((item) => { return item !== info })
}
} else if (info === '') {
this.$emit('sendInfoBlank')
}
},
// 把比較的結果送出
sendAutoComplete (info) {
if (info === '' || info === undefined) {
this.$emit('sendInfoBlank')
} else {
this.$emit('sendAutoCompleteResult', info)
this.inFoList = []
}
}
},
mounted () {
// 監控鍵盤的上下鍵與Enter、NumpadEnter,如果是上下鍵則是控制autoComplate list選擇樣式,如果是確定鍵則是送出選擇結果。
window.addEventListener('keydown', (e) => {
if (this.inputData && this.listIndex !== '') {
switch (e.code) {
case 'ArrowDown' :
if (this.listIndex === this.inFoList.length - 1) {
this.listIndex = this.inFoList.length - 1
} else { this.listIndex += 1 }
break
case 'ArrowUp' :
if (this.listIndex === 0) {
this.listIndex = 0
} else { this.listIndex -= 1 }
break
case 'Enter' || 'NumpadEnter' :
this.sendAutoComplete(this.inFoList[this.listIndex])
break
}
} else if (this.inputData === '') { this.listIndex = 0 }
})
}
}
</script>
```
## 2.AutoComplate的template
```htmlembedded=
<template>
<ul class="autoUl position-absolute top-100 w-100 w-sm-33 w-sm-50"
<!--當有輸入資料且searchBar是focus狀態或autoComplate是mouseOver狀態時顯示autoComplate-->
v-if="inFoList.length > 0 && (isFocus || isMouseIn)"
>
<li class="auto py-0" style="height:36px"
v-for="(item,index) in inFoList"
:key="item+index"
<!--用來顯示鍵盤上下鍵所控制的list-->
:class="{'autoBackground' : (index === listIndex)}"
@click="sendAutoComplete(item);"
@mouseover="mouseoverHover(index)"
@mouseleave="mouseleaveCancelHover(index)">
<p class="py-1 my-0">{{item}}</p>
</li>
</ul>
</template>
```
## 3.autoComplate樣式
```sass=
<style lang="scss">
.autoUl {
background: #fff;
z-index: 1;
padding: 0;
list-style: none ;
}
.autoBackground {
background: rgb(155, 150, 150) !important;
}
.auto {
padding-left: 12px;
background: rgb(225, 224, 224);
&:hover {
cursor:pointer;
}
}
</style>
```