从零开始,用 Vue.js 实现一个实用的搜索页面Vue.js 实战:构建一个动态搜索页面,包含历史记录、热搜和换一批功能 Vue 新手入门:快速上手的动态搜索页面教程 一步步实现一个功能丰富的搜索页

效果图

在这里插入图片描述

博客教程:使用 Vue.js 构建一个响应式搜索页面

目录
  1. 项目介绍
  2. 所需工具和技术
  3. 页面布局与样式
  4. Vue.js 数据绑定与事件处理
  5. 功能实现
  6. 总结与扩展思路
  7. 示例代码
项目介绍

在这个项目中,我们将构建一个带有搜索记录、搜索发现、热搜榜的响应式搜索页面。用户可以搜索内容,查看历史记录,点击"换一批"按钮来刷新搜索发现内容,并查看当前热门趋势。

所需工具和技术
  • HTML/CSS:用于页面布局和样式
  • Vue.js:用于实现数据绑定和页面交互
  • JavaScript:用于数据处理和逻辑控制

页面布局与样式

我们首先创建 HTML 结构,并使用 CSS 设置页面的基本样式。这个页面主要分为三个部分:

  1. 搜索栏:允许用户输入搜索关键词并提交。
  2. 历史搜索和搜索发现:展示用户历史搜索记录,并提供搜索建议。
  3. 趋势播报(热搜榜):展示当前热门的搜索词条及其趋势值。

head 部分引入 Vue.js,并设置基本的 CSS 样式,保持页面简洁、现代的视觉效果。页面的 body 中使用 div 元素构建布局,并通过 Vue 实现交互功能。


Vue.js 数据绑定与事件处理

在 HTML 结构准备好后,我们用 Vue.js 来实现数据的动态绑定和事件处理。以下是各部分功能的实现步骤。

1. 搜索记录的实现
<!-- 搜索框 -->
<div class="search-bar">
  <input type="text" v-model="searchQuery" placeholder="搜索内容">
  <button @click="search">搜索</button>
</div>
  • v-model:绑定输入框的值 searchQuery
  • @click="search":点击按钮时调用 search 方法,将输入的内容添加到搜索历史中。
2. 历史搜索与搜索发现的实现
<!-- 历史搜索 -->
<div>
  <div class="section-title">历史搜索</div>
  <div class="tags-container">
    <div v-for="item in searchHistory" :key="item" class="tag">{
   
   { item }}</div>
  </div>
</div>

<!-- 搜索发现 -->
<div>
  <div class="section-title">搜索发现</div>
  <div class="tags-container">
    <div v-for="item in searchDiscovery" :key="item" class="tag">{
   
   { item }}</div>
  </div>
  <div class="refresh-button" @click="refreshDiscovery">换一批 &#x21bb;</div>
</div>
  • v-for 循环:通过 v-for 遍历 searchHistorysearchDiscovery 数组,动态显示标签内容。
  • refreshDiscovery 方法:当用户点击 “换一批” 按钮时,更新 searchDiscovery 数据,展示新的搜索发现内容。
3. 热搜榜的实现
<!-- 热搜榜 -->
<div class="hot-list">
  <div class="section-title">趋势播报</div>
  <div v-for="(item, index) in hotTrends" :key="index" class="hot-item">
    <div class="hot-rank">{
   
   { index + 1 }}</div>
    <div class="hot-details">
      <div class="hot-title">{
   
   { item.title }}</div>
      <div class="hot-subtitle">{
   
   { item.subtitle }}</div>
    </div>
    <div class="hot-trend">趋势值{
   
   { item.trendValue }}</div>
  </div>
</div>
  • hotTrends 数组:包含每个热搜项的 titlesubtitletrendValue
  • v-for 循环:动态显示热搜榜的内容。

功能实现

实现搜索记录
search() {
    
    
  if (this.searchQuery && !this.searchHistory.includes(this.searchQuery)) {
    
    
    this.searchHistory.push(this.searchQuery);
  }
  this.searchQuery = '';
}
  • 将输入内容添加到 searchHistory 中,确保记录唯一。
  • 清空输入框,为下一次搜索准备。
实现搜索发现的换一批功能
refreshDiscovery() {
    
    
  this.discoveryIndex = (this.discoveryIndex + 1) % this.discoveryOptions.length;
  this.searchDiscovery = this.discoveryOptions[this.discoveryIndex];
}
  • discoveryIndex:跟踪当前搜索发现的批次,每次点击时更新 discoveryIndex,并刷新 searchDiscovery 内容。
  • 通过 % 运算符使批次循环展示。
实现热搜榜展示
data: {
    
    
  hotTrends: [
    {
    
     title: '暗黑纤体瓶', subtitle: '喜茶新品纤体瓶,万圣节限定款', trendValue: '98.9万' },
    // 添加更多热搜数据
  ]
}
  • 热搜榜通过 hotTrends 数组来存储数据,并用 v-for 循环展示。

总结与扩展思路

在这个项目中,我们利用 Vue.js 实现了一个搜索页面,包含搜索记录、搜索发现、趋势播报等功能。此页面结构简洁,逻辑清晰,非常适合 Vue.js 初学者练习。

扩展建议
  1. 本地存储:将 searchHistory 存储到浏览器的 localStorage 中,防止页面刷新后丢失记录。
  2. API 集成:将热搜榜数据从 API 获取,展示实时趋势。
  3. 交互优化:增加动画效果,如标签的淡入淡出,提高用户体验。

