返回

vue composition-api优化实战心得

前端





很长时间以来,我们一直向往vue3的开发方式,但是受限于历史项目的ie支持问题,我们做出了一个艰难的决定:在vue2中引入composition-api,来体验新特性。


在引入composition-api的过程中,我们遇到了很多问题和性能优化问题。我们阅读了大量的文档,通过尝试和实验,最终找到了一些解决方案,并且在项目中成功实施。现在,我想把这些经验分享给你们,希望对你们有所帮助。

1、合理使用setup和composition API

setup和composition API是composition-api的核心,它们允许我们在组件中以声明式的方式定义响应式数据、计算属性和方法。在使用这些API时,我们需要特别注意以下几点:

1)避免在setup函数中使用this

// ❌ 不要这样做
export default {
  setup(props, context) {
    // 不要在setup函数中使用`this`
    this.name = 'John Doe';
  }
};

```js // ✅ 这样做 export default { setup(props, context) { // 在setup函数中使用`context` const { emit } = context;
// 定义响应式数据
const name = ref('John Doe');

// 定义计算属性
const fullName = computed(() => {
  return `${name.value} Smith`;
});

// 定义方法
const changeName = (newName) => {
  name.value = newName;
};

// 返回一个对象,其中包含响应式数据、计算属性和方法
return {
  name,
  fullName,
  changeName
};

}
};

<br>

**2)避免在composition API函数中使用`this`。** 
<br>

```js
// ❌ 不要这样做
export const useMyComposition = () => {
  // 不要在composition API函数中使用`this`
  this.name = 'John Doe';
};
// ✅ 这样做
export const useMyComposition = () => {
  // 在composition API函数中使用函数参数
  const { name } = setupContext();

  // 定义响应式数据
  const fullName = ref('John Doe');

  // 定义计算属性
  const formattedName = computed(() => {
    return `${name.value} Smith`;
  });

  // 定义方法
  const changeName = (newName) => {
    name.value = newName;
  };

  // 返回一个对象,其中包含响应式数据、计算属性和方法
  return {
    fullName,
    formattedName,
    changeName
  };
};

3)避免在setup函数中定义过多的响应式数据。


如果你在setup函数中定义了过多的响应式数据,可能会导致性能问题。这是因为,每次响应式数据的依赖项发生变化时,都需要重新计算该响应式数据。因此,如果你在setup函数中定义了过多的响应式数据,可能会导致频繁的重新计算,从而降低性能。

4)避免在composition API函数中定义过多的响应式数据。


如果你在composition API函数中定义了过多的响应式数据,可能会导致性能问题。这是因为,每次响应式数据的依赖项发生变化时,都需要重新计算该响应式数据。因此,如果你在composition API函数中定义了过多的响应式数据,可能会导致频繁的重新计算,从而降低性能。

2、合理使用memo

memo是一个非常好用的工具,它可以帮助我们减少不必要的重新计算。在使用composition-api时,我们可以使用memo来优化以下几种情况:

1)优化计算属性。

// ❌ 不要这样做
export const fullName = computed(() => {
  // 这个计算属性每次都会重新计算
  return `${firstName.value} ${lastName.value}`;
});

// ✅ 这样做
export const fullName = computed(() => {
  // 使用memo来优化计算属性
  return memo(() => {
    return `${firstName.value} ${lastName.value}`;
  });
});

2)优化方法。

// ❌ 不要这样做
export const changeName = (newName) => {
  // 这个方法每次都会重新创建
  firstName.value = newName;
  lastName.value = newName;
};

// ✅ 这样做
export const changeName = (newName) => {
  // 使用memo来优化方法
  memo(() => {
    firstName.value = newName;
    lastName.value = newName;
  });
};

3、合理使用watch

watch是一个非常强大的工具,它可以帮助我们监听响应式数据的变化并执行相应的操作。在使用composition-api时,我们可以使用watch来优化以下几种情况:

1)监听响应式数据的变化并执行相应的操作。

export const watchName = watch(() => {
  // 监听firstName和lastName的变化并执行相应的操作
  return `${firstName.value} ${lastName.value}`;
}, (newName, oldName) => {
  // 当firstName或lastName发生变化时,执行相应的操作
  console.log(`Name changed from "${oldName}" to "${newName}"`);
});

2)监听计算属性的变化并执行相应的操作。

export const watchFullName = watch(() => {
  // 监听fullName的变化并执行相应的操作
  return fullName.value;
}, (newFullName, oldFullName) => {
  // 当fullName发生变化时,执行相应的操作
  console.log(`Full name changed from "${oldFullName}" to "${newFullName}"`);
});

4、合理使用provide/inject

provide/inject是一个非常强大的工具,它可以帮助我们在组件之间共享数据。在使用composition-api时,我们可以使用provide/inject来优化以下几种情况:

1)在组件之间共享响应式数据。

// 父组件
export default {
  setup() {
    // 在父组件中定义响应式数据
    const name = ref('John Doe');

    // 使用provide将响应式数据提供给子组件
    provide('name', name);
  }
};
// 子组件
export default {
  setup() {
    // 使用inject将响应式数据注入到子组件中
    const name = inject('name');

    // 使用响应式数据
    console.log(`Hello, ${name.value}!`);
  }
};

2)在组件之间共享计算属性。

// 父组件
export default {
  setup() {
    // 在父组件中定义计算属性
    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`;
    });

    // 使用provide将计算属性提供给子组件
    provide('fullName', fullName);
  }
};
// 子组件
export default {
  setup() {
    // 使用inject将计算属性注入到子组件中
    const fullName = inject('fullName');

    // 使用计算属性
    console.log(`Hello, ${fullName.value}!`);
  }
};

3)在组件之间共享方法。

// 父组件
export default {
  setup() {
    // 在父组件中定义方法
    const changeName = (newName) => {
      firstName.value = newName;
      lastName.value = newName;
    };

    // 使用provide将方法提供给子组件
    provide('changeName', changeName);
  }
};
// 子组件
export default {
  setup() {
    // 使用inject将方法注入到子组件中
    const changeName = inject('changeName');

    // 使用方法
    changeName('Jane Doe');
  }
};

## 5、合理使用ref ref是一个非常强大的工具,它可以帮助我们在组件中使用DOM元素和组件实例。在使用composition-api