Nuxtjs结合Element-ui框架应用项目详细记录---时间处理/搜索框自动补全

420 阅读2分钟

一、搜索框的自动补全

显示自动补全的两个步骤

  1. 声明 fetch-suggestion 定义获取建议的函数
  2. 在函数当中,可以接受两个参数,
  • 第一个是饿了么传进来当前的输入值
  • 第二个是饿了么提供的封装好的显示列表函数 这个函数可以在形参随意命名 只要执行这个函数,并且带上结果数组 就会显示一个建议列表
  • 出发地输入框弹出搜索建议
  • 到达地输入框弹出搜索建议

获取真正的推荐数据:

  • 使用 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>

十一、航班列表渲染

思路:

  1. 渲染列表数据
  2. 计算相差时间
  3. 控制列表展开
  4. 分页