《一步步用Vue.js构建用户反馈表单,内含详细源码和解释》 《从零开始:使用Vue.js构建功能齐全的反馈系统》 《新手友好!Vue.js实现表单处理和数据绑定的完整指南》 《Vue.js表单实例:

效果图

在这里插入图片描述

博客教程:如何使用 Vue.js 构建简单的意见反馈页面

目录
  1. 引言
  2. 项目结构
  3. 代码实现
  4. 功能扩展建议
  5. 总结

引言

在本教程中,我们将使用 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 的双向数据绑定、事件绑定和条件渲染等核心特性,非常适合新手学习。


猜你喜欢

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