Vue 选取不同的产品,渲染出不同的页面 (computed 踩坑)

41 篇文章 0 订阅

场景

  • 产品经理提了一个需求:
    • 产品标准化处理,新增产品或者编辑产品的时候 可以直接通过页面操作;
    • 一个产品的开通只要再网站输入要求即可
    • 产品新的属性也是页面操作

分析

  • 现状

    • 各个产品线比较混乱,隶属于不同的项目组, 所以有各自的产品表 , 产品配置表
  • 实现

    • 各个产品合并成一个产品表, 提取公共属性,其余有差异的属性浓缩到data属性中 json串存储

环境

  • 切换产品使用是sagalbot/vue-select组件
  • Vue2.5.16
  • php5.5(运维:php7.2 这辈子都不可能的
  • top-think/framework (为什么不让用laraval呢? 哈 原因是 ….)

问题

  • computed product_modal属性 动态获取选定产品的配置信息
    • v-for 循环配置
    • v-if 渲染不同的组件
    • v-model是相应的product_modal.index.val
  • 然后 radio出现了很诡异的情况, 可以同时选中两个

解决

  • 组件有问题 vue-devtools来调试
    • 发现 product_modal.index.val属性 ,不会根据页面变化而变化;
  • computed 用法官网 找到了原因
    • computed 属性只有在依赖变化的时候 才会变化;
  • 所以新建data 选项 product_option, 在vue-select 值发生变化的时候,作对应的修改
    • 这里有个坑 sagalbot/vue-select对于change事件介绍极少
    • :on-change=function 触发事件 ;但是如果使用这个方法的话 v-select上的v-model将不在起作用 && computed自然也不会触发

源码

<template type="text/x-template" id="product_create">
    <div class="container">
        <div class="row">
            <div class="panel panel-default">
                <div class="panel-heading text-center">
                    <span class="font-bold">创建产品</span>
                </div>
                <div class="panel-body">
                    <prompt_modal ref="modal_prompt"></prompt_modal>
                    <form class="form-horizontal col-sm-12" @submit.prevent="createProduct">
                        <div class="form-group">
                            <label class="col-sm-3 control-label font-bold">账号名称:</label>
                            <div class="col-sm-6">
                                <input type="text" v-model.trim="account_name" class="form-control" disabled>
                            </div>
                        </div>
                        <div class="form-group">
                            <span class="alert-danger font-bold" v-if="!end_time"> * 必选选择</span>
                            <label class="col-sm-3 control-label font-bold">选择产品:</label>
                            <div class="col-sm-6">
                                <v-select :options="list_product_type" placeholder="请选择产品" v-model="product_type" label="product_name"></v-select>
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="col-sm-3 control-label font-bold">状态:</label>
                            <div class="col-sm-6">
                                <label class="radio-inline" v-for="status_item in  list_status">
                                    <input type="radio" v-model="status" :value="status_item.value"> {{status_item.label }}
                                </label>
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="col-sm-3 control-label font-bold">签约类型:</label>
                            <div class="col-sm-6">
                                    <select id="contract_status" v-model="contract_status" class="form-control">
                                        <option :value="item.value" v-for="item in list_contract_status">{{ item.name}}</option>
                                    </select>
                            </div>
                        </div>

                        <div class="form-group">
                            <label class="col-sm-3 control-label font-bold">限额类型:</label>
                            <div class="col-sm-6">
                                <label class="radio-inline" v-for="limit_item in list_limit_type">
                                    <input type="radio" v-model="limit_type" :value="limit_item.value"> {{ limit_item.name }}
                                </label>
                            </div>
                        </div>

                        <div class="form-group" v-if="limit_type">
                            <span class="alert-danger font-bold" v-if="!end_time"> * 必选填写</span>
                            <label class="col-sm-3 control-label font-bold">限额用量:</label>
                            <div class="col-sm-6">
                                <input type="text" class="form-control" v-model.trim="limit_number">
                            </div>
                        </div>

                        <div class="form-group">
                            <span class="alert-danger font-bold" v-if="!end_time"> * 必选填写</span>
                            <label class="col-sm-3 control-label font-bold">限额用量:</label>
                            <div class="col-sm-6">
                                <input type="text" class="form-control" v-model.trim="total_limit">
                            </div>
                        </div>

                        <div class="form-group">
                            <span class="alert-danger font-bold" v-if="!end_time"> * 必选选择</span>
                            <label class="col-sm-3 control-label font-bold" for="end_time">截至日期:</label>
                            <div class="col-sm-6">
                                <input type="date" id="end_time" v-model="end_time" class="form-control">
                            </div>
                        </div>

                        <!--1. 如果直接使用 product_modal 会导致radio不会在刷新,出现同时出现多个情况同时被选中的情况, 因为product_modal是只有在
                          依赖的产品类型发生变化的时候,再会刷新数据, 所以双向绑定的数据,  ===》 so 做为v-model的对象肯定不能是computed product_modal;
                          所以需要建立data镜像;
                          2. product_modal需要触发才会启动代码
                          -->
                        <div style="display: none">
                            {{ product_modal }}
                        </div>

                        <!-- 产品的配置属性 -->
                        <div class="form-group" v-if="product_option" v-for="(item_option,index) in product_option">
                            <span class="alert-danger font-bold" v-if="item_option.is_need"> * 必选选择</span>
                            <label class="col-sm-3 control-label font-bold" >{{ item_option.cn_name}}</label>
                            <div class="col-sm-6" v-if="item_option.type === 1">
                                <input type="text"  class="form-control" v-model.trim="item_option.val">
                            </div>
                            <div class="col-sm-6" v-else-if="item_option.type === 2">
                                <textarea class="form-control" cols="30" rows="10" v-model.trim="item_option.val"></textarea>
                            </div>
                            <div class="col-sm-6" v-else-if="item_option.type === 3">
                                <label class="radio-inline" v-for="item in  item_option.option">
                                    <input type="radio"  :value="item.opt_val" v-model="item_option.val" > {{item.opt_name }}
                                </label>
                            </div>
                            <div class="col-sm-6" v-else-if="item_option.type === 4">
                                <label class="checkbox-inline"  v-for="item in  item_option.option">
                                    <input type="checkbox"  :value="item.opt_val" v-model="item_option.val"> {{item.opt_name }}
                                </label>
                            </div>
                            <div class="col-sm-6" v-else-if="item_option.type === 5">
                                <input type="date" v-model="item_option.val" class="form-control">
                            </div>
                        </div>

                        <div class="form-group col-sm-9">
                            <ul class="list-inline pull-right">
                                <li><button type="submit" class="btn-primary btn-sm btn">开通产品</button></li>
                                <li><a @click.prevent="goBack" class="btn-default btn-sm btn">返回</a></li>
                            </ul>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    Vue.component('product_create_template', {
        template : '#product_create',
        props : ['account_info'],
        data : function () {
            return {
                account_name : '',
                account_id : '',
                contract_status : 3,
                list_contract_status : [
                    {name: '已签约已付费', value: 1},
                    {name: '已签约未付费', value: 2},
                    {name: '未签约', value: 3},
                    {name: '特殊客户', value: 5},
                    {name: '其他', value: 4}
                ],
                end_time: '',
                status : 1,
                list_status : [
                    { label : '正常', value : 1},
                    { label : '禁用', value : 0},
                ],
                list_limit_type : [
                    {name: '日限额', value: 1,},
                    {name: '月限额', value: 2},
                    {name: '年限额', value: 3},
                    {name: '无限制', value: 0},
                ], // 限额类型列表
                limit_type : 1, // 限额类型
                limit_number : '', // 限额用量
                total_limit : '', // 限额总量
                list_product_type : [], // 产品类型列表
                product_type : '', // 产品类型
                product_option : [],
            }
        },
        mounted : function(){
            // 初始化apikey appsecret
            this.iniParams();
        },
        computed : {
            // 产品配置项
            product_modal : function () {
                this.product_option = !!this.product_type ? JSON.parse(this.product_type.data) : [];
                return true;
            },
        },
        methods : {
            // 初始化apikey appsecret
            iniParams: function(){
                let account_info = JSON.parse(this.account_info);
                this.account_name = account_info.account_name;
                this.account_id = account_info.account_id;

                let vm = this;
                // 初始化产品列表
                this.$http.get('/product', {responseType: 'json'}).then(function (response) {
                    if (response.body.status === 0) {
                        vm.list_product_type = response.body.list_product_type;
                    } else {
                        this.$refs.modal_prompt.open({
                            title : '开通产品提示',
                            body : '网路故障,请稍后再试'
                        });
                        console.log(response);
                    }
                });
            },
            goBack : function(){
                window.history.back();
            },
            // 新建产品
            createProduct : function () {
                console.log(this.product_option);

                return false;
                // 检查参数
                if (!this.verifyParams()){
                    return false;
                }

                let params = {
                    product_name : this.product_name,
                    apikey : this.apikey,
                    email : this.email,
                    appsecret : this.appsecret,
                    end_time: this.end_time,
                    access_ip : this.access_ip,
                    mark : this.mark,
                    status : this.status
                };

                this.$http.post('/product/store', params, {responseType : 'json'}).then(function (response) {
                    console.log(response);
                    if (response.body.status === 0) {
                        this.$refs.modal_prompt.open({
                            title : '产品创建提示',
                            body : '产品创建成功',
                            btn_name_left : '返回产品列表',
                            btn_name_right : '立即开通产品',
                            btn_class_left : 'btn btn-sm btn-primary',
                            btn_class_right : 'btn btn-sm btn-primary',
                            btn_url_left : '/product',
                            btn_url_right : ''
                        });
                    } else {
                        this.$refs.modal_prompt.open({
                            title : '创建产品失败',
                            body : response.body.msg,
                        });
                    }
                });

            },

            // 检查参数
            verifyParams : function () {
                // 检查产品
                if (!this.product_name) {
                    this.$refs.modal_prompt.open({
                        title : '创建产品提示',
                        body : '请填写产品名称'
                    });
                    return false;
                }

                // 检查apikey appsecret
                if (!this.apikey) {
                    this.$refs.modal_prompt.open({
                        title : '创建产品提示',
                        body : '请填写产品APIKEY'
                    });
                    return false;
                }
                if (!this.appsecret) {
                    this.$refs.modal_prompt.open({
                        title : '创建产品提示',
                        body : '请填写产品APPSECRET'
                    });
                    return false;
                }

                // 检查email
                if (!this.email) {
                    this.$refs.modal_prompt.open({
                        title : '创建产品提示',
                        body : '请填写邮箱'
                    });
                    return false;
                }

                // 检查截至时间
                if (!this.end_time) {
                    this.$refs.modal_prompt.open({
                        title : '创建产品提示',
                        body : '请填写截至时间'
                    });
                    return false;
                }

                return true;
            }
        }

    });

</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值