效果图
博客教程:如何使用 Vue.js 构建简单的意见反馈页面
目录
引言
在本教程中,我们将使用 Vue.js 和 HTML 构建一个简单的意见反馈页面。该页面包含问题类型选择、场景选择、反馈描述输入框、联系方式输入框,以及提交反馈按钮。这是一个适合初学者的 Vue.js 项目,通过此项目你将了解如何实现基本的表单处理、条件渲染和事件绑定等功能。
项目结构
以下是代码文件结构。我们将在一个 HTML
文件中编写完整的代码。
index.html
— 包含了 HTML、CSS 和 Vue.js 代码
代码实现
设置页面布局
首先,我们将编写基础页面结构,包括一个标题、表单各部分的容器,以及提交按钮。以下代码片段展示了如何设置基础布局。
<!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: 0;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
#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;
}
h2 {
font-size: 18px;
text-align: center;
margin: 0;
}
</style>
</head>
<body>
<div id="app">
<h2>意见反馈</h2>
</div>
</body>
</html>
在以上代码中,我们创建了一个 #app
容器,将所有组件都放在该容器中以便与 Vue.js 绑定。
实现问题类型选择功能
接下来,我们使用 Vue 的 v-for
指令来循环显示不同的 “问题类型” 选项,同时使用 @click
事件和 v-bind
绑定动态类,实现点击选项后高亮显示。
<div class="section">
<div class="section-title">问题类型</div>
<div class="options">
<div
v-for="type in problemTypes"
:key="type"
:class="['option', { active: selectedProblemType === type }]"
@click="selectProblemType(type)"
>
{
{ type }}
</div>
</div>
</div>
data: {
problemTypes: ['功能异常', '产品改进'],
selectedProblemType: '',
},
methods: {
selectProblemType(type) {
this.selectedProblemType = type;
}
}
实现问题发生的场景选择功能
类似于问题类型选择,我们可以添加问题场景的选择功能。这次也使用 v-for
循环和条件样式绑定。
<div class="section">
<div class="section-title">问题发生的场景</div>
<div class="scene-options">
<div
v-for="scene in scenes"
:key="scene"
:class="['scene-option', { active: selectedScene === scene }]"
@click="selectScene(scene)"
>
{
{ scene }}
</div>
</div>
</div>
data: {
scenes: ['外卖', '优选', '更多'],
selectedScene: '',
},
methods: {
selectScene(scene) {
this.selectedScene = scene;
}
}
编写反馈描述和字符计数功能
在反馈描述部分,我们添加一个 textarea
并将其与 feedbackText
变量绑定,使用 Vue 的双向绑定功能实时显示字符数。
<div class="section">
<div class="section-title">反馈描述</div>
<textarea v-model="feedbackText" placeholder="说说您的建议或问题,方便我们提供更好的服务(5个字以上)"></textarea>
<div class="text-count">{
{ feedbackText.length }}/300</div>
</div>
data: {
feedbackText: '',
},
联系方式输入和提交功能
最后,添加一个输入框用于填写联系方式,并创建一个提交按钮。点击提交时,首先检查描述是否足够长,符合条件后提交。
<div class="section">
<div class="section-title">联系方式(选填)</div>
<input type="text" class="contact-input" v-model="contact" placeholder="请输入您的手机号">
</div>
<button class="submit-button" @click="submitFeedback">提交反馈</button>
data: {
contact: '',
},
methods: {
submitFeedback() {
if (this.feedbackText.length < 5) {
alert('请至少输入5个字的反馈描述');
return;
}
alert('反馈已提交');
this.resetForm();
},
resetForm() {
this.selectedProblemType = '';
this.selectedScene = '';
this.feedbackText = '';
this.contact = '';
}
}
完整代码
<!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: 0;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
#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;
}
h2 {
font-size: 18px;
text-align: center;
margin: 0;
}
.section {
margin-top: 20px;
}
.section-title {
font-size: 16px;
color: #333;
margin-bottom: 10px;
}
.options, .scene-options {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.option, .scene-option {
flex: 1;
background-color: #f4f4f4;
padding: 10px;
text-align: center;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.option.active, .scene-option.active {
background-color: #e0f7fa;
color: #00796b;
font-weight: bold;
}
.textarea {
margin-top: 10px;
}
textarea {
width: 100%;
min-height: 80px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
box-sizing: border-box;
font-size: 14px;
resize: none;
}
.text-count {
text-align: right;
font-size: 12px;
color: #999;
}
.add-image {
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
padding: 10px;
border: 1px dashed #ccc;
border-radius: 5px;
color: #666;
cursor: pointer;
}
.contact-input {
margin-top: 10px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 14px;
width: 100%;
box-sizing: border-box;
}
.submit-button {
margin-top: 20px;
width: 100%;
padding: 15px;
font-size: 16px;
background-color: #ffe082;
border: none;
border-radius: 5px;
color: #fff;
cursor: pointer;
transition: background-color 0.3s;
}
.submit-button:hover {
background-color: #ffd54f;
}
</style>
</head>
<body>
<div id="app">
<h2>意见反馈</h2>
<!-- 问题类型 -->
<div class="section">
<div class="section-title">问题类型</div>
<div class="options">
<div
v-for="type in problemTypes"
:key="type"
:class="['option', { active: selectedProblemType === type }]"
@click="selectProblemType(type)"
>
{
{ type }}
</div>
</div>
</div>
<!-- 问题发生的场景 -->
<div class="section">
<div class="section-title">问题发生的场景</div>
<div class="scene-options">
<div
v-for="scene in scenes"
:key="scene"
:class="['scene-option', { active: selectedScene === scene }]"
@click="selectScene(scene)"
>
{
{ scene }}
</div>
</div>
</div>
<!-- 反馈描述 -->
<div class="section">
<div class="section-title">反馈描述</div>
<textarea v-model="feedbackText" placeholder="说说您的建议或问题,方便我们提供更好的服务(5个字以上)"></textarea>
<div class="text-count">{
{ feedbackText.length }}/300</div>
<div class="add-image">添加图片</div>
</div>
<!-- 联系方式 -->
<div class="section">
<div class="section-title">联系方式(选填)</div>
<input type="text" class="contact-input" v-model="contact" placeholder="请输入您的手机号">
</div>
<!-- 提交按钮 -->
<button class="submit-button" @click="submitFeedback">提交反馈</button>
</div>
<script>
new Vue({
el: '#app',
data: {
problemTypes: ['功能异常', '产品改进'],
selectedProblemType: '',
scenes: ['外卖', '优选', '更多'],
selectedScene: '',
feedbackText: '',
contact: ''
},
methods: {
selectProblemType(type) {
this.selectedProblemType = type;
},
selectScene(scene) {
this.selectedScene = scene;
},
submitFeedback() {
if (this.feedbackText.length < 5) {
alert('请至少输入5个字的反馈描述');
return;
}
alert('反馈已提交');
// 清空输入框
this.selectedProblemType = '';
this.selectedScene = '';
this.feedbackText = '';
this.contact = '';
}
}
});
</script>
</body>
</html>
功能扩展建议
如果你希望更进一步,可以尝试添加以下功能:
- 图片上传功能:可以使用
<input type="file">
实现。 - 后端集成:将反馈数据提交到服务器以便保存。
- 输入校验:对联系方式进行格式验证,例如手机号格式。
总结
通过本教程,我们实现了一个简单的 Vue.js 反馈表单应用,包含了问题类型和场景选择、反馈描述输入和字符计数、联系方式输入,以及提交和数据重置等功能。这些功能展示了如何使用 Vue 的双向数据绑定、事件绑定和条件渲染等核心特性,非常适合新手学习。