Vue百度搜索框实例
2019-11-11 本文已影响0人
果木山
百度搜索框实例
- 思路:
- 通过vue.js和bootstrap.js来构建搜索框和列表页面架构;
- 文本输入框通过v-model设置与应用的双向绑定,列表框通过v-for来遍历,获取遍历的数据动态绑定在列表中;
- 设置
@keyup
事件,触发函数,函数内,通过vue-resource插件,进行jsonp请求数据,请求百度服务器上的数据,通过设置params中的wd值来进行查找数据,赋值给ary,遍历到列表中; - 实现文本输入框输入内容,列表同时更新数据;
- 设置列表中第一条数据点亮效果,动态绑定样式,利用
:class="{active:index===i}"
,意思为,当index值与i值相等时,设置类名active;其中index为data中设置的值,i为遍历ary数组时的列表数据索引值; - 设置列表中第一条数据点亮,即设置index的初始值为0;
- 设置下键效果:按键盘中的下键,实现列表数据的变化和点亮;同时输入框中的数据显示选中的列表中的数据;
- 设置
@keydown.down
事件,触发putDown函数,函数中改变this.index的值,让其累加,然后通过%来控制上限;
- 设置
- 设置上键效果:按键盘中的上键,实现列表数据的变化和点亮;同时输入框中的数据显示选中的列表中的数据;
- 设置
@keydown.up
事件,触发putUp函数,函数中改变this.index的值,使其累减,然后判断边界值;控制下限; - 注意:按上键时,文本框中会默认选中文字的最前面,所以需要阻止默认事件,即设置
@keydown.up.prevent
事件;
- 设置
- 设置上下键的效果中,需要注意,在更新输入框中的数据后,会执行keydown事件,重新进行数据获取,然后更新列表数据,所以,需要在keydown事件函数中,设置条件判断,通过事件对象e.keyCode来判断上下键,当按下上下键时,阻止搜索程序;
- 设置回车键效果:当按下enter键后,搜索文本框中的内容;
- 设置
@keydown.enter
事件,触发goSearch函数,函数中利用window.open(url)
来打开搜索地址;
- 设置
- 注意点:
- 文本框必须绑定keyup事件,不能绑定keydown事件;在获取数据时,必须判断msg是否为空,如果为空,则无需发送请求,并赋值ary为空;
- 实例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>百度搜索框</title>
<link rel="stylesheet" href="css/bootstrap.css"/>
</head>
<body>
<div class="container">
<div id="app">
<h1>百度搜索</h1>
<form>
<div class="form-group">
<input type="text" class="form-control" id="text" v-model="msg" @keyup="getData" @keydown.down="putDown" @keydown.up.prevent="putUp" @keydown.enter="goSearch"/>
</div>
</form>
<ul class="list-group">
<li v-for="(item,i) in ary" class="list-group-item" :class="{active:index===i}">{{item}}</li>
</ul>
</div>
</div>
<script src="js/vue.js"></script>
<script src="js/vue-resource.js"></script>
<script>
new Vue({
el:"#app",
data:{
msg:"",
ary:[],
index:0
},
methods:{
getData(e){
//当按下键和上键时,阻止搜索功能;
if(e.keyCode===38 || e.keyCode===40) return;
//发送jsonp请求,跨域获取数据
if(this.msg!==""){
this.$http.jsonp("https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",{
params:{
wd:this.msg
},
jsonp:"cb"
}).then(res=>{
this.ary=res.body.s;
})
}else{
this.ary=[];
}
},
putDown(){
//按下键,让对应的变亮,主要是改变this.index的值
this.index++;
this.index%=this.ary.length;
//更新文本框中的数据
this.msg=this.ary[this.index];
},
putUp(){
//按上键,让对应的变亮
this.index--;
if(this.index<0){
this.index=this.ary.length-1;
}
this.msg=this.ary[this.index];
},
goSearch(){
//按下回车键,跳转搜索
window.open(`https://www.baidu.com/s?wd=${this.msg}`,"_blank")
}
}
})
</script>
</body>
</html>
升级版百度搜索框实例
- 思路:
- 引入bootstrap插件;写出静态页面;
- 通过vue-resource插件,向百度服务器发送请求,获取数据; 文本框绑定keyup事件,当键盘抬起时,获取新的输入值,然后在获取数据;
- 获取数据赋值dataAry变量,通过v-for遍历插入dom结构;
- 功能1:通过按向上,向下键来使对应列表中的内容赋值到文本输入框内,并且该列被点亮;
- 文本框需绑定两个事件:keydown.up和keydown.down 指的是键盘上向下和向上按键事件;注意:当向上按键时,光标会在文本的最前面,所以需要阻止默认事件,则需绑定keydown.up.prevent
- 设置变量n,作为整个项目中的介质,目的:通过设置n的值,来点亮指定的列表;
- 在html中,绑定li时,通过v-bind来绑定class,设置为三目,通过判断index和n-1值是否相等,来设置类名,进而点亮列表;
- 在两个事件触发的函数中,对n进行自加和自减处理,设置边界值判断;
- 对文本框内数据进行赋值:在事件函数中,通过n的值来获取指定列表的索引值,进而在dataAry数组中找到对应的元素内容,赋值给msg即可;
- 当向上向下回到文本框时,让文本框中的数据为最开始输入的内容;方法:设置变量initVal,用来存储最初的输入值,赋值位置为getData()函数中,在每次向百度服务器发送请求之前,赋值给initVal;
- 注意:文本框绑定了keyup事件,当向下和向上按键触发后,也会再次触发,所以,必须阻止两个事件的执行;方法:通过事件对象e来获取按键码,进而阻止指定按键码的执行;
- 功能2:光标移入列表后,列表项被点亮;文本框中的内容不改变;并且,光标移出列表后,点亮消失;满足:当光标移入一个列表后,该列表被点亮,然后按上下键,列表会依次被点亮;
- 给每个列表绑定两个事件:mouseenter和mouseleave事件;光标移入移出事件;
- 事件函数中,通过获取列表的索引值,来赋值n的值;进而实现点亮功能;
- 移出函数中,赋值n值为文本框对应的值;
- 功能3:当按键盘enter键后,跳转到新的页面搜索;当鼠标点击列表项时,跳转到新的页面加载;
- 给文本输入框绑定keydown.enter事件;
- 给列表项绑定click事件;
- 两个事件,可以绑定同一个函数;
- 跳转到新的页面加载:通过window.open(url)实现;window.href=url实现在本页面中加载;
- 注意:keydown.enter事件绑定时,为传入实参,则触发后会给函数体默认传入事件对象e,而click事件因为赋值实参,所以不会默认传入事件对象e;所以需要给函数体设置两个形参;判断第二个形参是否被赋值实参,来判断是触发的哪个事件;进而进行不同操作;
- 注意点:
- 文本输入框中绑定keyup事件,不能绑定keydown事件,当键盘抬起时,获取msg,然后获取数据;
- 在获取数据之前,必须判断msg是否为空,若为空,则无需在发送请求获取数据;
-
@keydown.enter
和@click
事件;1)在绑定事件时,如果不传实参,则事件触发后默认向函数体中传入一个事件对象e;2)在绑定事件时,若给函数体传了实参值,则事件在触发后,不会再默认传入事件对象,若需要获取事件对象,则可在传入实参时,传入$event
实参; - 鼠标移入移出事件@mouseenter和@mouseleave;
-
window.location.href=url
指的是:在本页面中加载新页面;
window.open(url)
指的是:在新的页面中加载新页面;
- 实例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>升级版百度搜索框实例</title>
<!-- Bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
h1{
margin: 20px 0 10px;
}
.input-group{
width: 100%;
}
.input-group .form-control:last-child{
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
.input-group .form-control:first-child{
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
.list-group{
margin: 15px 0;
}
.list-group .list-group-item{
cursor: pointer;
}
.bgc{
background-color: lightskyblue;
}
</style>
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div id="app">
<h1>百度搜索框实例</h1>
<div class="input-group">
<input type="text" class="form-control" v-model="msg" @keyup="getData" @keydown.up.prevent="putUp" @keydown.down="putDown" @keydown.enter="goSearch"/>
</div>
<ul class="list-group">
<li class="list-group-item" v-for="(item,index) in dataAry" :class="index===n-1?'bgc':''" :key="index" @mouseenter="mouseEnter(index)" @mouseleave="mouseLeave(index)" @click="goSearch(index,item)">{{item}}</li>
</ul>
</div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js"></script>
<!--引入vue.js-->
<script src="./js/vue.js"></script>
<!--引入vue-resource.js-->
<script src="./js/vue-resource.js"></script>
<script>
new Vue({
el: "#app",
created(){
if(this.msg=""){
this.dataAry=[];
}
},
data: {
initVal:this.msg,
msg: "",
n: 0,
dataAry: []
},
methods: {
getData(e){
//当按键为向上和向下时,无需获取新的数据
if(e.keyCode===38 || e.keyCode===40) return;
if(this.msg!==""){
this.initVal=this.msg;
this.n=0;
this.$http.jsonp("https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",{
params: {
wd: this.msg
},
jsonp: "cb"
}).then(res => {
var ary=res.body.s;
if(ary.length>=6){
ary.splice(6);
}
this.dataAry=ary;
},err => {
console.log(err);
})
}else{
this.dataAry=[];
}
},
putUp(){
this.n--;
if(this.n===0){
//赋值为原来输入框内的数据
this.msg=this.initVal;
return;
}
if(this.n<0){
if(this.dataAry.length>0){
this.n=this.dataAry.length;
}
}
//将数组内容赋给文本输入框
this.msg=this.dataAry[this.n-1];
},
putDown(){
this.n++;
if(this.n>this.dataAry.length){
this.msg=this.initVal;
this.n=0;
return;
}
this.msg=this.dataAry[this.n-1];
},
mouseEnter(index){
this.n=index+1;
},
mouseLeave(){
//移出后,背景色消失;
this.n=0;
},
goSearch(e,item){
//知识点:@keydown.enter和@click事件;1)在绑定事件时,如果不传实参,则事件触发后默认向函数体中传入一个事件对象e;2)在绑定事件时,若给函数体传了实参值,则事件在触发后,不会再默认传入事件对象,若需要获取事件对象,则可在传入实参时,传入$event实参;
//筛选,判断第二个参数是否会传入,若传入了,则为点击事件触发,则需将文本输入框内的数据赋值为列表框内的数据,并跳转页面
if(item!==undefined){
//如果不等于undefined,则为click事件
this.msg=item;
}
//跳转新页面搜索
window.open("https://www.baidu.com/s?wd="+this.msg);
this.n=0;
}
}
})
</script>
</body>
</html>