手写Vue Table组件遇到的问题,特别是computed属性的执行时机

一、先说需求

        我想仿照elementUi中的table组件进行一次仿写练习,实现的功能不多,就是实现一下基础的展示和根据其中一列进行升序和降序的排列!!!

        

         基本就是如此,图中我将升序、降序的参考列设置为了时间列,点击时间那个label,就会进行升序和降序的排列。

        

二、思路

        

<div class="flex">
    <VTable :data="data">
      <TableCol prop="date" label="时间" sortable />
      <TableCol prop="name" label="名字" />
      <TableCol prop="address" label="地址" />
    <VTable/>
  </div>

        我们都知道,在table组件中,我们直接给table组件传入data数据,table将根据用户设置的tableCol中的prop属性来将这一列展示出来,

        比如,你的prop设置为date,那么tableCol应该在table去拿到传入的data数据(如下图)(data一般为数组),然后将数组中每一组数据中的date拿出来,放到一个对象里,并且加上对应的id(用于后续随着一列数据的顺序的改变,其他列也按照改变列的顺序进行排序),重新变为一个新数组,并展示。

        

const tableData = [
  {
    date: "2016-05-02",
    name: "王小虎1",
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    date: "2016-05-04",
    name: "王小虎2",
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    date: "2016-05-01",
    name: "王小虎3",
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    date: "2016-05-03",
    name: "王小虎4",
    address: "上海市普陀区金沙江路 1516 弄",
  },
];

        展示的基本的思路就是如此,这样每一个tableCol负责一组data中同样的prop的数据的展示。

        1.当,要求排序的时候,因为每一个tableCol负责自己那一组prop下的数据,当date的数据按照升序排列时,由于在computed阶段为每一个数据加上了id,

computed: {
    colDatas() {
      console.log("computed")
      return this.tableDataCom.map((item) => {
        // 更好的方案从这里tableData获取新的数组
        return { data: item[this.prop], id: item.id }; //获取id来完成后续的排序
      });
    },
  },

注意,tableDateCom 是 table组件中data数据,进入到tableCol组件后,本文使用inject的方式植入,并且将其赋值到data中的属性,用于后续生命周期钩子中的加ID处理

        2.所以当这一组数据的顺序进行改变后,记录各个id的新的序列(sortIds),然后通知table,并将新的id数组告知table,


    changeSort() {
      // 变化顺序并且更新
      if (this.sorted) { // sorted是一个flag 用来标记是升序还是降序
        // 升序
        this.colDatas.sort((a, b) => {
          return b.data[9] - a.data[9]; //为了方便一点,直接先写死了
        });
      } else {
        // 降序
        this.colDatas.sort((a, b) => {
          return a.data[9] - b.data[9];
        });
      }
      this.sortIds = this.colDatas.map((item) => {
        return item.id;
      });
      this.sorted = !this.sorted;
      // 新的index的顺序带过去
      this.$parent.$emit("sortChange", this.sortIds); // this.$on绑定在父级,这里必须加parent
    },
    

        3.这时,table将再次告知各个tableCol组件,将各自管辖下prop数组按照已经排序的prop的新的id序列,进行排序,来完成统一排序。

父组件table进行on监视sortChange事件,让每一个子组件tableCol进行按照新的ids进行重排

 

根据传入的新的id序列,对自己接收的父组件table的data的镜像数据,进行重排,当tableDataCom改变之后,会重新调用computed中的colDatas,进而完成更新。

 三、一些事后反思的点与思考

1.不好的地方

        1.不好的地方,我觉得首先,由于自己没有深刻理解这个table组件的意义,后来看了视频,人家都是通过data数据,来确定几个label的那一行,也就是标题行,data数据不需要拆解,

        而我是通过每一个label,将原本的数据进行了拆解,将同属于一个label或者prop的数据,进行合并,然后用flex-direction = column来完成了一列的展示,效率很低。

        2.由于我一开始对于table的理解有误,我不得不在这条歪路上越走越远,导致我,computed,watch,生命周期函数,以及将inject获得的数据放到data里,这些操作,有很多都是可以减少的。

 2.反思的点

        1. 用index来标识原来的数组 来 搭配id 来识别就会出现很多问题!

              // 1 3 0 2 + 3 2 1 0 + 2 0 3 1 + 1 3 0 2 用index 出现 问题

        原来我使用了index来标识数组,结果就会出现一种,升序和降序进行修改后,进行数组没有一下子变成想要的升序列或者降序列而是,出现了上面的第2、4 两种ids。

        我也有点说不清那种情况,反正就是以后不要用index来识别每一个数据的顺序

        2.this.$on this.$emit

        这个问题,我发现了两种模式,

        一种是我们常常在父组件中把@xxx= “xxx” ,写到哪一个<son @xxx = "sss"/>

        这个时候在子组件son中,直接写this.$emit()

        on the other hand,就是直接在父组件中mounted函数中,写this.$on监听事件的,像上面的一样,这个时候子组件就需要写this.$parent.emit()

        原因:我觉得应该是那种@xxx=“sss”,也是写到子组件实例中,在实例化中,绑定到了子组件上!!!

        3.computed的执行问题

         这个是本次最大的收获!!!

           在beforecreate和created两个生命周期之间,Vue 进行了initComputed,也就是初始化了computed中的每一个属性,并且放到vm实例上,进行了响应式处理,但是!!!

            但是computed中的每一个属性,并没有执行

         

 

 

1 在initComputed中,对每一个computed属性的函数设置为userDef,并且设置赋值给了getter,

2 放到watcher里,用于后续的update!!!

 3 将每一个computed属性的key放到vm里,进行响应式处理

 

所以到此为止,computed中的每一属性(xxx)没有执行,但是created之后,可以调用this.xxx来先执行一遍。

!!!!important!!!!

而在beforemount和mounted之间,由于挂载vm到浏览器上时,由于初始化数据,这时候的computed中每一个属性,就会自动被执行了!!!

有鉴于此,我在tableCol中将获得table的数据后,在created阶段,这个时候,data数据已经有了tableDataCom 是 inject进来的tableData的镜像数据。

在这个时候我判断源数据是否有id,没有我就自己加上,用于后续的操作!!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值