学了点皮毛之后,由于项目中修改用户信息,商品页面,管理员信息页面大多一样,所以想写个组件来复用。
不过毕竟初学,手法还很稚嫩,其中大多功能托饿了么的福,用了element组件。少些很多还不太懂的代码。
大概原理:
通过父子组件互相传值,完成信息修改。通过父组件传递要修改的id,以及申请修改的请求来源。子组件接收值后,调用http请求获取数据(后台传回的数据格式有些要求,规定了所需验证方式),接到数据后,通过循环生成特定数量的输入框。
话说休繁,上代码。
父组件中绑定传值:
<el-button @click="handleView(scope.row)" type="text" size="small">修改</el-button> <list-update :id='toChildId' @childToFather="clear_id" :transfer='transfer'></list-update> methods:{ handleView:function(row){ this.toChildId=row.id; this.transfer="update_user" }, clear_id:function(data){ this.toChildId='' ; this.getnode(); } },
因为信息列表中有很多项信息是通过循环出来的,通过点击修改按钮触发handleView函数改变toChildID的值,在这中发现了一个特别的属性,scope.row。很有用,会再开一个博客写。
clear_id方法是用来把toChildId置空,目的在后面说。
子组件代码如下:
<template> <div class="list_update"> <el-dialog title="修改信息" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <el-form label-position="left" status-icon :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic"> <el-form-item prop="id" label="ID" :rules="[ { required: true, message: 'ID不可为空', trigger: 'blur' } ]" > <el-input v-model="dynamicValidateForm.id" disabled></el-input> </el-form-item> <el-form-item v-for="(domain, index) in dynamicValidateForm.domains" :label="domain.label" :key="domain.key" :prop="'domains.' + index + '.value'" :rules="myrules[index]" v-if="need_select.indexOf(domain.label)==-1" > <el-input v-model.number="domain.value" v-if="need_number.indexOf(domain.label)>=0"></el-input> <el-input v-model="domain.value" v-else></el-input> </el-form-item> <el-form-item :label="domain.label" key="domain.key" :prop="'domains.' + index + '.value'" :rules="myrules[index]" v-else> <el-select v-model="domain.value" placeholder="请选择职位"> <el-option v-for=" a in select_choose" :label="a" :value="a"></el-option> <!-- <el-option label="会员" value="会员"></el-option> --> </el-select> </el-form-item> <el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button> <el-button @click="resetForm('dynamicValidateForm')">重置</el-button> <el-button @click="dialogVisible=false">返回</el-button> </el-form> </span> </el-dialog> </div> </template> <script> export default { name:'list_update', props:{ id:{ type:String, required:true }, transfer:{ type:String, required:true } }, data() { return { need_select:'', need_number:'', select_choose:'', myrules:'', dialogVisible: false, dynamicValidateForm: { domains: [], id: '' } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { let id=this.dynamicValidateForm.id; let come_from='list_update'; let update_table=this.transfer; this.dynamicValidateForm.domains[0].value=encodeURI(this.dynamicValidateForm.domains[0].value); let formDetail=JSON.stringify(this.dynamicValidateForm.domains) this.$http.post(this.baseUrl+'myphp/message_update.php',{come_from:come_from,id:id,formDetail:formDetail,update_table:update_table},{emulateJSON: true}).then((response)=>{ console.log(response.body) if(response.body==1){ alert("修改成功!") this.dialogVisible=false }else{ alert('修改失败!') } }) } else { console.log('error submit!!'); return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); }, removeDomain(item) { var index = this.dynamicValidateForm.domains.indexOf(item) if (index !== -1) { this.dynamicValidateForm.domains.splice(index, 1) } }, handleClose(done) { this.$confirm('确认关闭?') .then(_ => { done(); }) .catch(_ => {}); }, addDomain(value1,value2,value3) { this.dynamicValidateForm.domains.push({ value: value2, key: value3, label:value1 }); } }, watch:{ id:function(){ var checkNumber = (rule, value, callback) => { if (!value&&value!=0) { return callback(new Error('不能为空')); } setTimeout(() => { if ( isNaN( value )) { callback(new Error('请输入数字值')); } else { callback(); } }, 500); }; if(this.id!=''){ this.dynamicValidateForm.id=this.id let id=this.dynamicValidateForm.id; let come_from=this.transfer; this.dialogVisible=true; this.$http.post(this.baseUrl+'myphp/message_before.php',{come_from:come_from,id:id},{emulateJSON: true}).then((response)=>{ this.dynamicValidateForm.domains=[] this.myrules=[] this.need_number=response.body.need_number this.need_select=response.body.need_select this.select_choose=response.body.select_choose for(var i=0;i<response.body.list.length;i++){ if(response.body.need_number.indexOf(response.body.list[i].label)>=0){ // console.log(typeof(Number(response.body.list[i].value))) this.addDomain(response.body.list[i].label,Number(response.body.list[i].value),response.body.list[i].key) this.myrules.push( [{ required: true, message: '不能为空', trigger: 'blur' }, { validator: checkNumber, trigger: 'blur' }]) }else{ this.addDomain(response.body.list[i].label,response.body.list[i].value,response.body.list[i].key) this.myrules.push([{ required: true, message: '不能为空', trigger: 'blur' }]) } } }) } }, dialogVisible:function(){ if(!this.dialogVisible){ this.$emit("childToFather","turn_false") this.resetForm('dynamicValidateForm') } } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> .list_update{ width: 600px; margin:auto; } </style>接收toChildId和transfer,获取相关数据,循环使用addDomain方法处理成想要的数据结构。v-for循环生成input框,通过v-if判断生成input框类型(和是否为下拉框)。
主要内容在于id的监听。监听id有变化时,根据新传入的id调取内容。
但有一个bug,主要原因是如果用户点击修改后,有点击了取消,再次点击同一项的修改时,子组件接收到的toChildId没有变化,弹窗就不会被唤醒。
解决办法就是 通过向父组件传值(传什么不重要)父组件接到值后调用函数,把传过去的toChildId置空,再次点击修改时,传入的toChildId就会有变化,触发子组件相应的内容。
后台返回的数据格式是有点要求的。我用php页面获取数据,大概就是这样(PHP小白,只能写成这样了,见谅。。):
<?php header('Access-Control-Allow-Origin:*'); header('Content-Type:text/html; charset= utf-8'); include 'link.php';//数据库的配置 if($come_from=='update_user'){ $id=$_POST['id'];//获取数据,并给要获取的数据取别名,这里的汉字别名是子组件输入框前的中文提示 $sql=" select name as '会员名称', phone as '电话号码',referrerID as '推荐人',rank as '职位',real_name as '真实姓名',bankcard as '银行卡号',bankname as '银行卡名' from user_info where id='$id' limit 1 "; $result=mysqli_query($link,$sql); $list=mysqli_fetch_assoc($result); $result=mysqli_query($link,$sql); $list=mysqli_fetch_assoc($result); $sql2=" select name,phone,referrerID,rank,real_name,bankcard,bankname from user_info where id='$id' limit 1 "; //$sql2的查询,以及后面的foreach,是为了在获取的list中加入一个key值,这个值在子组件的v-for中以及修改后提交到后台时有用到。 $result2=mysqli_query($link,$sql2); $list2=mysqli_fetch_assoc($result2); $list['会员名称']=urldecode(base64_decode($list['会员名称']));//使用的数据库中的会员名称是加密的,需要解密 $list2['name']=urldecode(base64_decode($list2['name'])); $newlist=[]; $n=0; $n2=0; foreach ($list as $k=>$v){ $newlist[$n]['value']=$v; $newlist[$n]['label']=$k; $n=$n+1; } foreach ($list2 as $k=>$v){ $newlist[$n2]['key']=$k; $n2=$n2+1; } $re['list']=$newlist; $re['need_select']=['职位'];//增加个标记 规定需要下拉框的输入框项 $re['select_choose'][0]="会员";//下拉框中可选的选项 $re['select_choose'][1]="店员"; $re['select_choose'][2]="门店"; $re['select_choose'][3]="全国代理"; $re['select_choose'][4]="商家"; $re['need_number']=['电话号码','推荐人'];//规定需要数字验证方式的输入框 echo json_encode($re); } $newlist[$n2]['key']=$k; $n2=$n2+1; } $re['list']=$newlist; $re['need_select']=['职位'];//增加个标记 规定需要下拉框的输入框项 $re['select_choose'][0]="会员";//下拉框中可选的选项 $re['select_choose'][1]="店员"; $re['select_choose'][2]="门店"; $re['select_choose'][3]="全国代理"; $re['select_choose'][4]="商家"; $re['need_number']=['电话号码','推荐人'];//规定需要数字验证方式的输入框 echo json_encode($re); } ?>
。。大概就是这样把,代码比较粗糙,瞧一眼设计思路就好了。
