心愿便利贴
发表于: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是主页面。css是element-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 文件中补全代码,具体需求如下:
- 将填写完的表单正确渲染到许愿墙上。
- 完成表单验证,姓名(必填项) 2-4 个字符,许愿内容(必填项)长度在 1 到 30 个字符。
本项目使用到的 element-ui 表单验证 API 如下:
表单属性
| 参数 | 说明 | 类型 |
|---|---|---|
| rules | 表单验证规则 | object |
表单项属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| prop | 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 | string | 传入 Form 组件的 model 中的字段 | - |
| required | 是否必填 | boolean | - | false |
| trigger | 验证时触发的事件 | string | click/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>