使用vue.js+element实现简单dialog对话框功能

毕设篇:点击预订按钮实现简单酒店+景点预订购买功能

效果展示


使用vue.js+element实现简单dialog对话框功能_第1张图片
使用vue.js+element实现简单dialog对话框功能_第2张图片
使用vue.js+element实现简单dialog对话框功能_第3张图片

技术实现

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 对话框

计算属性

你可能感兴趣的:(毕设-旅游网,vue.js,element,ui,dialog对话框,js)