Vue2.0组件实现动态搜索引擎(二)
接上一篇,完成logo部分我们就要开始整个项目的核心——panel组件。
整个panel组件分为3个部分:关键字输入框,相关搜索建议下拉列表和搜索跳转按钮。
由于我们整个项目是设计成父子组件的架构所以在父组件即panel部分开头需要引入子组件:
HTML:
<logo-select @logoNow="changeSource"></logo-select>
JS:
import logoSelect from './logo-new.vue';
export default {components: {logoSelect //等价于logoSelect: logoSelect}
注意使用相对路径不要照搬。
目前的效果如下。
接下来做我们的搜索框,这一步比较简单,设置一个input再用v-model做一个双向绑定到data:
<input type="text" v-model="msgInput">
data: function () {return {msgInput: '',...}
}
顺便加上一个“X”span,方便清空输入栏:
<span class="markDelete" @click="clearInput">x</span>
methods: {clearInput: function () {this.msgInput = '',//清空输入框this.results = ''//清空搜索建议数组},
...
}
这里比较偷懒用了个X字符代替清除按钮,对样式有追求的童鞋可以找个美观的图片,其他不变。
接下来就是核心功能:如何输入关键字就能自动弹出下拉菜单并且给出搜索建议?
由于我们要做的动态搜索建议,必然要使用其他搜索引擎的接口,那么跨域就成了主要技术难点。
翻阅了相关资料,使用jsonp跨域最为方便,Vue使用jsonp就要考虑vue-resource;
如果是第一次使用就要命令行安装:
npm install vue-resource --save
先在main.js引入vue-resource:
var vueResource = require('vue-resource');
Vue.use(vueResource);
然后我们在data里新建一个空数组以便将来存放jsonp获取到的搜索建议,之后便接着input标签写一个ul列表循环数组里的搜索结果。
<ul><li v-for="(item, index) in results">{{ item }}</li>
</ul>
给input设置一个键盘监听事件,触发jsonp:
@keyup="get($event)"
methods: {get: function (ev) {
//左右方向键不触发if(ev.keyCode === 38 || ev.keyCode === 40) {return;}//利用jsonp跨域this.$http.jsonp('https://sug.so.360.cn/suggest?word=' + this.msgInput+ '&encodein=utf-8&encodeout=utf-8').then(function(res) {//成功后执行函数this.results = res.data.s//将搜索建议赋给预先准备好的数组})}
}
如此一来,基本的跨域功能就实现了,下一步是解决父子间通信的问题。
子组件向父组件传递信息一般是子组件$emit一个参数,父组件监听这个参数,再执行相应函数:
<logo-select @logoNow="changeSource"></logo-select>
//监听的子组件函数不用写参数,但调用的函数需要加changeSource: function (index) {this.logoIndex = index}
如此一旦logo改变panel就能够得到logo的index,可以改变回车搜索的链接url:
logoData: [{name: '360搜索',url: 'https://www.so.com/s?ie=utf-8&fr=none&src=360sou_newhome&q='},{name: '百度搜索',url: 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd='},{name: '搜狗搜索',url: 'https://www.sogou.com/web?query='}
search: function () {window.open(this.logoData[this.logoIndex].url + this.msgInput)//进行字符串拼接url和搜索关键字}
最后还有一个要点就是模仿主流搜索引擎的上下键选取搜索建议到输入框的功能。
@keydown.up.prevent="selectUp()" @keydown.down="selectDown()" @keydown.enter="search()"//prevent可以阻止input默认事件光标回到最前
selectDown: function () {this.now++;//data中设置一个变量记录当前选中的indexif(this.now == this.results.length) {//到达最下回到顶部this.now = 0;}this.msgInput = this.results[this.now];//改变输入框内容},selectUp: function () {this.now--;if(this.now == -1) {//到达最上回到底部this.now = this.results.length - 1;}this.msgInput = this.results[this.now];}
上面代码的核心原理跟之前的logo组件部分类似,也是先设置选中背景色,再通过对应index控制输入框的当前内容。
最后贴出完整代码:
main.js:
import Vue from 'vue';
import App from './App1.vue';
import VueRouter from 'vue-router';var vueResource = require('vue-resource');
Vue.use(vueResource);
Vue.use(VueRouter);new Vue({el: '#app',render: h => h(App)
})
App1.vue:
<template><div id="app"><panel></panel></div>
</template><script>import panel from './components/panel-new.vue'export default {components: {panel}}
</script>
logo-new.vue:
<template><div class="logo"><img class="logoNow" :src="imgs[imgState].imgSrc" @click="toggle"><div class="triangle" @click="toggle"><span></span></div><div class="logoMain"><transition name="fade"><ul v-show="toggleState" class="listLogo" @mouseleave="leaveList"><li v-for="(item, index) in imgs" :class=" index == imgSelected ? 'colorBack' : ''" @click="changeImg(index)"@mouseover="changeBackColor(index)"><img :src="item.imgSrc"></li></ul></transition></div></div>
</template><script>export default {data () {return {//下拉图片背景初始值imgSelected: -1,//判断下拉条件toggleState: false,//界面显示哪张图片imgState: 0,//图片一类的静态文件,应该放在这个static文件夹下,// 这个文件夹下的文件(夹)会按照原本的结构放在网站根目录下imgs: [{imgSrc: ('.././static/360_logo.png')}, {imgSrc: ('.././static/baidu_logo.png')}, {imgSrc: ('.././static/sougou_logo.png')}]}},methods: {toggle: function () {this.toggleState = !this.toggleState,//清空上次背景色,this.imgSelected = -1},changeImg: function (index) {this.toggleState = !this.toggleState,this.imgState = index,this.$emit('logoNow', [index])},changeBackColor: function (index) {this.imgSelected = index},leaveList: function () {this.toggleState = false,this.imgSelected = -1}}}
</script>
panel-new.vue:
<template><div><logo-select @logoNow="changeSource"></logo-select><div class="inputSelect"><input type="text" v-model="msgInput" @keyup="get($event)" @keydown.up.prevent="selectUp()"@keydown.down="selectDown()" @keydown.enter="search()"><span class="markDelete" @click="clearInput">x</span><button @click="search">搜一下</button></div><div class="inputToggle"><!--多个元素/组件的过渡效果用transition-group,每个 <transition-group> 的子节点必须有 独立的key ,动画才能正常工作--><transition-group tag="ul" name="fade" class="ulResult" mode="out-in" v-cloak><li v-for="(item, index) in results" class="liStyle" :class="{selectback:index==now}"@mouseover="changeBack(index)" @click="msgChange(index)" :key="item">{{ item }}</li></transition-group></div></div>
</template><script type="text/javascript">import logoSelect from './logo-new.vue';export default {components: {logoSelect},data: function () {return {msgInput: '',results:[],now: -1,logoIndex: 0,logoData: [{name: '360搜索',url: 'https://www.so.com/s?ie=utf-8&fr=none&src=360sou_newhome&q='},{name: '百度搜索',url: 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd='},{name: '搜狗搜索',url: 'https://www.sogou.com/web?query='}]}},methods: {clearInput: function () {this.msgInput = '',this.results = ''},get: function (ev) {if(ev.keyCode === 38 || ev.keyCode === 40) {return;}//利用jsonp跨域this.$http.jsonp('https://sug.so.360.cn/suggest?word=' + this.msgInput+ '&encodein=utf-8&encodeout=utf-8').then(function(res) {this.results = res.data.s,this.now = -1})},selectDown: function () {this.now++;if(this.now == this.results.length) {this.now = 0;}this.msgInput = this.results[this.now];},selectUp: function () {this.now--;if(this.now == -1) {this.now = this.results.length - 1;}this.msgInput = this.results[this.now];},changeBack: function (index) {this.now = index},msgChange: function (index) {this.msgInput = this.results[index],window.open(this.logoData[this.logoIndex].url + this.msgInput)},search: function () {window.open(this.logoData[this.logoIndex].url + this.msgInput)},//监听的子组件函数不用写参数,但调用的函数需要加changeSource: function (index) {this.logoIndex = index}}}
</script>
逻辑功能的代码大致就是这样了,css部分大家可以结合自己喜好自行配置。
Vue2.0组件实现动态搜索引擎(二)相关推荐
- 关于vue2.0组件通信
1.父组件通过props属性给子组件通信 //父组件 <template> <child :show="is_showshare" :age="age& ...
- vue2.0组件生命周期探讨
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>vue ...
- vue 仿二手交易app_项目vue2.0仿外卖APP(二)
vue-cli开启vue.js项目 Vue.js开发利器vue-cli,是vue的脚手架工具. 在工地上,脚手架是工人搭建好的架子,能够帮助工人们作业:在技术圈,脚手架就是来帮助我们编写好基础的代码的 ...
- vue2.0组件之间的通信
官方建议可以直接使用一个空vue实例来处理简单的事件触发机制 var bus = new Vue(); bus.$emit('create',{title:'name'}); bus.$on('cre ...
- vue2.0 组件通信
组件通信: 子组件要想拿到父组件数据 props 子组件不允许直接给父级的数据, 赋值操作如果想更改,父组件每次穿一个对象给子组件, 对象之间引用. 例子: <script> window ...
- Vue2.0组件注册
组件注册分为全局注册 和 局部注册 import 名称 from '包地址'//app.component用来对组件进行全局注册 app.component('my-swiper' ,'导包时使用的名 ...
- Vue2.0 组件文本超出3行显示... 点击查看更多可以查看全部内容(展开收起)
效果 <template><div ref="txttype" class="bottom"><div :class=" ...
- 项目vue2.0仿外卖APP(五)
header组件 vue-resourse应用 https://github.com/pagekit/vue-resource vue-resource是Vue.js的一款插件,它可以通过XMLHtt ...
- vue2.0+stylus实现星级评定组件,computed计算属性实现全星半星,动态改变星级,多种星星规格
vue2.0+stylus实现星级评定组件,computed计算属性实现全星半星,多种星星规格 使用方法如下:(size为星星的大小,score为评分,比如传4.5,则4.5颗星亮:传4.1则四颗星亮 ...
最新文章
- 170万奖金扶持 华为云究竟在下一盘怎样的棋?
- android之 实现对搜索框输入内容(自动出现匹配内容)
- nmap,tcpdump
- 常用Oracle系统表查询
- 技术实践 | Android 设备音视频兼容性适配
- redis中执行lua脚本命令
- 汇编语言0AH功能调用中显示字符出错
- asp.net html helper,6. ASP.NET MVC 5.0 中的HTML Helper【HTML 帮助类】
- 骑马与砍杀服务器修复,骑马与砍杀21.3.1公共版和热修说明 修复联机模式
- 洛谷P2585 [ZJOI2006]三色二叉树
- Linux curl 常用示例你都 Get 了吗?| CSDN 博文精选
- H3C VLAN显示及维护
- Roller的安装步骤
- 制作一键架设服务器,制作一键端方法
- Windows下CMD操作常用指令详解
- STEP2——《数据分析:企业的贤内助》重点摘要笔记(五)——数据加工
- 在世界读书日之后,重温与好书相遇的时光 | O'Reilly赠书活动
- android 圆圈扩大动画,Android实现3个圆圈的动画
- 【数据结构期末例题】
- 结合若依框架实现微信小程序授权登录
热门文章
- Android Studio导入他人项目注意的一些地方
- php 自旋锁,自旋锁、排队自旋锁、MCS锁、CLH锁(转)
- 软件设计实验(一)C#火车售票系统-基于UML的软件分析与设计模型建模实验(用例图、类图、时序图)
- JavaScript零基础入门 4:javascript对象有哪些
- generate报错 make_opencv3.4.8编译opencv-contrib并使用sift
- WEBUG逻辑漏洞测试
- docker安装nginx教程
- 无法删除文件的解决方法
- 3000万美元投资,看看以太坊未来12个月又有哪些大动作!
- python怎么写中文至excel_Python操作Excel_输出所有内容(包含中文)