HTML、Vue.js、Element.js 感兴趣的小伙伴们可以下载测试一波
案例实现源码 提取码:love
点击预订按钮,弹出一个dialog对话框,并将景点详情模块的数据传递到对话框中,具体包括景点名称,景区门票价格然后在dialog对话框中镶嵌一个form表单。
form表单功能模块简述:
1.对门票价格进行只读属性,对门票个数进行增减操作(最少减至1,为1时减少按钮失效)
2.添加radio单选按钮,实现预订模式的转换,选择否,对应景点预订;选择是,对应酒店+景点预订
3.添加酒店、酒店房间类型、入住时间选择、入住天数四个select选择下拉框,关键在于对其value和label的数据获取和传递
4.关联酒店和房间类型的数据、根据具体公式计算最终预订价格(并且在所有表单事件获取有效数据才显示最终价格),利用element自带的模板代码进行ref控制
5.按钮的确认、取消、重置以及气泡提示框的组件使用,增强交互效果
boxforshop.html
<div id="app">
<div v-for="(info,index) in infos" :key="info.name+index">
<div class="content">
<figure>
<img :src="info.img" alt="" :key="info.img">
figure>
<div class="cr">
<h3 :key="info.name">{{info.name}}h3>
<span class="stn1" :key="info.cont">{{info.cont}}span>
<span class="stn2" :key="info.price">¥{{info.price}}span>
<el-button @click="changeValue(info.name,info.price,info.count)" class="btn">预订
el-button>
div>
div>
div>
<el-dialog :title="fname" :visible.sync="dialogFormVisible" :before-close="handleClose">
<el-form :model="form" label-width="120px" :rules="rules" ref="form" :inline="true"
class="demo-form-inline">
<el-form-item label="门票价格" :label-width="formLabelWidth">
<el-input type="text" v-model="fprice" readonly="readonly" class="e-input" style="width: 201.5px;">
el-input>
el-form-item>
<el-form-item label="选择门票" :label-width="formLabelWidth">
<el-input type="text" v-model="fcount" placeholder="请选择购买门票个数" class="e-input"
style="width: 201.5px;">el-input>
<el-button @click="dec()" :disabled="fcount <= 1">-el-button>
<el-tooltip class="item" effect="dark" content="最多购买5张" placement="top-start">
<el-button @click='add()' :disabled="fcount >= 5">+el-button>
el-tooltip>
el-form-item>
<el-form-item label="酒店+景点" :label-width="formLabelWidth" prop="resource" style="display: block;">
<el-radio-group v-model="form.resource">
<el-radio label="是" value="1">el-radio>
<el-radio label="否" value="0">el-radio>
el-radio-group>
el-form-item>
<div v-if="form.resource === '是' ">
<el-form-item label="选择酒店" :label-width="formLabelWidth" prop="name">
<el-select v-model="form.name" placeholder="请选择酒店" @change="hotelValue">
<el-option v-for="(item,index) in hotelList" :label="item.label" :value="item.value"
:key="item.value">
el-option>
el-select>
el-form-item>
<el-form-item label="房间类型" :label-width="formLabelWidth" prop="namec">
<el-tooltip class="item" effect="dark" content="仅限购买一间" placement="top-start">
<el-select v-model="form.namec" placeholder="请选择酒店房间类型" @change="hotelcValue"
style="margin-left: 0;">
<el-option v-for="(itemc,index) in hotelcList" :label="itemc.label" :value="index+1"
:key="'hc-'+index">
el-option>
el-select>
el-tooltip>
<span v-if="form.namec != '' && form.name != ''"> ¥{{itemc.value}}span>
<span v-else>span>
el-form-item>
<el-form-item label="居住时间" :label-width="formLabelWidth" prop="date1">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 204%;">
el-date-picker>
el-col>
el-form-item>
<el-form-item label="居住天数" :label-width="formLabelWidth" prop="region" style="margin-left: -15px;">
<el-select v-model="form.region" placeholder="请选择居住天数" @change="dayValue">
<el-option v-for="(item1,index) in dayList" :label="item1.label" :value="item1.value"
:key="'d-'+index">
el-option>
el-select>
el-form-item>
div>
<div v-else>
div>
<el-form-item label="电子发票" prop="delivery">
<el-switch v-model="form.delivery">el-switch>
el-form-item>
<el-form-item label="总计支付" :label-width="formLabelWidth" style="display: block;">
<span v-if="form.resource == '否'|| (form.resource == '是' && form.region != '' && form.name != '' && form.namec != '') ">¥
<strong style="text-decoration: none;color: red;font-size: 14px;">{{totalPrice}}strong>span>
<span v-else>span>
el-form-item>
el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeFrom('form')">取 消el-button>
<el-button type="primary" @click="submitForm('form')">确 定el-button>
<el-button @click="resetForm('form')">重置el-button>
div>
el-dialog>
div>
<script src="js/boxforshop.js">script>
css样式
js导入,这里我使用的是公共js
common.js
//调用公共css
document.write('');
document.write('');
//调用公共js
document.write('');
document.write('');
boxforshop.js
/*
* @Author: lzm
* @Date: 2021-11-24 17:21:59
* @Notes: 使用built命令快速得到一些常用的snippets,右击py文件可以preview代码
* @LastEditTime: 2021-11-24 23:21:46
*/
//保存当前的this
// var _this = this;
new Vue({
//
el: '#app',
data() {
return {
//数据源
infos: [
{
img: 'img/img1.png',
name: '张家界天门山',
cont: '这就是我,不一样的烟火',
price: 299,
count: 1
},
{
img: 'img/img2.png',
name: '张家界武陵源',
cont: '不到武陵源,枉到张家界',
price: 279,
count: 1
}
],
//
form: {
name: '',
namec: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
//控制dialog显示与隐藏
dialogFormVisible: false,
//label宽度
formLabelWidth: '120px',
//酒店列表
hotelList: [
{ label: '张家界华天大酒店', value: 129 },
{ label: '张家界韦斯特大酒店', value: 159 },
],
//酒店房间类型列表
hotelcList: [
{ label: '普通单人房', value: 1 },
{ label: '普通双人房', value: 2 },
{ label: '豪华单间', value: 3 },
{ label: '豪华双人房', value: 4 },
{ label: '经济大床房(3-5)', value: 5 },
{ label: '豪华大套房(3-5)', value: 6 },
],
//居住天数
dayList: [
{ label: '1', value: 1 },
{ label: '2', value: 2 },
{ label: '3', value: 3 },
{ label: '5', value: 5 },
{ label: '7', value: 7 },
],
//初始化变量
value: '',
//循环接收对应变量 对应酒店价格、房间价格、居住天数
fname: "",
fprice: "",
fcount: "",
//关联酒店与房间的中间变量
iname: 0,
//展示酒店名称的变量
janem: '',
// 列表value提取
item: {},
item1: {},
itemc: {},
//表单规则
rules: {
name: [
{ required: true, message: '请选择酒店', trigger: 'blur' },
// { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
],
namec: [
{ required: true, message: '请选择酒店类型', trigger: 'blur' },
],
region: [
{ required: true, message: '请选择居住天数', trigger: 'change' }
],
date1: [
{ type: 'date', required: true, message: '请选择日期', trigger: 'change' }
],
resource: [
{ required: true, message: '请选择购买形式', trigger: 'change' }
],
// date2: [
// { type: 'date', required: true, message: '请选择时间', trigger: 'change' }
// ],
// type: [
// { type: 'array', required: true, message: '请至少选择一个活动性质', trigger: 'change' }
// ],
// desc: [
// { required: true, message: '请填写活动形式', trigger: 'blur' }
// ]
}
}
},
methods: {
//未调用
onSubmit() {
//ajax发送成功的是响应的时候也需要要关闭弹出层
this.dialogFormVisible = false
},
//监听酒店的select选择事件
hotelValue(value) {
this.item = this.hotelList.find((item) => {
console.log(this.form.name);
console.log(this.itemc.value);
console.log(this.iname);
if (this.iname != 0) {
this.hotelcValue(this.iname)
}
//这里必须全等于,数据才会动态绑定在一起,原理还未百度
return item.value === value
});
// console.log(this.item);
this.jame = this.item.label;
//由于没有双向绑定jame,并且由于函数作用域问题导致无法在全局使用,暂不影响
console.log(this.jame);
},
//监听酒店房间的select选择事件
hotelcValue(value) {
console.log(this.form.name);
console.log(this.item.value);
this.itemc = this.hotelcList.find((itemc) => {
// console.log(value);
itemc.value = value
this.iname = itemc.value
if (itemc.value === 1) {
// console.log(itemc.value);
return itemc.value = this.form.name - 20;
}
if (itemc.value === 2) {
return itemc.value = this.form.name + 30;
}
if (itemc.value === 3) {
return itemc.value = this.form.name;
}
if (itemc.value === 4) {
return itemc.value = this.form.name + 60;
}
if (itemc.value === 5) {
return itemc.value = this.form.name + 100;
}
if (itemc.value === 6) {
return itemc.value = this.form.name + 160;
}
return itemc.value = value
})
},
//监听居住天数的select选择事件
dayValue(value) {
this.item1 = this.dayList.find((item1) => {
return item1.value === value
})
},
//使用methods方法实现点击事件获取价格计算
getPrice() {
console.log(this.form.name);
console.log(this.form.region);
this.totalPrice = this.itemc.value * this.form.region + this.info.price * this.info.count
if (this.totalPrice > 1000) {
return this.totalPrice = this.totalPrice - 100
}
if (this.totalPrice > 2000) {
return this.totalPrice = this.totalPrice - 200
}
if (this.totalPrice > 3000) {
return this.totalPrice = this.totalPrice - 500
}
return this.totalPrice
},
//门票数增减button
dec() {
// console.log('dec',index);
this.fcount--
},
add() {
// console.log('add',index);
this.fcount++
},
//确定按钮点击事件
submitForm(formName) {
console.log(formName);
this.$refs[formName].validate((valid) => {
if (valid) {
// console.log(this.item.label);
if (this.form.resource == "否") {
alert('购买成功!, 你选择的套餐是:' + this.fname + '景点');
}
else {
alert('购买成功!, 你选择的套餐是:' + this.fname + '景点和' + this.item.label + '酒店');
}
// return this.dialogFormVisible = false
this.dialogFormVisible = false;
// 点击取消 数据重置
this.$refs[formName].resetFields();
} else {
console.log('error submit!!');
return false;
}
});
},
//重置按钮
resetForm(formName) {
this.$refs[formName].resetFields();
},
//接收循环对应数据,值传递, 这一步很重要
changeValue(name, price, count) {
this.dialogFormVisible = true
this.fname = name
this.fprice = price
this.fcount = count
},
//X号点击事件
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => { });
},
// 对话框取消事件
closeFrom(formName) {
this.dialogFormVisible = false;
// 点击取消 数据重置
this.$refs[formName].resetFields();
}
},
//计算属性
computed: {
//计算价格
totalPrice() {
let result = 0;
// console.log(this.form.name);
// console.log(this.form.region);
// result = this.info.price * this.info.count
if (this.form.resource === "是") {
result = this.itemc.value * this.form.region + this.fprice * this.fcount
}
else {
result = this.fprice * this.fcount
}
if (result > 1200) {
return result = result - 100
}
if (result > 2000) {
return result = result - 300
}
if (result > 3000) {
return result = result - 500
}
else {
return result
}
// return result
}
}
});
//log代码暂不删除,方便后期查看测试,学习过程很乏味,但是一旦有了自己想要的成果,这一切就变得有意义了
1.首先界面UI比较容易实现,找到对应的class进行样式设置,就是需要反复调试费时间
2.element中的dialog对话框组件不需要跟随页面数据循环,这样不仅会造成代码冗余,还会被提示form不是一个函数的错误警告,原因是form具有唯一性(我猜的)
3.对于vue相关指令的了解与熟练使用,可以说在这个案例中显得淋漓尽致,包含v-model、v-for、v-if、v-else、v-bind、v-on都有涉及
4.对于报错,需要常常用到console.log()进行测试
5.难点在于选择酒店和酒店房间类型之间的关联和数据绑定与传递,我理解的酒店房间的选择才是最终的实际价格,以及select选择的非顺序输入对交互和数据显示的影响,好在都已调试解决
没有对票数和人数与酒店元素相关联,功能并不完善;
酒店和酒店房间的价格关联并不合理,缺乏逻辑性,但是应付需求还是可行的
//监听居住天数的select选择事件
dayValue(value) {
this.item1 = this.dayList.find((item1) => {
return item1.value === value
})
},
这里的find()方法有什么作用?以及 return item1.value === value 中的全等于 与 赋值 = 有什么区别(在我的案例中,这里写赋值=,会获取不到改变的select的value值)
在实现这些功能的过程中,会因为实现了某个需求而喜悦,也会因为某个代码报错而感到烦恼,但是好在我的问题都可以通过在CSDN、简书、百度搜索而得到解决,所以感谢那些帮我完成功能模块的优质文章创作者们!所以附上我认为在此案例中有价值的文章链接。
ElementUI中获取select 的label值
vue+elementui 对话框取消 表单验证重置示例
elementUi Dialog 对话框使用中数据获取问题
Dialog 对话框
计算属性