这次终于能用上新的代码组织方式了

562 阅读2分钟

image.png

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情


这两周把公司的一个vue2.x的老项目升级到了vue2.7版本,也用上了ts,也优化了 webpack,但是最重要的还是用上了新的代码组织方式!!

新的代码组织方式

Composition API<script setup>,Composition API 可以让我们更好地组织代码结构,而让你感到好奇的 \<script setup\> 本质上是以一种更精简的方式来书写 Composition API 。


来个例子

下面来看看怎么用新的代码组织方式写一个Todolist.vue

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

<script setup>
import { ref } from "vue";
let count = ref(1)
function add(){
    count.value++
}
</script>

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

在上述代码中,我们使用 template 标签放置模板、script 标签放置逻辑代码,并且用 setup 标记我们使用 <script setup> 的语法,style 标签放置 CSS 样式。

我们就可以基于新的语法实现之前的清单应用。下面的代码就是把之前的代码移植过来后,使用 ref 包裹的响应式数据。在你修改 title 和 todos 的时候,注意要修改响应式数据的 value 属性。

<template>
  <div>
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul v-if="todos.length">
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{ done: todo.done }"> {{ todo.title }}</span>
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref } from "vue";
let title = ref("");
let todos = ref([{title:'学习Vue',done:false}])

function addTodo() {
  todos.value.push({
    title: title.value,
    done: false,
  });
  title.value = "";
}
</script>

计算属性

在 Composition API 的语法中,计算属性和生命周期等功能,都可以脱离 Vue 的组件机制单独使用 。我们向 TodoList.vue 代码块中加入下面的代码:


<template>
  <div>
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <button v-if="active < all" @click="clear">清理</button>
    <ul v-if="todos.length">
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{ done: todo.done }"> {{ todo.title }}</span>
      </li>
    </ul>
    <div v-else>暂无数据</div>
    <div>
      全选<input type="checkbox" v-model="allDone" />
      <span> {{ active }} / {{ all }} </span>
    </div>
  </div>
</template>

<script setup>
import { ref,computed } from "vue";
let title = ref("");
let todos = ref([{title:'学习Vue',done:false}])

function addTodo() {
...
}
function clear() {
  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;
    });
  },
});
</script>

所有功能代码都写在一起的话,也会带来一些问题:随着功能越来越复杂,script 内部的代码也会越来越多。因此,我们可以进一步对代码进行拆分,把功能独立的模块封装成一个独立的函数,真正做到按需拆分。

function useTodos() {
  let title = ref("");
  let todos = ref([{ title: "学习Vue", done: false }]);
  function addTodo() {
    todos.value.push({
      title: title.value,
      done: false,
    });
    title.value = "";
  }
  function clear() {
    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;
      });
    },
  });
  return { title, todos, addTodo, clear, active, all, allDone };
}
<script setup>
import { ref, computed } from "vue";

let count = ref(1)
function add(){
    count.value++
}

let { title, todos, addTodo, clear, active, all, allDone } = useTodos();
</script>

再用上Pinia

2021年11月24日,尤大在 Twitter 上宣布:Pinia 正式成为 Vue 官方的状态库,意味着 Pinia 就是 Vuex 5Pinia 的优点:

  • 同时支持 Composition Api 和 Options api 的语法;
  • 去掉 mutations ,只有 state 、getters 和 actions ;
  • 不支持嵌套的模块,通过组合 store 来代替;
  • 更完善的 Typescript 支持;
  • 清晰、显式的代码拆分;

它最初的设计理念是让Vue Store拥有一款 Composition API 方式的状态管理库,并同时能支持 Vue2.x版本的Option API 和 Vue3版本的setup Composition API开发模式,并完整兼容Typescript写法(这也是优于Vuex的重要因素之一),适用于所有的vue项目。