用两种方式实现搜索的功能

在这里我用两种方式来实现搜索,一种是组件的未拆分,另一种是用组件拆分来实现

一、用组件的未拆封的方式来实现(Vuex来管理数据)

sore中的数据(即Vuex)

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
	state:{
		list:[
			'html','css','javascript','vue','react','jquery','html5','css3'
		]
	},
	actions: {},
	modules: {}
})

Main.vue组件

<template>
	<div>
		<!-- 搜索的未拆分 -->
		<!-- 绑定输入框的值并作筛选  失去焦点的时候让他隐藏  当按下下键的时候执行 当按下上键的时候执行  当按下回车的时候,把值给到输入框 -->
		<input type="text" v-model="val" @input="show" @blur="blur" @keydown.down.prevent="down" @keydown.up.prevent="up"
		 @keydown.enter.prevent="enter">
		 <!-- 判断鼠标移入的时候,让mouse为true,鼠标离开的时候,让mouse为false -->
		<div class="search-list" v-show="isShow" @mouseenter="mouse=true" @mouseleave="mouse=false">
			<!-- 当tap与要选中的下标一样的时候,选中背景变颜色 -->
			<div v-for="(item,index) in list" :key="index" :class="{'sel':tap==index}" @mouseenter="tap=index" @click="enter">
				{{item}}
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				list: [], //全部数据
				val: '', //输入框的值
				isShow: false,//判断是否要展示数据
				tap: -1,//在按上键和下键以及那个鼠标移入的时候的下标
				mouse: false,//判断鼠标的移入和移出
			}
		},
		methods: {
			//键盘输入事件
			show() {
				// 首先清空原来的数据
				this.list = [];
				// 拿到下标
				this.tap = -1;
				// 遍历所有的数据,如果输入框输入的值与list的一样,就添加到list页面上
				this.$store.state.list.map(item => {
					if (item.includes(this.val)) {
						this.list.push(item)
					}
				});
				// 判断list的数据的长度大于0,就展示数据,否则就隐藏
				if (this.list.length > 0) {
					this.isShow = true
				} else {
					this.isShow = false
				}
			},
			// 输入框失去焦点
			blur() {
				if (this.mouse) {
					return
				}
				this.isShow = false;
			},
			//下方向键
			down() {
				if (this.tap == this.list.length - 1) {
					return
				}
				this.tap++;
			},
			// 上方向键
			up() {
				if (this.tap == -1) {
					return
				}
				this.tap--;
			},
			// 回车事件
			enter() {
				this.val = this.list[this.tap];
				this.isShow = false;
			}
		}
	}
</script>

<style>
	input {
		width: 300px;
		height: 30px;
		font-size: 16px;
	}

	.search-list {
		border: 1px solid #000;
		width: 300px;
		line-height: 40px;
	}

	.sel {
		background-color: #EEEEEE;
	}
</style>

最终的效果
在这里插入图片描述

二、用组件的拆封的方式来实现(在这里是获取json数据)

json数据(hot.json)

{
	"world":[
		"html",
		"css",
		"javascript",
		"vue",
		"node",
		"jquery",
		"html5",
		"css3",
		"react",
		"hello"
	]
}

引入axios
先执行指令:cnpm i axios --save
在main.js中引入axios

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'

Vue.config.productionTip = false
Vue.prototype.$axios = axios

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

在这里要用到子传父
父组件:(Test.vue)

<template>
	<div>
		<input type="text"
		 v-model="val"
		  @input="search"
		   @keydown.down.prevent="down"
			@keydown.up.prevent="up"
			@keydown.enter="enter"
			 />

		<search-list
		 :list="list"
		  :tap="tap"
		   :show="isShow"
			@ok="enter"
			 @menter="mEnter"></search-list>
	</div>
</template>

<script>
	import SearchList from '../components/SearchList.vue'
	export default {
		components: {
			'search-list': SearchList
		},
		data() {
			return {
				word: [], //全部的数据
				val: '', //输入框中的数据
				list: [], //用于存放符合搜索条件的元素
				tap: -1, //被选中的元素下标
				isShow: false, //搜索结果默认显示状态
			}
		},
		// 拿到json中的数据
		created() {
			this.$axios.get('/hot.json')
				.then(res => {
					this.word = res.data.world;
				})
		},
		methods: {
			// 键盘输入事件
			search() {
				this.list = [];
				this.isShow = true;
				this.tap = -1;
				this.word.map(item => {
					if (item.includes(this.val)) {
						this.list.push(item);
					}
				})
			},
			// 上方向键
			up() {
				if (this.tap == 0) {
					return
				}
				this.tap--;
			},
			// 下方向键
			down() {
				if (this.tap == this.list.length - 1) {
					return
				}
				this.tap++;
			},
			// 回车事件
			enter() {
				this.val = this.list[this.tap];
				this.isShow = false;
			},
			mEnter(index) {
				this.tap = index;
			}
		}
	}
</script>

<style>
	input {
		width: 200px;
	}

	.search-list {
		border: 1px solid #999;
		width: 200px;
	}

	.search-list p {
		line-height: 30px;
	}

	.sel {
		background-color: #EEEEEE;
	}
</style>

子组件:(SearchList.vue)

<template>
	<div>
		<div class="search-list" v-show="show">
			<p v-for="(item,index) in list" :key="index" :class="{'sel':tap==index}" @mouseenter="menter(index)" @click="clickme"
			 class="search-item">

				<span style="font-size: 14px;">{{item}}</span>
			</p>
		</div>
	</div>
</template>

<script>
	export default {
		props: {
			list: {
				type: Array
			},
			tap: {
				type: Number
			},
			show: {
				type: Boolean
			}
		},
		methods: {
			clickme() {
				this.$emit('ok')
			},
			menter(index) {
				this.$emit('menter', index)
			}
		}
	}
</script>

<style scoped="scoped">
	.search-item {
		border-bottom: 1px solid #eee;
		display: flex;
		flex-direction: row;
		justify-content: space-between;
		align-items: center;
	}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值