引用类型在项目中的实际使用以及思考

254 阅读4分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。

我们在学习JavaScript时,肯定会学习到JavaScript的数据类型,其中又分为基本类型和引用类型,这里就不一一列举;这次想要记录的主要是我自己在开发中针对对象这种引用类型的特点,在面对部分需求时的解决方法;

1. 面对大量数据的渲染和操作

使用场景:当页面中有一个表格,且对表格数据有查找/修改的需求;

实现思路:首先表格数据肯定是一个对象数组的形式,而上面的需求的本质就是根据条件查找到对应的对象;我会选择根据原有的对象数组新建一个对象,这个对象以id或者数组的下标为key,对应的对象为value;

// 原始数据users,用于表格的渲染
let users = [
  {
    id: 1,
    name: '张三',
  },
  {
    id: 2,
    name: '李四',
  },
]

// 由于对象是引用类型,所以只要userObj和users下的对象指向的同一个地址
// 那么如果usersid为1的对象变量name变化了( 张三 -> 王五 )
// userObj下id为1的对象变量name也会相应变化( 张三 -> 王五 )
// 这样就省却了多次修改变量
let len = users.length
for(let i = 0; i < len; i++) {
  userObj[users[i].id] = users[i]
}

// 根据users创建的变量userObj,用于快速查找
let userObj = {
  1: {
    id: 1,
    name: '张三',
  },
  2: {
    id: 2,
    name: '李四',
  }
}

假设没有创建变量userObj,那么每次需要找到某一条数据,就需要遍历users,如果需要找的是多条数据,那么就需要使用嵌套循环的形式来查找;

那么如果我预先创建了变量userObj,那么就起码减少了了一层循环,个人认为在一般情况下,这种通过空间换取事件的形式是能够提高效率的;

2. vue项目中对父子组件间变量的操作

使用场景:子组件需要修改父组件传递进来的变量;

实现思路:常规的父子组件通信需要使用props、$emit等形式,但是如果父组件通过props传递给子组件的变量为一个对象,那么子组件可以通过直接修改这个对象变量的形式操作这个变量,父组件中这个变量也会随之更改;

起初在实现这个功能的时候还觉得这个操作能节省很多代码,毕竟根据vue提供的父子组件的通信方法需要在父组件中多写一个方法,然后再子组件需要修改父组件变量的时候调用;

但是我们可以在官网上看到关于Prop的单向数据流的相关的内容,如下:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

我个人的理解是,数据从父组件开始往子组件传递,而因为这种父子结构可能是一对多的,所以为了避免程序的可读性变差,子组件要避免去修改父组件传递的参数;这也能联系到我在学习react时了解到的一种思路,子组件仅作为UI组件,不进行任何逻辑的操作,仅仅根据样式展示数据;

而且根据官网的提示,如果传递多个数据中有一个更新,那么子组件会更新所有的数据,也会影响性能;

而假设确实在子组件中需要修改变量,那么官网也提供了简单明了的例子,我摘抄一下:

// 1. 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用
// 在这种情况下,最好定义一个本地的 data property 并将这个 prop 用作其初始值
props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}


// 2. 这个 prop 以一种原始的值传入且需要进行转换
// 在这种情况下,最好使用这个 prop 的值来定义一个计算属性:
props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}