Vue2.0组件实现动态搜索引擎(二)
来源:互联网 发布:react.js项目 编辑:程序博客网 时间:2024/06/05 07:05
接上一篇,完成logo部分我们就要开始整个项目的核心——panel组件。
注意使用相对路径不要照搬。
顺便加上一个“X”span,方便清空输入栏:
这里比较偷懒用了个X字符代替清除按钮,对样式有追求的童鞋可以找个美观的图片,其他不变。
如此一旦logo改变panel就能够得到logo的index,可以改变回车搜索的链接url:
整个panel组件分为3个部分:关键字输入框,相关搜索建议下拉列表和搜索跳转按钮。
由于我们整个项目是设计成父子组件的架构所以在父组件即panel部分开头需要引入子组件:
HTML:
<logo-select @logoNow="changeSource"></logo-select>
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中设置一个变量记录当前选中的index 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]; }
上面代码的核心原理跟之前的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部分大家可以结合自己喜好自行配置。
阅读全文
0 0
- Vue2.0组件实现动态搜索引擎(二)
- Vue2.0组件实现动态搜索引擎(一)
- vue2.0动态组件及render
- 3.vue2.0 轮番图组件实现
- vue2.0+stylus实现星级评定组件,computed计算属性实现全星半星,动态改变星级,多种星星规格
- vue2.0 组件
- vue2.0翻页组件
- VUE2.0组件库
- Vue2.0组件问题
- vue2.0 组件通信
- Vue2.0 组件通信
- vue2.0实现父子通信(基于之前我写的复选框组件)
- Vue2.0+ElementUi封装table组件实现分页功能
- vue2.0使用swiper组件实现轮播
- vue2.0+stylus实现商品增加减少控制按钮组件
- vue2.0s中eventBus实现兄弟组件通信
- vue2.0s中eventBus实现兄弟组件通信
- 7、vue2.0用Vue.extend构建消息提示组件的方法实例实现alert模态框组件(2)
- Spring之@Value 注解获取properties值(Spring 3的@value简化配置文件的读取)
- windows8安装msi软件提示2503错误的解决办法
- 实现1+2+3...+n,要求不能使用乘除法、循环、条件判断
- Spring MVC 实现文件的上传和下载
- LinearSnapHelper , 滑动停靠效果, 当滑动停止的时候,自动调整item,左对齐,或者靠中对齐
- Vue2.0组件实现动态搜索引擎(二)
- 在507干活的第4天(下)
- 网络基础-MAC和IP的区别
- Git 使用记录
- 论文笔记-Temporal segment network:towards good practices for deep action recognition
- Android 动态权限申请原则 Best Practices for App Permissions
- Nginx+Tomcat+Redis实现负载均衡、资源分离、session共享
- BZOJ 2005 NOI2010 能量采集 莫比乌斯反演
- OBIEE12C_Linux_安装日志