1.上一章--页面图标ico的设置
2.苍渡大神的项目源码--项目地址
3.UI框架--Mint ui
4.数据接口地址--接口地址
5.下一章--组件的使用(svg及watch的简单使用)vue
1.先看看我们目前的city样式node
2.再来看看我们须要实现的样式git
3.样式
city.vue样式修改以下github
<template> <div> <mt-header :title="$store.state.nowcity.name" class='fs1-2' fixed> <mt-button slot="left"><mt-button icon="back"></mt-button></mt-button> <mt-button slot="right" class='fs0-8'>切换城市</mt-button> </mt-header> <div class="mgtop50 padlr10 bgfff padbot10"> <input class="cityinput" placeholder="输入商务楼,学校,地址"></input> <div class="submit bgcol ih40">提交</div> </div> <div class="main"> <div class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div class="mainbody bgfff "> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div class='search bgfff'> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> </div> </div> </div> </template> <script> export default { data () { return { } }, component:{ //注册组件 }, mounted:function(){ //生命周期 }, computed:{ //计算属性 }, methods:{ //函数 } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .cityinput{ width:100%; height:40px; margin:10px 0px; outline:0px; padding:0px 5px; box-sizing:border-box; } .submit{ text-align:center; color:white; border-radius:3px; } .fs0-8{ font-size:0.8rem !important; } .main{ border-top:2px solid #E4E4E4; } .maintop{ border-bottom:2px solid #E4E4E4; } .clearall{ text-align:center; } </style>
页面显示为vuex
咱们先把全部的样式都写出来,而后再来控制显示哪一个divsegmentfault
4.点击搜索
4.1当咱们在搜索框输入地址后,点击提交,应该弹出全部搜索的地址。因此咱们应该设置一个变量inputval
来存放输入框的值,一个变量list
来存放搜索到的数据。api
data () { return { inputval:"", list:"" } }
4.2点击事件。先看数据接口api
先写发送请求函数searchcity
(这里我把参数拼接到url上就没错,在url后加个{}来传参数就报 参数错误 ,哪位老铁知道玄机么?)数组
methods:{ //函数 searchcity:function(){ this.$http.get('http://cangdu.org:8001/v1/pois?city_id='+this.$store.state.nowcity.id+'&keyword='+this.inputval+'&type=search').then(response => { console.log(response); this.list=response.body; }, response => { console.log(response); }); } }
this.$store.state.nowcity.id
是从vuex里获取当前城市的id,在第八章存入;this.inputval
是我们输入框的值。
而后把点击函数searchcity
绑定到元素上缓存
<div @click="searchcity" class="submit bgcol ih40">提交</div>
运行试试,结果以下
解决,能够看到数据已经请求回来了。框架
4.3显示
如今咱们来控制class='his'
(搜索历史的div)和class='search'(搜索结果的div)的显示与隐藏。当咱们点击提交时,请求数据,将请求的数据加到list
上去。那咱们就判断,list
为空时,说明没点提交,就显示搜索历史的div,list
不为空时,显示搜索结果的div。
那咱们怎么控制div的显示隐藏呢?vue封装了一个方法v-if。在使用元素上加上v-if=""
便可,只要""
中间返回的值是true
,元素就会显示,反之则隐藏。main
div修改以下
<div class="main"> <div v-if="list==''" class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div class="mainbody bgfff "> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div v-if="list!=''" class='search bgfff'> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> </div> </div>
div显示隐藏写好了,下面用显示数据。数据循环显示依旧用v-for
,我们在第五章已经讲过了。main
div修改以下
<div class="main"> <div v-if="list==''" class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div class="mainbody bgfff "> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="pad10 after"> <div class="ih30">南开区公园</div> <div class="ih30 fs0-8 col9f">天津市南开区金马路112号</div> </div> <div class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div v-if="list!=''" class='search bgfff'> <div v-for="item in list" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> </div> </div>
看看结果
完美!数据显示成功。
5.存储搜索历史
首先咱们要设置一个变量his
来存放搜索历史,这样咱们显示的时候直接v-for
循环就能够了。
data () { return { inputval:"", list:"", his:"" } },
如今要点击搜索结果列表,会有两个反应。一个是页面跳转到商家列表页,我们先不作,另外一个是把点击的地点存到搜索历史里。那咱们把搜索历史存到哪里?想了想后以为存到localstorage
里(哪位老铁另有妙计?),既然要存,我们天然不能犯前面的错误(只存名字),因此咱们要把经度,纬度,经纬度合计,名字,地址都存进去。
先写点击事件goaddress
在methods里
goaddress:function(e){ var arr=[]; if(localStorage.getItem("his")){ arr=JSON.parse(localStorage.getItem("his")); arr.push(e); }else{ arr.push(e); } localStorage.setItem("his",JSON.stringify(arr)); this.his=JSON.parse(localStorage.getItem("his")); this.list=''; },
其中his
使咱们要存到localStorage
里的键值名称,先判断有没有,有说明有历史记录,咱们就把当前新加的地址放到his
里,没有咱们就新建一个his
,而后再存到localStorage
里。添加结束后咱们要把his
赋值给city.vue
的his里,这样咱们就能够循环his在页面里显示了(其实应该不用显示,直接页面就跳转了,但咱们为了效果先不作跳转,先作历史记录的存储与读取,this.list=''
是为了让搜索结果的div隐藏)。
函数写完后咱们绑定到要点击的元素上
<div v-if="list!=''" class='search bgfff'> <div v-for="item in list" @click="goaddress({name:item.name,latitude:item.latitude,longitude:item.longitude,address:item.address,geohash:item.geohash})" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> </div>
我们直接把要存储的对象当作参数传给点击事件goaddress,参数为{name:名字,latitude:经度,longitude:维度,address:地址,,geohash:经纬度合计}
如今咱们先点击试试
成功!咱们能够在右侧的控制台(F12)的Application下的localStorage里看到咱们已经存进去了一条数据
6.显示搜索历史
如今咱们的变量his
已经有数据了,咱们只须要把它显示出来就能够
<div class="main"> <div v-if="list==''" class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div v-if="his!=''" class="mainbody bgfff "> <div v-for="item in his" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> <div class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div v-if="list!=''" class='search bgfff'> <div v-for="item in list" @click="goaddress({name:item.name,latitude:item.latitude,longitude:item.longitude,address:item.address,geohash:item.geohash})" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> </div> </div>
这时候发现 清空全部
按钮 并无功能,因此咱们再写一个清空搜索历史的函数removeall
(并不会把搜索历史his
与localStorage
绑定起来,每次都要手动管理his
,哪位老铁可有妙计?)
removeall:function(){ localStorage.clear(); this.his=""; }
而后绑定到清空全部
的div上
<div @click='removeall' class="clearall ih30 pad10 col9f"> 清空全部 </div>
ok,运行试试
看着没问题了,可是可能有老铁已经注意到了--历史记录应该页面一进来就显示出来,因此咱们应该在vue的生命周期mounted
函数里写操做
mounted:function(){ //生命周期 if(localStorage.getItem("his")){ this.his=localStorage.getItem("his"); } },
判断本地缓存是否有his
,有就加到city.vue里的his
里。city.vue完整代码以下
<template> <div> <mt-header :title="$store.state.nowcity.name" class='fs1-2' fixed> <mt-button slot="left"><mt-button icon="back"></mt-button></mt-button> <mt-button slot="right" class='fs0-8'>切换城市</mt-button> </mt-header> <div class="mgtop50 padlr10 bgfff padbot10"> <input v-model="inputval" class="cityinput" placeholder="输入商务楼,学校,地址"></input> <div @click="searchcity" class="submit bgcol ih40">提交</div> </div> <div class="main"> <div v-if="list==''" class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div v-if="his!=''" class="mainbody bgfff "> <div v-for="item in his" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> <div @click='removeall' class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div v-if="list!=''" class='search bgfff'> <div v-for="item in list" @click="goaddress({name:item.name,latitude:item.latitude,longitude:item.longitude,address:item.address,geohash:item.geohash})" class="pad10 after"> <div class="ih30">{{item.name}}</div> <div class="ih30 fs0-8 col9f">{{item.address}}</div> </div> </div> </div> </div> </template> <script> export default { data () { return { inputval:"", list:"", his:"" } }, component:{ //注册组件 }, mounted:function(){ //生命周期 if(localStorage.getItem("his")){ this.his=JSON.parse(localStorage.getItem("his")); } }, computed:{ //计算属性 }, methods:{ //函数 searchcity:function(){ this.$http.get('http://cangdu.org:8001/v1/pois?city_id='+this.$store.state.nowcity.id+'&keyword='+this.inputval+'&type=search').then(response => { console.log(response); this.list=response.body; }, response => { console.log(response); }); }, goaddress:function(e){ var arr=[]; if(localStorage.getItem("his")){ arr=JSON.parse(localStorage.getItem("his")); arr.push(e); }else{ arr.push(e); } localStorage.setItem("his",JSON.stringify(arr)); this.his=JSON.parse(localStorage.getItem("his")); this.list=''; }, removeall:function(){ localStorage.clear(); this.his=""; } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .cityinput{ width:100%; height:40px; margin:10px 0px; outline:0px; padding:0px 5px; box-sizing:border-box; } .submit{ text-align:center; color:white; border-radius:3px; } .fs0-8{ font-size:0.8rem !important; } .main{ border-top:2px solid #E4E4E4; } .maintop{ border-bottom:2px solid #E4E4E4; } .clearall{ text-align:center; } </style>
运行试试--
ok!到这里city.vue
的搜索历史的存储与
读取基本写完了
页面目前还有几个小bug
1.输入框数据为空时不能点击提交,把输入框放到form表单里,增长一个required
属性
<div class="mgtop50 padlr10 bgfff padbot10"> <form v-on:submit.prevent> <input v-model="inputval" class="cityinput" required placeholder="输入商务楼,学校,地址"></input> <input type='submit' name='submit' value='提交' @click="searchcity" class="submit bgcol ih40"></input> </form> </div>
再在函数searchcity
里判断搜索地址数据是否为空,不为空再发送请求。
searchcity:function(){ if(this.inputval){ this.$http.get('http://cangdu.org:8001/v1/pois?city_id='+this.$store.state.nowcity.id+'&keyword='+this.inputval+'&type=search').then(response => { console.log(response); this.list=response.body; }, response => { console.log(response); }); } },
2.页面内容明明就没有填满,却出现滚动条,这是由于我们的第一个div
即form的父元素(固定定位的头部不算)有一个magtop50致使的(碰见过不少次,缘由是啥不知道),我们去掉这个class再在form的父元素外层加一个div加上padtop50
<div class='padtop50'> <div class="padlr10 bgfff padbot10"> <form v-on:submit.prevent> <input v-model="inputval" class="cityinput" required placeholder="输入商务楼,学校,地址"></input> <input type='submit' name='submit' value='提交' @click="searchcity" class="submit bgcol ih40"></input> </form> </div> </div>
3.搜索的结果返回数据为空怎么办?地址输入 隐隐 点击提交
能够看到,返回数据的body为空。那我们就给他弹出个消息框提示数据为空。
消息提示框能够用 Mint UI 的 Toast组件,例子写的很清楚,我们用最简单的就行
在city.vue的<script>
里第一行写入
import { Toast } from 'mint-ui';
先引入,引入后就可使用。在提交的点击事件searchcity
里判断返回数据是否为空
searchcity:function(){ if(this.inputval){ this.$http.get('http://cangdu.org:8001/v1/pois?city_id='+this.$store.state.nowcity.id+'&keyword='+this.inputval+'&type=search').then(response => { console.log(response); this.list=response.body; if(response.body==""){ Toast('抱歉,空空如也'); } }, response => { console.log(response); }); } },
运行试试
解决!弹出返回数据为空时消息提示框!
4.判断是否重复
当点击搜索结果与搜索历史有相同时,就不添加到历史记录。
goaddress:function(e){ var arr=[]; if(localStorage.getItem("his")){ arr=JSON.parse(localStorage.getItem("his")); for(var i=0;i<arr.length;i++){ if(arr[i].geohash==e.geohash){ var isok=true; } } if(!isok){ arr.unshift(e); } }else{ arr.unshift(e); } localStorage.setItem("his",JSON.stringify(arr)); this.his=JSON.parse(localStorage.getItem("his")); this.list=''; },
这里要注意
geohash
来判断是否相等unshift
添加而不是push
isok
这个中间变量来改变是否添加新地址,而不是把 arr.unshift(e)
直接写在if判断里。。。嘿嘿,若是你用unshift
在if判断直接添加新元素,会出现死循环,由于当你把元素加到数组第一位后,数组全部的元素都会日后退一位,这样你下次循环进来,取到的元素还是上一次循环的元素...(我也没想明白,而个人学长强哥Topqiang一眼就看出来了,各位老铁若是有其余的好方法能够分享一下)city.vue修改后的完整代码以下
<template> <div> <mt-header :title="$store.state.nowcity.name" class='fs1-2' fixed> <mt-button slot="left"><mt-button icon="back"></mt-button></mt-button> <mt-button slot="right" class='fs0-8'>切换城市</mt-button> </mt-header> <div class='padtop50'> <div class="padlr10 bgfff padbot10"> <form v-on:submit.prevent> <input v-model="inputval" class="cityinput" required placeholder="输入商务楼,学校,地址"></input> <input type='submit' name='submit' value='提交' @click="searchcity" class="submit bgcol ih40"></input> </form> </div> </div> <div class="main"> <div v-if="list==''" class="his after"> <div class='maintop fs0-8 padlr10'>搜索历史</div> <div v-if="his!=''" class="mainbody bgfff "> <div v-for="item in his" class="pad10 after"> <div class="ih30 nowarp">{{item.name}}</div> <div class="nowarp ih30 fs0-8 col9f">{{item.address}}</div> </div> <div @click='removeall' class="clearall ih30 pad10 col9f"> 清空全部 </div> </div> </div> <div v-if="list!=''" class='search bgfff'> <div v-for="item in list" @click="goaddress({name:item.name,latitude:item.latitude,longitude:item.longitude,address:item.address,geohash:item.geohash})" class="pad10 after"> <div class="ih30 nowarp">{{item.name}}</div> <div class="nowarp ih30 fs0-8 col9f">{{item.address}}</div> </div> </div> </div> </div> </template> <script> import { Toast } from 'mint-ui'; export default { data () { return { inputval:"", list:"", his:"" } }, component:{ //注册组件 }, mounted:function(){ //生命周期 if(localStorage.getItem("his")){ this.his=JSON.parse(localStorage.getItem("his")); } }, computed:{ //计算属性 }, methods:{ //函数 searchcity:function(){ if(this.inputval){ this.$http.get('http://cangdu.org:8001/v1/pois?city_id='+this.$store.state.nowcity.id+'&keyword='+this.inputval+'&type=search').then(response => { console.log(response); this.list=response.body; if(response.body==""){ Toast('抱歉,空空如也'); } }, response => { console.log(response); }); } }, goaddress:function(e){ var arr=[]; if(localStorage.getItem("his")){ arr=JSON.parse(localStorage.getItem("his")); for(var i=0;i<arr.length;i++){ if(arr[i].geohash==e.geohash){ var isok=true; } } if(!isok){ arr.unshift(e); } }else{ arr.unshift(e); } localStorage.setItem("his",JSON.stringify(arr)); this.his=JSON.parse(localStorage.getItem("his")); this.list=''; }, removeall:function(){ localStorage.clear(); this.his=""; } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .cityinput{ width:100%; height:40px; margin:10px 0px; outline:0px; padding:0px 5px; box-sizing:border-box; } .submit{ text-align:center; color:white; border-radius:3px; width:100%; border:0px; outline:0px; } .fs0-8{ font-size:0.8rem !important; } .main{ border-top:2px solid #E4E4E4; } .maintop{ border-bottom:2px solid #E4E4E4; } .clearall{ text-align:center; } </style>
运行试试
解决!
下面,我们写点击搜索结果的另外一个反应--页面跳转