学了点皮毛之后,由于项目中修改用户信息,商品页面,管理员信息页面大多一样,所以想写个组件来复用。
不过毕竟初学,手法还很稚嫩,其中大多功能托饿了么的福,用了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);
}
?>
。。大概就是这样把,代码比较粗糙,瞧一眼设计思路就好了。