zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

Added internal search function

As the title suggests, I spent over an hour referring to the Nuxt documentation to add the search function. The URL address is /search. Here are the relevant codes.

You can choose to place it inside components/<Search /> and then import it into the head template, or you can create a separate page. I chose the latter.

Create a new page template /pages/search.vue.

<template>
  <div>
    <HeaderMe />
    <div class="wrapper">
      <PageSidebar />
      <div class="archive">
        <h2>{{ article.attributes.title }}</h2>
        <div class="article-content markdown-body" v-html="article.html"></div>
        <div class="search">
          <input v-model="searchQuery" type="search" autocomplete="off" placeholder="Article keywords" />
          <ul v-if="articles.length">
            <li v-for="article of articles" :key="article.slug">
              <NuxtLink :to="article.path+'/'">{{ article.title }}</NuxtLink>
               <!-- Add a / after the URL address to configure the site-wide URL format to prevent confusion -->
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import HeaderMe from "@/components/HeaderMe";
import PageSidebar from '@/components/PageSidebar';
export default {
  components: {
    HeaderMe,
    PageSidebar
  },
  data () {
    return {
      searchQuery: '',
      articles: []
    }
  },
  async asyncData () {
    // Call data from search.md
    const article = await import(`~/content/search.md`);
    return {
      article
    };
  },
  watch: {
    async searchQuery (searchQuery) {
      if (!searchQuery) {
        this.articles = []
        return
      }
      this.articles = await this.$content('posts') // posts is the name of the folder where the articles are located
        .limit(10)
        .search(searchQuery)
        .fetch()
    }
  }
}
</script>


The styling is not very important, so I will put it below.

CSS code
.wrapper {
  min-height: 300px;
  .archive {
    padding: 25px 2% 15px;
    .article-content {
      font-size: inherit;
      line-height: 1.8;
      color: inherit;
      margin-top: 20px;
    }
    .search {
      margin-top: 16px;
      input {
        width: 100%;
        background-color: #edf2f7;
        color: #2f495e;
        outline: none;
        border: none;
        border-radius: 30px;
        padding: 4px 20px;
        box-sizing: border-box;
        transition: all 0.1s linear;
        &:focus {
          box-shadow: 3px 2px 10px rgb(0 0 0 / 20%);
        }
      }
      ul {
        margin-top: 6px;
        list-style: none;
        li {
          a {
            display: block;
            padding: 6px 14px;
            line-height: 1.6;
            transition: all 0.2s linear;
            &:hover {
              background: #edf2f7;
            }
          }
        }
      }
    }
  }
}
@media (max-width: 520px) {
  .wrapper {
    .archive {
      .search {
        ul {
          li {
            a {
              border-bottom: 1px solid #ddd;
            }
          }
        }
      }
    }
  }
}
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.