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>
運行試試
解決!
下面,我們寫點擊搜索結果的另外一個反應--頁面跳轉