Vue 中如何实现仿有道词典的页面设计?

1. 前言

Vue 是当下最流行的前端框架之一,具有数据响应式、组件化、轻量化等优点,同时由于其灵活性,可以轻易地实现各种复杂的页面设计。本篇文章将以仿有道词典的页面设计为例,介绍 Vue 中如何实现。

2. 页面结构设计

2.1 整体布局

仿有道词典的页面主要分为顶部导航栏、搜索框、搜索结果等三个部分,其中搜索结果还包括左侧菜单栏和右侧展示区。因此,我们可以使用 Vue 的组件化思想,将整个页面划分为三个组件:Header、SearchBar 和 SearchResult。

// Header.vue

<template>

<div class="header">

<!-- 导航栏内容 -->

</div>

</template>

<script>

export default {

// 组件相关代码

}

</script>

// SearchBar.vue

<template>

<div class="searchbar">

<!-- 搜索框内容 -->

</div>

</template>

<script>

export default {

// 组件相关代码

}

</script>

// SearchResult.vue

<template>

<div class="searchresult">

<div class="menu">

<!-- 左侧菜单栏内容 -->

</div>

<div class="content">

<!-- 右侧展示区内容 -->

</div>

</div>

</template>

<script>

export default {

// 组件相关代码

}

</script>

2.2 搜索框布局

由于搜索框部分包含搜索框和搜索按钮两个子组件,并且搜索按钮被点击后还需要响应父组件 SearchResult 的事件,因此我们需要使用 Vue 中的 props 和事件机制来实现。

// SearchBar.vue

<template>

<div class="searchbar">

<input type="text" v-model="keyword"><!-- 搜索框 -->

<button @click="handleClick">搜索</button><!-- 搜索按钮 -->

</div>

</template>

<script>

export default {

props: {

submit: {

type: Function,

required: true

}

},

data() {

return {

keyword: ''

}

},

methods: {

handleClick() {

this.submit(this.keyword)

}

}

}

</script>

// SearchResult.vue

<template>

<div class="searchresult">

<search-bar :submit="handleSubmit"></search-bar>

<!-- 下面的菜单栏和展示区的内容 -->

</div>

</template>

<script>

import SearchBar from './SearchBar.vue';

export default {

components: {

SearchBar

},

methods: {

handleSubmit(keyword) {

// 处理搜索结果相关的逻辑

}

}

}

</script>

2.3 搜索结果布局

搜索结果部分比较复杂,因此我们需要再将其细分为左侧菜单栏和右侧展示区,分别对其进行编写。其中,左侧菜单栏需要渲染搜索结果的分类信息,右侧展示区则需要根据不同的分类来渲染对应的搜索结果列表。

// SearchResult.vue

<template>

<div class="searchresult">

<search-bar :submit="handleSubmit"></search-bar>

<menu :data="menuData"></menu>

<result :data="resultData"></result>

</div>

</template>

<script>

import SearchBar from './SearchBar.vue';

import Menu from './Menu.vue';

import Result from './Result.vue';

export default {

components: {

SearchBar,

Menu,

Result

},

data() {

return {

menuData: [], // 左侧菜单栏数据

resultData: [], // 右侧展示区数据

currentCategory: '' // 当前选中的分类

}

},

methods: {

handleSubmit(keyword) {

// 处理搜索结果相关的逻辑

},

handleCategoryClick(category) {

this.currentCategory = category

}

}

}

</script>

// Menu.vue

<template>

<div class="menu">

<div

v-for="category in data"

:class="{ active: category === currentCategory }"

@click="handleClick(category)"

>

{{ category }}

</div>

</div>

</template>

<script>

export default {

props: {

data: {

type: Array,

default: () => []

}

},

data() {

return {

currentCategory: ''

}

},

methods: {

handleClick(category) {

this.currentCategory = category

this.$emit('categorychange', category)

}

}

}

</script>

// Result.vue

<template>

<div class="result">

<div v-for="(item, index) in data" :key="index">

<p><strong>{{ item.title }}</strong></p>

<p>{{ item.content }}</p>

</div>

</div>

</template>

<script>

export default {

props: {

data: {

type: Array,

default: () => []

}

}

}

</script>

3. 数据获取与展示

3.1 发送请求获取数据

使用 Vue 进行前端开发最常见的数据来源便是 API 接口。因此,我们需要在 SearchResult 组件中发送请求获取搜索结果,并将得到的数据保存到组件的 data 中。

// SearchResult.vue

<template>

<div class="searchresult">

<search-bar :submit="handleSubmit"></search-bar>

<menu :data="menuData" @categorychange="handleCategoryClick"></menu>

<result :data="resultData"></result>

</div>

</template>

<script>

import SearchBar from './SearchBar.vue';

import Menu from './Menu.vue';

import Result from './Result.vue';

export default {

components: {

SearchBar,

Menu,

Result

},

data() {

return {

menuData: ['xxx', 'yyy', 'zzz'], // 左侧菜单栏数据

resultData: [], // 右侧展示区数据

currentCategory: '' // 当前选中的分类

}

},

methods: {

async handleSubmit(keyword) {

const res = await fetch(`/search?q=${keyword}`)

const data = await res.json()

this.resultData = data

},

handleCategoryClick(category) {

this.currentCategory = category

}

}

}

</script>

3.2 根据分类渲染内容

由于展示区的内容需要随着左侧菜单栏的分类变化而改变,因此我们需要根据当前选中的分类来渲染对应的内容。

// SearchResult.vue

<template>

<div class="searchresult">

<search-bar :submit="handleSubmit"></search-bar>

<menu :data="menuData" @categorychange="handleCategoryClick"></menu>

<result :data="currentData"></result>

</div>

</template>

<script>

import SearchBar from './SearchBar.vue';

import Menu from './Menu.vue';

import Result from './Result.vue';

export default {

components: {

SearchBar,

Menu,

Result

},

data() {

return {

menuData: ['xxx', 'yyy', 'zzz'], // 左侧菜单栏数据

resultData: [], // 右侧展示区数据

currentCategory: '' // 当前选中的分类

}

},

computed: {

currentData() {

return this.resultData.filter(item => item.category === this.currentCategory)

}

},

methods: {

async handleSubmit(keyword) {

const res = await fetch(`/search?q=${keyword}`)

const data = await res.json()

this.resultData = data

},

handleCategoryClick(category) {

this.currentCategory = category

}

}

}

</script>

4. 总结

通过以上实现方法,我们成功地实现了仿有道词典的页面设计。相信读者通过本篇文章的介绍,不仅学会了 Vue 的基础使用方法,还掌握了如何使用组件化思想来搭建复杂的页面结构,并能够通过 API 接口来获取、展示数据。