Skip to content

心愿便利贴

作者:江月迟迟
发表于:2024-12-10
字数统计:1601 字
预计阅读6分钟

介绍

小蓝发现人之间面对面交流逐渐减少,倾诉的机会变少了,有些人比较腼腆保守,不敢大声说出自己的心里话,期盼之类的,容易造成压力过大,心愿便利贴可以匿名,提供大家安全隐秘方便的倾诉平台。

小蓝希望大家写下自己的目标、理想、愿望等,激励自己奋斗,积极向上......写出来做一个精神寄托。

可是,小蓝对 Vue 语法不熟,便利贴没能完成,快来帮助小蓝完成吧!

准备

本题已经内置了初始代码,打开实验环境,目录结构如下:

txt
├── css
│   ├── fonts
│   │   ├── element-icons.ttf
│   │   └── element-icons.woff
│   ├── index.css
│   └── wish.css
├── images
│   ├── bg.jfif
│   └── ding.png
├── index.html
└── js
    ├── index.js
    └── vue.min.js

其中:

  • index.html 是主页面。
  • csselement-ui 存放项目样式的文件夹。
  • images 是图片文件夹。
  • js 是项目所依赖的 js 库的文件夹。

注意:打开环境后发现缺少项目代码,请复制下述命令至命令行进行下载。

bash
wget https://labfile.oss.aliyuncs.com/courses/18164/wish.zip && unzip wish.zip && rm wish.zip

在浏览器中预览 index.html 页面效果如下:

初始效果

在初始化的时候输入框并没有做验证,输入内容发布后,许愿贴并不能出现。

目标

请在 index.html 文件中补全代码,具体需求如下:

  1. 将填写完的表单正确渲染到许愿墙上。
  2. 完成表单验证,姓名(必填项) 2-4 个字符,许愿内容(必填项)长度在 1 到 30 个字符。

本项目使用到的 element-ui 表单验证 API 如下:

表单属性

参数说明类型
rules表单验证规则object

表单项属性

参数说明类型可选值默认值
prop表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的string传入 Form 组件的 model 中的字段-
required是否必填boolean-false
trigger验证时触发的事件stringclick/focus/change/blur/input-
min最小长度number--
max最大长度number--
message验证不通过时的错误信息string--

使用示例

html
   <el-form-item label="姓名" prop="activeName">
      <el-input v-model="form.activeName" placeholder="请输入姓名"></el-input>
    </el-form-item>
