美文网首页
vue 向请求数据添加新字段,view层实时渲染

vue 向请求数据添加新字段,view层实时渲染

作者: 兔子不打地鼠打代码 | 来源:发表于2018-07-10 14:34 被阅读116次

一、需求

地址选择列表

  • 默认地址置顶(字段: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">&#xe60b;</font>
    <font v-else >&#xe602;</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的承认。

因为 Vue 是通过递归遍历初始数据中的所有属性,并用 Object.defineProperty 把它们转化为 getter 和 setter 来实现数据观察的。如果一个属性在实例创建时不存在于初始数据中,那么 Vue 就没有办法观察这个属性了。——【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;
        });
      }
    },

相关文章

网友评论

      本文标题:vue 向请求数据添加新字段,view层实时渲染

      本文链接:https://www.haomeiwen.com/subject/qljfpftx.html