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 接口来获取、展示数据。