// ....
 rules: {
          activeName: [
            { required: true, message: '请输入活动名称', trigger: 'blur' },
            { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
          ],
    }

完成后效果如下:

完成效果

规定

  • 请按照给出的步骤操作,切勿修改默认提供的文件名称、文件夹路径等。
  • 满足需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动检测。

判分标准

  • 本题完全实现题目目标得满分,否则得 0 分。

总通过次数: 1297 | 总提交次数: 1346 | 通过率: 96.4%

难度: 中等 标签: 2022, 省模拟赛, Web 前端, Vue.js, ElementUI

题解

js
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>心愿便利贴</title>
		<!-- 引入element-ui样式 --> 
		<link rel="stylesheet" href="css/index.css">
		<link rel="stylesheet" href="./css/wish.css">
		<!-- 引入element-ui组件库 -->  
		<script src="./js/vue.min.js"></script> 
		<script src="./js/index.js"></script>
	</head>
	<body>
		<div id="app">
			<h1>心愿便利贴</h1>
			<div class="container">
				<!-- TODO 待修改的代码 -->
				<div class="card" :class="item.css" v-for="(item,index) in wishList" :key="index">
					<div class="header">
						<img class="close" @click="closeCard(index)" src="./images/ding.png" alt="close">
					</div>
					<el-image
					    v-if="item.pic"
					    style="width: 100px; height: 100px"
					    :src="item.pic" 
					    :preview-src-list="picList">
					  </el-image>
					<div class="content"> 
						{{item.content}}
					</div>
					<div class="name">{{item.name}}</div>
				</div>
			</div>
			<div class="form">
				<el-form ref="form" :rules="rules" label-position="left" :model="form" label-width="80px">
					<el-form-item label="姓名" prop="name">
						<el-input id="firstName" v-model="form.name" placeholder="请输入姓名"></el-input>
					</el-form-item>
					<el-form-item label="许愿内容" prop="content">
						<el-input type="textarea" id="content" placeholder="请输入内容" v-model="form.content" show-word-limit></el-input>
					</el-form-item>
					<el-form-item label="图片上传">
					<el-upload
					  ref="uploadRef"
					  action="#"
					  :limit="1"
					  list-type="picture-card" 
					  :on-remove="handleRemove"
					  :on-change="getPic"
					  :auto-upload="false">
					    <i slot="default" class="el-icon-plus"></i>
					    <div slot="file" slot-scope="{file}">
					      <img
					        class="el-upload-list__item-thumbnail"
					        :src="file.url" 
					      >
					      <span class="el-upload-list__item-actions">
					        <span
					          class="el-upload-list__item-preview"
					          @click="handlePictureCardPreview(file)"
					        >
					          <i class="el-icon-zoom-in"></i>
					        </span>  
							<span
								v-if="!disabled"
								class="el-upload-list__item-delete"
								@click="handleRemove(file)">
							<i class="el-icon-delete"></i>
							</span>
					      </span> 
					    </div>
					</el-upload> 
					</el-form-item>
					<el-form-item>
					    <el-button id="onSubmit" type="primary" @click="onSubmit">发布</el-button>
					    <el-button @click="onRest">重置</el-button>
					</el-form-item>
				</el-form>
				<el-dialog :visible.sync="dialogVisible">
				  <img width="100%" :src="form.pic" alt="">
				</el-dialog>
			</div>
		</div> 
	</body>
	<script>
		const app = new Vue({
			el: "#app",
			data: { 
				wishList: [], 
				form: {
					name:'',
					content: '',
					pic: ''
				},
				rules: {
					// TODO 待补充验证的代码
					name: [
						{required: true, trigger: 'blur', min: 2, max: 4, message: '长度在2-4字符'}
					],
					content: [
						{
							required: true,
							trigger: 'blur',
							min: 1,
							max: 30,
							message: '长度在1-30'
						}
					]
				},
				num:1,
				picList: [],
				textarea: '', 
				dialogVisible: false,
				disabled: false
			},
			methods: { 
				// 提交方法
			  onSubmit() { 
				  this.$refs['form'].validate((valid) => {
					if (valid) {
					  let obj = this.form;
					  obj.css = 'item' + this.num;
					  this.num++;
					  if(this.num > 4) {
						this.num = 1;
					  }
					  this.wishList.push(obj)
					  this.form = {};
					  this.$refs.uploadRef.uploadFiles.pop()  
					  console.log(this.wishList);
					  // render
					} else { 
					  this.$message({
						message: '提交错误!请检查输入内容',
						type: 'warning'
					  });
					  return false;
					}
				  }); 
			  },
			  // 关闭许愿卡
			  closeCard(index) { 
				  this.wishList.splice(index,1)
			  },
			  // 重置表单
			  onRest() { 
				  this.$refs['form'].resetFields();
			  },
			  // 图片删除
			  handleRemove(file) { 
				  let index = this.$refs.uploadRef.uploadFiles.findIndex(e => e.uid === file.uid);
				  this.$refs.uploadRef.uploadFiles.splice(index,1); 
			  },
			  // 模拟上传图片
			  getPic(e) { 
				  this.form.pic = e.url;
				  this.picList.push(e.url)
			  }, 
			  // 预览图片
			  handlePictureCardPreview(file, fileList) {
				this.form.pic = file.url;
				this.dialogVisible = true;
			  }
			}
		});
	</script>
</html>