一、需求
地址选择列表
- 默认地址置顶(字段:isDefult,只有一条)
- 默认勾选默认地址
- 只能勾选一条地址,且勾选地址要显示成打勾
- 勾选好地址后,点击确定按钮,要发送请求
ps. 图中的true和false 只是为了方便查看实时数据;
二、需求实现
先上一个不大简便的方法,组长说用‘医院和科室’的选择思路来做更好,后续优化后再补。
大致思路:
1、向请求来的数据里,手动新增一个字段 ‘check’ ,因为默认地址要默认打勾,且默认的字段‘isDefult’也是一个Boolean值,所以只需要让check的初始值等于idDefult的值就可以。
2、通过isdeful
的值,对数组进行排序。
3、在data里设置对象defultForm:{},
,初始值为默认地址的值,之后点击哪条地址,defultForm就变成哪条地址的值,点击确定按钮后执行的请求以其为参数。
三、所遇问题
我定义了一个公共函数,请求地址列表数据,返回一个this.commpatAddressList = list
async mixin_get_commpat_address_list(){
let {code,list} = await this.$http('smarthos.user.pat.address.list');
if(code==0){
return this.commpatAddressList = list
})
}
},
项目页面组件
<template>
<div>
<v-header>
<span @click="toAddAddress" slot="right">新建地址</span>
选择送药地址
</v-header>
<div>
<choose-item v-for="(o,i) in commpatAddressList" :key="i"
:info="o" :index="i" @checkAdd="checkAdd"></choose-item>
</div>
<button v-if="commpatAddressList && commpatAddressList.length>0" @click="addShip" >
确定寄到该地址</button>
</div>
</template>
<script>
export default {
data(){
return{
commpatAddressList:[], //传给子组件的地址数组
defultForm:{}, //确认按钮的http请求参数
}
},
methods:{
// 获取收货地址列表
async getAddressList(){
await this.mixin_get_commpat_address_list();
},
// 默认地址置顶,每条数据都添加check字段
//这种遍历太麻烦,后面的优化的方法
sortAddressList(){
let newAddList=[];
let defult = [];
for(let obj of this.commpatAddressList){
if (obj.isDefault==true){
obj.check = true;
defult = obj;
this.defultForm = obj;
}else{
obj.check = false;
newAddList.push(obj);
}
}
newAddList.unshift(defult);
this.commpatAddressList= newAddList;
},
//点击地址时,子组件触发的页面组件函数
//将地址数组中所有数据的check字段都改为false,
//子组件返回的index数字所对应的那条数据的check字段值变为true
checkAdd(info, index){
let newAddList=[];
for(let obj of this.commpatAddressList){
obj.check=false;
newAddList.push(obj);
}
newAddList[index].check = true;
this.commpatAddressList.splice(0);
//尝试了两种this.$set方式,但是都没有渲染
/* let news = newAddList[index];
news.check = true;
this.$set(this.commpatAddressList, index, news);*/
this.defultForm = info;
this.commpatAddressList=[].concat(newAddList);
//this.$set(this.$data, 'commpatAddressList', newAddList);
},
}
}
</script>
项目子组件
<template>
<div @click="tocheckAdd">
<div >
<font v-if="info.check"></font>
<font v-else ></font>
</div>
<div >
<p ><span class="flex0 ziti">{{info.name}}</span><span>{{info.mobile}}</span></p>
<p >{{info.areaName}},{{info.address}}</p>
</div>
</div>
</template>
<script>
export default {
name: "choose-item",
props:{
info:{
type:Object,
},
index:{
type:Number,
}
},
methods:{
tocheckAdd(){
this.$emit('checkAdd', this.info, this.index)
},
},
}
</script>
但是这样运行之后,点击地址,check的确发生了改变,但是页面上打勾选项一直没有反应;
然后试了
1、watch函数、
2、在addCheck里采用this.$set的方法修改check值,
3、采用splice方式归零commpatAddressList数组,
4、 同步传递数据 :info.sync="o"
,点击地址
仍旧没有反应;
最后找到了最初的公共的请求函数,问题就出在 return this.commpatAddressList = list
里,此处的 this.commpatAddressList 意味着初始化了组件的数据 ‘this.commpatAddressList’,然后在父组件中,再添加check,check也只存在于js层,而不受vue的承认。
所以解决办法是,在公共的请求函数里,就加上check字段
async mixin_get_commpat_address_list(){
let {code,list} = await this.$http('smarthos.user.pat.address.list');
if(code==0){
//代替了遍历数组添加check字段 以及 添加sort字段方便排序
this.commpatAddressList = list.map(r=>{
r.check=r.isDefault; //默认地址默认打勾
r.sort=r.isDefault?1:0; //idDefult为true就为1,否则为0
return r;
}).sort((a,b)=>{ //根据sort字段将数组降序排列,默认字段置顶
return b.sort-a.sort;
});
}
},