一、搜索框的自动补全
显示自动补全的两个步骤
- 声明
fetch-suggestion定义获取建议的函数- 在函数当中,可以接受两个参数,
- 第一个是饿了么传进来当前的输入值
- 第二个是饿了么提供的封装好的显示列表函数 这个函数可以在形参随意命名 只要执行这个函数,并且带上结果数组 就会显示一个建议列表
- 出发地输入框弹出搜索建议
- 到达地输入框弹出搜索建议
获取真正的推荐数据:
- 使用
ajax获取数据 这个接口如果没有参数会获取到100条数据- 修改数据格式,,再进行回调渲染 自动补全搜索建议的数组里面的对象,必须有
value才可以显示出来 配合组件的要求 (每个都需要有value)
1.1封装机票列表接口
components/air/air文件
import axios from '@/utils/http'
export const airsCity = function (name) {
return axios({
url: '/airs/city',
params: {
name
}
})
}
1.2引入,改造并渲染数据
// 出发城市的返回输入建议的方法属性
async queryDepartSearch(string, callback) {
//这个是显示建议的函数
// 第一个参数是当前输入框的值
//第二个是用来显示建议列表的回调函数
//在调用这个函数的时候往里面输入一个建议数组即可
//数组中每个元素都是一个建议对象
let res = await airsCity(string);
if (res) {
console.log(res);
const list = res.data.data.map((city) => {
return {
...city,
value: city.name,
};
});
callback(list);
}
// this.$axios({
// url: "/airs/city",
// params: {
// name: string,
// },
// }).then((res) => {
// const list = res.data.data.map((city) => {
// return {
// ...city, //展开数据
// value: city.name, //框架需要value值
// };
// });
// callback(list);
// });
},
// 到达城市的建议函数
async queryDestSearch(string, callback) {
let res = await airsCity(string);
if (res) {
console.log(res);
const list = res.data.data.map((city) => {
return {
...city,
value: city.name,
};
});
callback(list);
}
},
二、用户选中城市时附带城市代码
- 每当选中一个选项时, 同时将城市代号更新到
form中- 监听
select事件,函数可以接受一个固定的参数, 就是选中的那个城市的数据对象- 将这个数据对象里面的
sort放入code城市代码当中即可
handleDepartSelect(item) {
//这里是用户选择了其中一个建议选项之后出发的事件
//可以接收到用户选择选项的对象本身
//不单单是渲染项,而是整个对象,可以进行后续操作
// console.log(item);
if (item.sort) {
this.form.departCode = item.sort;
}
},
//到达城市的建议回调
handleDestSelect(item) {
// console.log(item);
if (item.sort) {
this.form.destCode = item.sort;
}
},
三、时间处理
element组件有个方法:使用format指定输入框的格式;使用value-format指定绑定值的格式。- 时间格式转换的时机每次用户修改日期的时候自动触发 (监听
change事件), 并且修改用户时间格式
<!-- change 用户确认选择日期时触发 -->
<el-date-picker
v-model="form.departDate"
format="yyyy 年 MM 月 dd 日"
value-format="yyyy-MM-dd"
type="date"
placeholder="请选择日期"
style="width: 100%"
@change="handleDate"
>
</el-date-picker>
3.1引入momentjs第三方包的处理方式
3.1.1下载安装
npm install --save moment
3.1.2组件中引入
import moment from "moment";
3.1.3触发change事件时代入
// 日期选择
handleDate(value) {
this.form.departDate = moment(value).format("YYYY-MM-DD");
},
3.2当前日期之前禁用
:picker-options="{ }":当前时间日期选择器特有的选项disabledDate:禁止选择当前之前的日期
<el-date-picker
v-model="form.departDate"
type="date"
placeholder="请选择日期"
style="width: 100%"
@change="handleDate"
:picker-options="{ disabledDate }"
>
</el-date-picker>
disabledDate(time) {
return time.getTime() < Date.now();
//为true禁用
// return true;
console.log(time);
},
四、优化
看码云
五、城市互换
- 定义两个常量存放一部分旧数据,等旧数据腾出来后,重新赋值
////城市互换
handleReverse() {
// 先缓存原来的出发信息
const oldDepartCity = this.form.departCity;
const oldDepartCode = this.form.departCode;
//将到达城市信息放入触发城市
this.form.departCity = this.form.destCity;
this.form.departCode = this.form.destCode;
//将缓存旧出发城市信息放入到达城市
this.form.destCity = oldDepartCity;
this.form.destCode = oldDepartCode;
},
六、往返接口暂时不可用,给出提示
// 切换tab
handleSearchTab(index) {
this.currentTab = index;
if (index == 1) {
this.$message.error("目前不支持双程");
}
},
七、点击搜索跳转页面传递带参
- 要在
URL中把5个参数都到带过去给搜索列表页/air/flights
// 搜索
handleSubmit() {
console.log(this.form);
this.$router.push({
path: "/air/flights",
query: this.form,
});
},
八、创建结果页组件并获取数据
- 列表页
/air/flights,获取数据并创建变量flightsData接收
export default {
data() {
return {
flightsData: {},
};
},
created() {
this.$axios({
url: "/airs",
params: this.$route.query,
}).then((res) => {
this.flightsData = res.data;
// console.log(this.flightsData);
console.log(res.data);
});
},
};
九、特价机票处理
- 获取数据并渲染,在点击时拼接路径并带上数据参数
components/air/air.js设置接口
// 推荐机票
export const airsSale = function () {
return axios({
url: '/airs/sale',
})
}
pages/air/index.vue页面
<!-- 特价机票 -->
<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="$axios.defaults.baseURL + 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>
import { airsSale } from "../../components/air/air";
- 获取数据并赋值给
sales
async mounted() {
let res = await airsSale();
this.sales = res.data.data;
console.log(this.sales);
},
十、机票结果列表页
10.1基本布局
<template>
<section class="contianer">
<el-row type="flex" justify="space-between">
<!-- 顶部过滤列表 -->
<div class="flights-content">
<!-- 过滤条件 -->
<div></div>
<!-- 航班头部布局 -->
<div></div>
<!-- 航班信息 -->
<div></div>
</div>
<!-- 侧边栏 -->
<div class="aside">
<!-- 侧边栏组件 -->
</div>
</el-row>
</section>
</template>
<script>
export default {
};
</script>
<style scoped lang="less">
.contianer {
width: 1000px;
margin: 20px auto;
}
.flights-content {
width: 745px;
font-size: 14px;
}
.aside {
width: 240px;
}
</style>
10.2列表头部组件
- 创建
components/air/flightsListHead.vue- 并引入
air/flights.vue
<template>
<el-row class="flight-title">
<el-col :span="5"> 航空信息 </el-col>
<el-col :span="14">
<el-row type="flex" justify="space-between">
<el-col :span="12"> 起飞时间 </el-col>
<el-col :span="12"> 到达时间 </el-col>
</el-row>
</el-col>
<el-col :span="5"> 价格 </el-col>
</el-row>
</template>
<script>
export default {};
</script>
<style scoped lang="less">
.flight-title {
padding: 0 15px;
border: 1px #ddd solid;
background: #f6f6f6;
height: 38px;
line-height: 38px;
color: #666;
font-size: 12px;
margin-bottom: 10px;
> div {
text-align: center;
}
}
</style>
效果
10.3机票列表组件
component/air/flightsItem.vue
<template>
<div class="flight-item">
<div>
<!-- 显示的机票信息 -->
<el-row type="flex" align="middle" class="flight-info">
<el-col :span="6"> <span>东航 </span> MU5316 </el-col>
<el-col :span="12">
<el-row
type="flex"
justify="space-between"
class="flight-info-center"
>
<el-col :span="8" class="flight-airport">
<strong>20:30</strong>
<span>白云机场T1</span>
</el-col>
<el-col :span="8" class="flight-time">
<span>2时20分</span>
</el-col>
<el-col :span="8" class="flight-airport">
<strong>22:50</strong>
<span>虹桥机场T2</span>
</el-col>
</el-row>
</el-col>
<el-col :span="6" class="flight-info-right">
¥<span class="sell-price">810</span>起
</el-col>
</el-row>
</div>
<div class="flight-recommend">
<!-- 隐藏的座位信息列表 -->
<el-row type="flex" justify="space-between" align="middle">
<el-col :span="4">低价推荐</el-col>
<el-col :span="20">
<el-row
type="flex"
justify="space-between"
align="middle"
class="flight-sell"
>
<el-col :span="16" class="flight-sell-left">
<span>经济舱</span> | 上海一诺千金航空服务有限公司
</el-col>
<el-col :span="5" class="price"> ¥1345 </el-col>
<el-col :span="3" class="choose-button">
<el-button type="warning" size="mini"> 选定 </el-button>
<p>剩余:83</p>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
export default {
props: {
// 数据
data: {
type: Object,
// 默认是空数组
default: {},
},
},
};
</script>
<style scoped lang="less">
.flight-item {
border: 1px #ddd solid;
margin-bottom: 10px;
.flight-info {
padding: 15px;
cursor: pointer;
> div {
&:first-child,
&:last-child {
text-align: center;
}
}
}
.flight-info-center {
padding: 0 30px;
text-align: center;
.flight-airport {
strong {
display: block;
font-size: 24px;
font-weight: normal;
}
span {
font-size: 12px;
color: #999;
}
}
.flight-time {
span {
display: inline-block;
padding: 10px 0;
border-bottom: 1px #eee solid;
color: #999;
}
}
}
.flight-info-right {
.sell-price {
font-size: 24px;
color: orange;
margin: 0 2px;
}
}
}
.flight-recommend {
background: #f6f6f6;
border-top: 1px #eee solid;
padding: 0 20px;
.flight-sell {
border-bottom: 1px #eee solid;
padding: 10px 0;
&:last-child {
border-bottom: none;
}
.flight-sell-left {
font-size: 12px;
span {
color: green;
}
}
.price {
font-size: 20px;
color: orange;
}
.choose-button {
text-align: center;
color: #666;
button {
display: block;
width: 100%;
margin-bottom: 5px;
}
}
}
}
</style>
十一、航班列表渲染
思路:
- 渲染列表数据
- 计算相差时间
- 控制列表展开
- 分页