Vue移动端系列 => [05-1] 首页-搜索 diff

95 阅读1分钟

6.1 创建组件并配置路由

1、给搜索按钮添加to属性

<!-- 导航栏 -->
    <van-nav-bar class="page-nav-bar" fixed>
      <van-button
        class="search-btn"
        slot="title"
        type="info"
        size="small"
        round
        icon="search"
        to="/search"
      >搜索</van-button>
    </van-nav-bar>
    <!-- /导航栏 -->

1、创建 src/views/search.vue
2、创建 src/components/search-history.vue
3、创建 src/components/search-suggest.vue
4、创建 src/components/search-result.vue

<template>
  <div class="search-container">搜索页面</div>
</template>

<script>
  export default {
    name: "SearchPage",
    components: {},
    props: {},
    data() {
      return {};
    },
    computed: {},
    watch: {},
    created() {},
    methods: {}
  };
</script>

<style scoped></style>

2.配置路由

const routes = [
  {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login.vue'), // 工作里面全部用的路由懒加载
  },
  {
    path: '/',
    component: () => import('@/views/layout.vue'),
    children: [
      {
        path: '',
        name: 'home',
        component: () => import('@/views/home.vue'),
      },
      {
        path: '/qa',
        name: 'qa',
        component: () => import('@/views/qa.vue'),
      },
      {
        path: '/video',
        name: 'video',
        component: () => import('@/views/video.vue'),
      },
      {
        path: '/my',
        name: 'my',
        component: () => import('@/views/my.vue'),
      },
    ],
  },
  {
    path: '/search',
    component: () => import('@/views/search.vue'),
  },
];

3.search.vue页面

<template>
  <div class="search-container">
    <!-- 搜索框 -->
    <form action="/">
      <van-search
        v-model="searchText"
        show-action
        placeholder="请输入搜索关键词"
        @search="onSearch"
        @cancel="onCancel"
        shape="round"
        @clear="isShowResult = false"
        @focus="isShowResult = false"
      />
    </form>

    <!-- 搜索历史页面 -->
    <search-history v-if="!searchText" />
    <!-- 搜索建议 -->
    <search-suggest v-if="searchText && !isShowResult" :searchText="searchText" />
    <!-- 搜索结果 -->
    <searchResult v-if="isShowResult" />
  </div>
</template>

<script>
import searchHistory from '@/components/search/search-history.vue';
import searchSuggest from '@/components/search/search-suggest.vue';
import searchResult from '@/components/search/search-result.vue';

export default {
  name: 'search',
  components: {
    searchHistory,
    searchSuggest,
    searchResult,
  },
  data() {
    return {
      searchText: '',
      isShowResult: false,
    };
  },
  methods: {
    onSearch(val) {
      this.isShowResult = true;
      this.$toast(val);
    },
    onCancel() {
      this.$toast('取消');
    },
  },
};
</script>

<style lang="less" scoped>
.search-container {
  .van-search {
    background-color: #3296fa;
    .van-search__action {
      color: #fff;
      &:active {
        background-color: #3296fa;
        color: #fff;
        opacity: 0.9;
      }
    }
  }
}
</style>

4.search-history.vue页面

<template>
  <div>
    <van-cell title="搜索历史">
      <template #right-icon>
        <van-icon name="delete" class="search-icon" />
      </template>
    </van-cell>
    <van-cell value="搜索内容" />
    <van-cell value="搜索内容" />
    <van-cell value="搜索内容" />
  </div>
</template>

<script>
export default {
  name: 'searchHistory',
};
</script>

<style lang="less" scoped></style>

5.search-suggest.vue页面

<template>
  <div class="search-container">
    <van-cell title="建议" icon="shop-o">
      <!-- 使用 right-icon 插槽来自定义右侧图标 -->
      <template #right-icon>
        <van-icon name="search" class="search-icon" />
      </template>
    </van-cell>
  </div>
</template>

<script>
export default {
  name: 'searchSuggest',
  props: {
    searchText: {
      type: String,
      required: true,
    },
  },
   //   methods: {
  //   节流  : 放技能CD
  //     fn: throttle (function() {
  //       console.log(111);
  //     }, 1000),
  //   },
  
  watch: {
    // searchText: function(newVal, oldVal) {
    //   console.log(newVal, oldVal);
    // },

	// handler这个函数是这么写immediate的固定写法,要写对象
    searchText: {
      handler(newV, oldV) {
        console.log(newV, oldV);
      },
      // 防抖  在回城的时候,只要被打断,就会重新计算时间
      // handler:debounce(function(newV, oldV){
      //      console.log(newV, oldV, this.searchText);
      // },300)
      
      // 已进入这个组件就开始监听我们外面传递进来的值
      immediate: true,
    },
  },
};
</script>

<style lang="less" scoped></style>

6.search-result.vue页面

<template>
  <div>
    <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
      <van-cell v-for="item in list" :key="item" :title="item" />
    </van-list>
  </div>
</template>

<script>
export default {
  name: 'searchResult',
  data() {
    return {
      list: [],
      loading: false,
      finished: false,
    };
  },
  methods: {
    onLoad() {
      // 异步更新数据
      // setTimeout 仅做示例,真实场景中一般为 ajax 请求
      setTimeout(() => {
        for (let i = 0; i < 10; i++) {
          this.list.push(this.list.length + 1);
        }

        // 加载状态结束
        this.loading = false;

        // 数据全部加载完成
        if (this.list.length >= 40) {
          this.finished = true;
        }
      }, 1000);
    },
  },
};
</script>

<style lang="less" scoped></style>