示例代码

完整代码如下所示:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>搜索页 - Vue.js 实现</title>
  <script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
  <style>
    body {
      
      
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 20px;
      background-color: #f4f4f4;
      display: flex;
      justify-content: center;
    }
    #app {
      
      
      width: 100%;
      max-width: 420px;
      background-color: #ffffff;
      border-radius: 10px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      padding: 20px;
      box-sizing: border-box;
    }
    .search-bar {
      
      
      display: flex;
      align-items: center;
      border: 1px solid #ddd;
      border-radius: 20px;
      padding: 8px 10px;
      margin-bottom: 20px;
    }
    .search-bar input {
      
      
      flex: 1;
      border: none;
      outline: none;
      font-size: 16px;
    }
    .search-bar button {
      
      
      background: none;
      border: none;
      color: #007bff;
      cursor: pointer;
      font-size: 16px;
    }
    .section-title {
      
      
      font-size: 16px;
      font-weight: bold;
      margin: 10px 0;
      color: #333;
    }
    .tags-container {
      
      
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      margin-bottom: 10px;
    }
    .tag {
      
      
      background-color: #f2f2f2;
      padding: 8px 12px;
      border-radius: 20px;
      font-size: 14px;
      color: #666;
      cursor: pointer;
      height: 30px;
      line-height: 30px;
    }
    .refresh-button {
      
      
      font-size: 14px;
      color: #007bff;
      cursor: pointer;
      margin-top: 5px;
    }
    .hot-list {
      
      
      margin-top: 20px;
    }
    .hot-item {
      
      
      display: flex;
      align-items: center;
      padding: 10px 0;
      border-bottom: 1px solid #eaeaea;
    }
    .hot-item:last-child {
      
      
      border-bottom: none;
    }
    .hot-rank {
      
      
      font-size: 18px;
      font-weight: bold;
      color: #ff6f61;
      margin-right: 10px;


      width: 30px;
    }
    .hot-details {
      
      
      flex: 1;
    }
    .hot-title {
      
      
      font-size: 16px;
      color: #333;
    }
    .hot-subtitle {
      
      
      font-size: 14px;
      color: #999;
    }
    .hot-trend {
      
      
      font-size: 14px;
      color: #666;
    }
  </style>
</head>
<body>
<div id="app">
  <!-- 搜索框 -->
  <div class="search-bar">
    <input type="text" v-model="searchQuery" placeholder="搜索内容">
    <button @click="search">搜索</button>
  </div>

  <!-- 历史搜索 -->
  <div>
    <div class="section-title">历史搜索</div>
    <div class="tags-container">
      <div v-for="item in searchHistory" :key="item" class="tag">{
   
   { item }}</div>
    </div>
  </div>

  <!-- 搜索发现 -->
  <div>
    <div class="section-title">搜索发现</div>
    <div class="tags-container">
      <div v-for="item in searchDiscovery" :key="item" class="tag">{
   
   { item }}</div>
    </div>
    <div class="refresh-button" @click="refreshDiscovery">换一批 &#x21bb;</div>
  </div>

  <!-- 热搜榜 -->
  <div class="hot-list">
    <div class="section-title">趋势播报</div>
    <div v-for="(item, index) in hotTrends" :key="index" class="hot-item">
      <div class="hot-rank">{
   
   { index + 1 }}</div>
      <div class="hot-details">
        <div class="hot-title">{
   
   { item.title }}</div>
        <div class="hot-subtitle">{
   
   { item.subtitle }}</div>
      </div>
      <div class="hot-trend">趋势值{
   
   { item.trendValue }}</div>
    </div>
  </div>
</div>

<script>
new Vue({
      
      
  el: '#app',
  data: {
      
      
    searchQuery: '',
    searchHistory: ['烧烤', '饮料', '烤洋芋', '烤红薯', '奶茶', '米皮'],
    searchDiscovery: ['抢麦当劳惊喜周边', '优可云端超市', '洋芋饭', '刀削面', '番茄鸡蛋'],
    hotTrends: [
      {
      
       title: '暗黑纤体瓶', subtitle: '喜茶新品纤体瓶,万圣节限定款', trendValue: '98.9万' },
      {
      
       title: '太妃棒香拿铁', subtitle: '瑞幸×Pingu,新品周边', trendValue: '97.9万' },
      {
      
       title: '鱼豆腐蔬菜米线', subtitle: '米线店火热售卖', trendValue: '91.3万' },
      {
      
       title: '香辣水煮鱼', subtitle: '美食广场火爆', trendValue: '93.5万' },
    ],
    discoveryOptions: [
      ['火锅底料', '果冻粉', '牛排', '羊肉卷', '麻辣香锅'],
      ['椰子汁', '芋圆', '杨枝甘露', '米皮', '螺蛳粉'],
      ['汉堡', '冰淇淋', '奶茶', '咖啡豆', '茶叶蛋']
    ],
    discoveryIndex: 0
  },
  methods: {
      
      
    search() {
      
      
      if (this.searchQuery && !this.searchHistory.includes(this.searchQuery)) {
      
      
        this.searchHistory.push(this.searchQuery);
      }
      this.searchQuery = '';
    },
    refreshDiscovery() {
      
      
      this.discoveryIndex = (this.discoveryIndex + 1) % this.discoveryOptions.length;
      this.searchDiscovery = this.discoveryOptions[this.discoveryIndex];
    }
  }
});
</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_22182989/article/details/143312166