闲云旅游项目开发-(第四篇:机票首页/机票搜索功能(`el-autocomplete`远程搜索组件)/moment.js的使用/日期选择组件el-date-picker)
目錄
相關組件介紹
一 機票首頁布局
二?封裝搜索組件
1. 組件布局
2.目標思路
3.步驟
3.1 基本功能
3.2 自動補全
3.3獲取真正的推薦數據
3.4 添加城市代號
3.5 處理日期格式
3.6? 使用了momentjs,這是一個第三方的包,需要先下載并且導入。
其他功能
優化
三 搜索功能
1.思路
2.實現步驟
獲取城市數據
調用城市查詢接口
下拉數據選中賦值
搜索跳轉
城市切換
往返
3.總結
四 特價機票
1. 思路
2.實現步驟
2.1 特價機票布局
2.2 請求數據接口
五 效果圖
?
相關組件介紹
1.el-autocomplete遠程搜索自動補全組件
組件文檔:https://element.eleme.cn/#/zh-CN/component/input#yuan-cheng-sou-suo
2.el-date-picker日期選擇組件
組件文檔:https://element.eleme.cn/#/zh-CN/component/date-picker#xuan-ze-ri
一 機票首頁布局
pages/air/index.vue的代碼如下 :
<template><section class="container"><h2 class="air-title"><span class="iconfont iconfeiji"></span><i>國內機票</i></h2><!-- 搜索廣告欄 --><el-row type="flex" justify="space-between"><!-- 搜索表單 --><div>搜索</div><!-- banner廣告 --><div class="sale-banner"><img src="http://157.122.54.189:9093/images/pic_sale.jpeg"></div></el-row><!-- 廣告 --><el-row type="flex" class="statement"><el-col :span="8"><i class="iconfont iconweibiaoti-_huabanfuben" style="color:#409EFF;"></i><span>100%航協認證</span></el-col><el-col :span="8"><i class="iconfont iconbaozheng" style="color:green;"></i><span>出行保證</span></el-col><el-col :span="8"><i class="iconfont icondianhua" style="color:#409EFF;"></i><span>7x24小時服務</span></el-col></el-row><h2 class="air-sale-title"><span class="iconfont icontejiajipiao"></span><i>特價機票</i></h2><!-- 特價機票 --><div class="air-sale"></div></section> </template><script> export default {} </script><style scoped lang="less"> .air-sale{border: 1px #ddd solid;padding:20px;margin-bottom:50px;.air-sale-pic{> div{width:225px;height:140px;position: relative;overflow: hidden;img{width:100%;}.layer-bar{position:absolute;bottom:0;left:0;background: rgba(0,0,0,0.5);color:#fff;height:30px;line-height: 30px;width:100%;box-sizing: border-box;padding: 0 15px;font-size: 14px;span:last-child{font-size:18px;}}}} }.air-sale-group{margin-top:20px;padding-top:8px;border-right:1px #eee solid;&:last-child{border-right:none;}.air-sale-row{font-size:12px;color:#666;margin-bottom:8px;.air-sale-price{color:orange;font-size: 20px;}} }.container{width:1000px;margin:0 auto; }.air-title{margin:15px 0;font-size:20px;font-weight: normal;color:orange;span{font-size:20px;} }.statement{margin:15px 0;border:1px #ddd solid;background:#f5f5f5;height: 58px;padding:10px 0;box-sizing:border-box;> div{text-align: center;line-height: 38px;border-right:1px #ddd solid;&:last-child{border-right: none;}*{vertical-align: middle;}i{font-size:30px;}} }.air-sale-title{margin:15px 0;font-size:20px;font-weight: normal;color:#409EFF;span{font-size:20px;} } </style>?
?
?
?
?
二?封裝搜索組件
1. 組件布局
新建機票搜索表單組件components/air/searchForm.vue,并替換以下布局代碼 :
<template><div class="search-form"><!-- 頭部tab切換 --><el-row type="flex" class="search-tab"><span v-for="(item, index) in tabs" :key="index"@click="handleSearchTab(item, index)":class="{active: index === currentTab}"><i :class="item.icon"></i>{{item.name}}</span></el-row><el-form class="search-form-content" ref="form" label-width="80px"><el-form-item label="出發城市"><!-- fetch-suggestions 返回輸入建議的方法 --><!-- select 點擊選中建議項時觸發 --><el-autocomplete:fetch-suggestions="queryDepartSearch"placeholder="請搜索出發城市"@select="handleDepartSelect"class="el-autocomplete"></el-autocomplete></el-form-item><el-form-item label="到達城市"><el-autocomplete:fetch-suggestions="queryDestSearch"placeholder="請搜索到達城市"@select="handleDestSelect"class="el-autocomplete"></el-autocomplete></el-form-item><el-form-item label="出發時間"><!-- change 用戶確認選擇日期時觸發 --><el-date-picker type="date" placeholder="請選擇日期" style="width: 100%;"@change="handleDate"></el-date-picker></el-form-item><el-form-item label=""><el-button style="width:100%;" type="primary" icon="el-icon-search"@click="handleSubmit">搜索</el-button></el-form-item><div class="reverse"><span @click="handleReverse">換</span></div></el-form> </div> </template><script> export default {data(){return {tabs: [{icon: "iconfont icondancheng", name: "單程"},{icon: "iconfont iconshuangxiang", name: "往返"}],currentTab: 0,}},methods: {// tab切換時觸發handleSearchTab(item, index){},// 出發城市輸入框獲得焦點時觸發// value 是選中的值,cb是回調函數,接收要展示的列表queryDepartSearch(value, cb){cb([{value: 1},{value: 2},{value: 3},]);},// 目標城市輸入框獲得焦點時觸發// value 是選中的值,cb是回調函數,接收要展示的列表queryDestSearch(value, cb){cb([{value: 1},{value: 2},{value: 3},]);},// 出發城市下拉選擇時觸發handleDepartSelect(item) {},// 目標城市下拉選擇時觸發handleDestSelect(item) {},// 確認選擇日期時觸發handleDate(value){},// 觸發和目標城市切換時觸發handleReverse(){},// 提交表單是觸發handleSubmit(){}},mounted() {} } </script><style scoped lang="less"> .search-form{border:1px #ddd solid;border-top:none;width:360px;height:350px;box-sizing: border-box; }.search-tab{span{display: block;flex:1;text-align: center;height:48px;line-height: 42px;box-sizing: border-box;border-top:3px #eee solid;background:#eee;}.active{border-top-color: orange;background:#fff;}i{margin-right:5px;font-size: 18px;&:first-child{font-size:16px;}} }.search-form-content{padding:15px 50px 15px 15px;position: relative;.el-autocomplete{width: 100%;} }.reverse{position:absolute;top: 35px;right:15px;&:after,&:before{display: block;content: "";position: absolute;left:-35px;width:25px;height:1px;background:#ccc;}&:after{top:0;}&:before{top:60px;}span{display: block;position:absolute;top: 20px;right:0;font-size:12px;background: #999;color:#fff;width:20px;height:20px;line-height: 18px;text-align: center;border-radius: 2px;cursor: pointer;&:after,&:before{display: block;content: "";position: absolute;left:10px;width:1px;height:20px;background:#ccc;}&:after{top:-20px;}&:before{top:20px;}} } </style>創建完成后在pages/air/index.vue中導入組件
<template> <!-- 其他代碼... --><!-- 搜索廣告欄 --><el-row type="flex" justify="space-between"><!-- 搜索表單 --><SearchForm/><!-- banner廣告 --></el-row><!-- 其他代碼... --> </template> <script> import SearchForm from "@/components/air/searchForm";export default {components: {SearchForm}, } </script>2.目標思路
通過用戶輸入數據, 組合成需要的參數 點擊搜索, 跳轉頁面后, 傳遞到機票搜索結果頁面,再發送請求
需要的參數包括
-
出發地 / 出發地代碼 departCity /departCode
-
到達地 / 到達地代碼 destCity / destCode
-
出發時間 departDate
3.步驟
3.1 基本功能
-
三個輸入框綁定數據
-
點擊按鈕, 打印出出全部數據作為參考
3.2 自動補全
先用死數據模擬搜索建議,顯示自動補全的兩個步驟
- 聲明fetch-suggestion 定義獲取建議的函數
- 在函數當中,可以接受兩個參數
-
出發地輸入框彈出搜索建議
-
到達地輸入框彈出搜索建議
?
3.3獲取真正的推薦數據
-
使用 ajax 獲取數據
這個接口如果沒有參數會獲取到100條數據
-
修改數據格式,,再進行回調渲染
自動補全搜索建議的數組里面的對象,必須有value才可以顯示出來
配合組件的要求 (每個都需要有 value)
3.4 添加城市代號
選擇一個選項的時候, 城市名作為 value 無需處理
但是城市代碼code必須主動放入數據當中
-
獲取搜索建議列表時, 除了 value 值用來渲染列表需要以外, 還需要將當前城市的 code 放進去備用
-
form 數據有兩個屬性儲存城市代號 departCode / destCode
-
每當選中一個選項時, 同時將城市代號更新到 form 中
-
監聽 select 事件,函數可以接受一個固定的參數, 就是我們選中的那個城市的數據對象
-
講這個數據對象里面的 sort 放入 code 城市代碼當中即可
-
3.5 處理日期格式
-
使用日期選擇組件(基本用法,用 v-model 綁定數據)
-
選了日期之后, 輸出的是一個日期對象
-
需要轉換為合適的格式
-
可以嘗試自己將日期對象改成 YYYY-MM-DD 的格式
-
餓了么也有一個功能 使用value-format指定綁定值的格式, 可以使用
-
-
時間格式轉換的時機每次用戶修改日期的時候自動觸發 (監聽 change 事件), 并且修改用戶時間格式
3.6? 使用了momentjs,這是一個第三方的包,需要先下載并且導入。
下載命令:
npm install --save moment在組件中引入
import moment from "moment";傳入日期對象即可改變格式
moment(value).format("YYYY-MM-DD");其他功能
優化
-
封裝獲取建議函數,, 將獲取出發地搜索建議和獲取到達地搜索建議的函數合并
-
輸入后再激活輸入建議 :trigger-on-focus="false"
-
自動高亮第一個選項 : highlight-first-item ="true" (如果不生效請注意elementui 版本)
-
數據來自第三方, 某些城市缺失代碼, 刪除獲取不到 sort 的數據
其實可以過濾, 獲取簡易列表時, 將所有不帶有 sort 數據的城市去掉
-
城市名稱不應帶有市字, 在獲取列表的時候直接替換掉市字即可
利用 replace 方法, 將數據 name 中最后一個 市字 替換成 空字符串
-
處理用戶沒有選擇城市,造成缺失代碼的問題
-
搜索得出建議選項的時候,默認將列表的第一項 code 數據放入 form
默認給一個值, 如果用戶自己選了, 再去覆蓋
-
-
思考:如果用戶非要寫一個市字, 可以在以下幾個時間點進行處理, 只要最終發請求前處理完畢沒有市字即可
-
失去焦點
-
跳轉頁面的時候
-
頁面跳轉后提交搜索 ajax 的時候
(建議在搜索時才處理,將這個處理隱藏起來不讓用戶感知)
-
?
三 搜索功能
1.思路
從結果出發,首先來看下我看點擊表單后會發生什么事?
點擊表單的搜索按鈕后會跳轉到該頁面,并且提供了5個用于查詢的參數,暫且不考慮目前有沒該頁面,我們可以先考慮如何給頁面提供這些參數。
參數列表(重要):
-
departCity 出發城市(注意沒有市字)
-
departCode 出發城市代碼
-
destCity 到達城市(注意沒有市字)
-
destCode 到達城市代碼
-
departDate 出發日期
可以從查找機票城市的接口找到城市相關數據,在用戶輸入城市的同時獲得上面的數據。
接口:http://157.122.54.189:9095/airs/city
返回結果:
{ ?data: [{ ? ?code: "440100000000", ? ?created_at: "2019-04-02 08:18:16", ? ?id: 197, ? ?level: "2", ? ?name: "廣州市", ? ?parentCode: "440000000000", ? ?sort: "CAN", ? ?updated_at: 1558617184703 }]; ?total: 1 }?
2.實現步驟
-
獲取城市數據
在data中新增變量存儲表單數據?,在data中定義需要提交的是5個參數
<script> export default {data(){return {// 其他代碼...form: {departCity: "", // 出發城市departCode: "", // 出發城市代碼destCity: "", // 到達城市destCode: "", // 到達城市代碼departDate: "", // 日期字符串},}}, } </script>注意在template的表單中使用v-model雙向綁定數據到form的屬性。
比如出發城市v-model="form.departCity":
<el-autocomplete:fetch-suggestions="queryDepartSearch"placeholder="請搜索出發城市"@select="handleDepartSelect"class="el-autocomplete"v-model="form.departCity"></el-autocomplete>日期departDate只需要在el-date-picker組件中使用v-model="form.departDate"進行綁定即可獲得了。
-
調用城市查詢接口
使用實時查詢的方式調用查詢城市的接口,由于出發城市和到達城市都需要調用這個查詢接口,所以把查詢操作封裝到一個獨立函數來調用。
<script> export default {// 其他代碼...methods: {// 出發城市輸入框獲得焦點時觸發// value 是選中的值,cb是回調函數,接收要展示的列表async queryDepartSearch(value, cb){const arr = await this.querySearchAsync(value)if(arr.length > 0){// 不在下拉列表中選擇,則默認選擇第一項this.form.departCity = arr[0].value;this.form.departCode = arr[0].sort;}cb(arr)},// 目標城市輸入框獲得焦點時觸發// value 是選中的值,cb是回調函數,接收要展示的列表async queryDestSearch(value, cb){const arr = await this.querySearchAsync(value)if(arr.length > 0){// 不在下拉列表中選擇,則默認選擇第一項this.form.destCity = arr[0].value;this.form.destCode = arr[0].sort;}cb(arr)},// 查詢城市接口的方法,返回promise// queryString是查詢關鍵字querySearchAsync(queryString) {return new Promise((resolve, reject) => {// 如果關鍵字是空,則直接返回if(!queryString){return resolve([]);}this.$axios({url: `/airs/city`,params: {name: queryString}}).then(res => {const {data} = res.data;// 下拉提示列表必須要有value字段const arr = data.map(v => {return {...v,value: v.name.replace("市", "")}});resolve(arr);});});},// 其他代碼...}} </script>?
-
下拉數據選中賦值
針對城市下拉框選項選中的事件處理,我們應該把選中的選項當做是當前的數據
<script>export default {// 其他代碼...methods: {// 其他代碼...// 出發城市下拉選擇時觸發// item代表當前選中項handleDepartSelect(item) {this.form.departCity = item.value;this.form.departCode = item.sort;},// 目標城市下拉選擇時觸發// item代表當前選中項handleDestSelect(item) {this.form.destCity = item.value;this.form.destCode = item.sort;},// 確認選擇日期時觸發handleDate(value){this.form.departDate = moment(value).format("YYYY-MM-DD");},// 其他代碼...}} </script>?
-
搜索跳轉
下面來實現頁面跳轉,需要在URL中把5個參數都到帶過去給搜索結果頁/air/flights
<script>export default {// 其他代碼...methods: {// 其他代碼...// 提交表單是觸發handleSubmit(){// 表單驗證數據const rules = {depart: {value: this.form.departCity, message: "請選擇出發城市"},dest: {value: this.form.destCity, message: "請選擇到達城市"},departDate: {value: this.form.departDate, message: "請選擇出發時間"},}let valid = true; // 表單驗證結果Object.keys(rules).forEach(v => {// 只要有一個結果不通過,就停止循環if(!valid) return;const item = rules[v];// 數據字段為空if(!item.value){valid = false;this.$confirm(item.message, '提示', {confirmButtonText: '確定',showCancelButton: false,type: 'warning'})}});// 不通過驗證,不需要往下執行if(!valid) return;this.$router.push({path: "/air/flights",query: this.form})}}} </script>/air/flights頁面暫時還沒創建,不過只要能從URL中看到參數正確傳遞即可。
?
-
城市切換
這是個把出發城市和到達城市對換位置的功能,實現起來非常簡單,把form的數據對調換就可以了
調換的事件函數
<script>export default {// 其他代碼...methods: {// 其他代碼...// 觸發和目標城市切換時觸發handleReverse(){const { departCity, departCode, destCity, destCode} = this.form;this.form.departCity = destCity;this.form.departCode = destCode;this.form.destCity = departCity;this.form.destCode = departCode;},}} </script>?
?
-
往返
目前接口不支持往返,需要添加一個提示
// tab切換時觸發 handleSearchTab(item, index){if(index === 1){this.$confirm("目前暫不支持往返,請使用單程選票!", '提示', {confirmButtonText: '確定',showCancelButton: false,type: 'warning'})} },?
3.總結
關鍵點在于如何獲取跳轉鏈接需要的5個參數!
el-autocomplete組件的使用(查看文檔)
使用momentjs進行時間轉換
表單自定義驗證
?
四 特價機票
1. 思路
思路: 其實就是獲取數據布局, 點擊的結果就是模擬一個搜索
特價機票布局 :注意鏈接跳轉時的數據拼接
請求數據接口 :在機票首頁 created/mounted 生命周期里面獲取數據 賦值到 data sales 然后遍歷渲染頁面即可
2.實現步驟
2.1 特價機票布局
新增特價機票布局和模擬數據。
pages/air/index.vue
<template><section class="container"><!-- 其他代碼... --><!-- 特價機票 --><div class="air-sale"><el-row type="flex" class="air-sale-pic" justify="space-between"><el-col :span="6" v-for="(item, index) in sales" :key="index"><nuxt-link :to="`/air/flights?departCity=${item.departCity}&departCode=${item.departCode}&destCity=${item.destCity}&destCode=${item.destCode}&departDate=${item.departDate}`"><img :src="item.cover"/><el-row class="layer-bar" type="flex" justify="space-between"><span>{{item.departCity}}-{{item.destCity}}</span><span>¥699</span></el-row></nuxt-link></el-col></el-row></div></section> </template><script> // 其他代碼... export default {data(){return {sales: [{cover: "https://gss0.bdstatic.com/94o3dSag_xI4khGkpoWK1HF6hhy/baike/s%3D220/sign=9154c841bcfd5266a32b3b169b199799/3812b31bb051f8199687c7e0d0b44aed2f73e7fe.jpg",departCity: "廣州",departCode: "CAN",departDate: "2019-06-17",destCity: "上海",destCode: "SHA",price: 760}]}},// 其他代碼... } </script>注意跳轉鏈接的nuxt-link :to="/air/flights?xxxx的參數拼接
?
2.2 請求數據接口
<script> import SearchForm from "@/components/air/searchForm";export default {data(){return {sales: [] // 去除模擬數據}},mounted(){this.$axios({url: `/airs/sale`}).then(res => {this.sales = res.data.data;});},// 其他代碼... } </script>五 效果圖
?
?
總結
以上是生活随笔為你收集整理的闲云旅游项目开发-(第四篇:机票首页/机票搜索功能(`el-autocomplete`远程搜索组件)/moment.js的使用/日期选择组件el-date-picker)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这几种游戏配音教程分享给你
- 下一篇: 你上一次忍住没揍产品经理是什么时候?