Composition API(vue3) 和Options API(vue2)区别

options API

  • 由于所有数据都挂载在 this 之上,因而 Options API 的写法对 TypeScript 的类型推导很不友好,并且这样也不好做 Tree-shaking 清理代码。
  • 增功能基本都得修改 data、method 等配置,并且代码上 300 行之后,会经常上下反复横跳,开发很痛苦。
  • 代码不好复用,Vue 2 的组件很难抽离通用逻辑,只能使用 mixin,还会带来命名冲突的问题。

Composition API

  • 所有 API 都是 import 引入的,没用到功能,打包的时候会被清理掉 ,减小包的大小。
  • 不再上下反复横跳,我们可以把一个功能模块的 methods、data 都放在一起书写,维护更轻松。
  • 可以更好的组织代码结构、利用业务逻辑代码复用,更好的维护
  • computed ref 声明周期靠单独引入,而不是依赖上下文(onMouted、onUnmounted)生命周期
  • Composition API 对我们开发 Vue 项目起到了巨大的帮助。下面这个示例图很好地说明了问题:每一个功能模块的代码颜色一样,左边是 Options API,一个功能的代码零散的分布在 data,methods 等配置内,维护起来很麻烦,而右边的 Compositon API 就不一样了,每个功能模块都在一起维护。

在这里插入图片描述

script setup 是为了提高使用compostion API而存在的

Composition API 拆分代码

为什么要拆分代码? 如果在一个页面里有这两个功能,那就需要在 data 和 methods 里分别进行配置。但这样的话,数据和方法相关的代码会写在一起,在组件代码行数多了以后就不好维护。所以,我们需要使用 Composition API 的逻辑来拆分代码,把一个功能相关的数据和方法都维护在一起。
但是,所有功能代码都写在一起的话,也会带来一些问题:随着功能越来越复杂,script 内部的代码也会越来越多。因此,我们可以进一步对代码进行拆分,把功能独立的模块封装成一个独立的函数,真正做到按需拆分。

在下面我们在uitils中新建一个todoList.js

import { ref, computed } from "vue";
function useTodos() {
  let title = ref("");
  let todos = ref([{ title: "学习Vue3", done: false }]);
  function addTodo() {
    todos.value.push({
      title: title.value,
      done: false,
    });
    title.value = "";
  }
  function clear() {
    //把done为true的过滤掉
    todos.value = todos.value.filter((v) => !v.done);
  }
  let active = computed(() => {
    return todos.value.filter((v) => !v.done).length;
  });
  let all = computed(() => todos.value.length);
  let allDone = computed({
    get: function () {
      return active.value === 0;
    },
    set: function (value) {
      todos.value.forEach((todo) => {
        todo.done = value;
      });
    },
  });

  function delTodo(idx){
    todos.value.splice(idx,1)
  }
  return { title, todos, addTodo, clear,delTodo, active, all, allDone };
 }
export {
  useTodos
}

这个函数就是把那些和清单相关的所有数据和方法,都放在函数内部定义并且返回,这样这个函数就可以放在任意的地方来维护。

而我们的组件入口,也就是 script setup 中的代码,就可以变得非常简单和清爽了。在下面的代码中,我们只需要调用 useTodos,并且获取所需要的变量即可,直接在模板中使用即可,具体的实现逻辑可以去 useTodos 内部维护,代码可维护性大大增强。

<script setup>
	import {useTodos} from '../utils/todoList'
	import {useAdd} from '../utils/tiredAdd'
	let { title, todos:todoList, addTodo, clear,delTodo, active, all, allDone } = useTodos();
</script>

响应式style 样式的特性

在 style 标签上,当我们加上 scoped 这个属性的时候,我们定义的 CSS 就只会应用到当前组件的元素上,这样就很好地避免了一些样式冲突的问题。

<style scoped>
h1 {
  color: red;
}
</style>>

这样,组件就会解析成下面代码的样子。标签和样式的属性上,新增了 data- 的前缀,确保只在当前组件生效。


<h1 data-v-3de47834="">1</h1>
<style scoped>
h1[data-v-3de47834] {
    color: red;
}
</style>

style 标签的特殊属性,通过标记 scoped 可以让样式只在当前的组件内部生效,还可以通过 v-bind 函数来使用 JavaScript 中的变量去渲染样式,如果这个变量是响应式数据,就可以很方便地实现样式的切换。


<template>
  <div>
    <h1 @click="add">{{ count }}</h1>
  </div>
</template>

<script setup>
import { ref } from "vue";
let count = ref(1)
let color = ref('red')
function add() {
  count.value++
  color.value = Math.random()>0.5? "blue":"red"
}
</script>

<style scoped>
h1 {
  color:v-bind(color);
}
</style>>
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