vue3代码的组织形式

注:本文是大圣老师课程的笔记,原课程地址:06 | 新的代码组织方式:Composition API + 到底好在哪里? (geekbang.org)

一,使用setup之后的改变

首先新建一个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>

在 script setup语法中,我们使用引入的 ref 函数包裹数字,返回的 count 变量就是响应式的数据,使用 add 函数实现数字的修改。需要注意的是,对于 ref 返回的响应式数据,我们需要修改 .value 才能生效,而在 script setup 标签内定义的变量和函数,都可以在模板中直接使用。

也就是说,从上面代码看,相较于vue2来说,有这点改变:

1,不再有export default,然后data,methods,components等的写法了,而是直接从vue引入相关api如(ref)来实现代码。

紧接着,把这个组件引入到home页面使用:


<template>
    <h1>这是首页</h1>
    <TodoList />    
</template>

<script setup>
import TodoList from '../components/TodoList.vue'
</script>

可以看到一个新的改变:

2,vue3的setup会自动注册组件,这样就减少了注册组件的一步。而可以直接使用。

完善代码后:

<template>
  <div>
    <div class="title">
      <input type="text" @keypress.enter="add" v-model="title" />
       <button v-if="active < all" @click="clear">清理</button>
    </div>
    <div class="content">
      <ul v-if="todoList.length">
        <li v-for="(item, index) in todoList" :key="index">
          <input type="checkbox" v-model="item.done" />
          <span :class="[item.done ? 'inactive' : 'active']">
            {
    
    {
    
     item.content }}
          </span>
        </li>
      </ul>
      <div v-else>暂无数据</div>
    </div>
    全选 {
    
    {
    
     active }} / {
    
    {
    
     all }}
  </div>
</template>

<script setup>
import {
    
    ref,computed} from "vue"
//把这个useTodo解耦出来
function useTodos() {
    
    
  let title=ref("")
  let todoList=ref([
    {
    
    
      content:"五湖四海皆一望",
      done:false
    },{
    
    
      content:"千江有水千江月",
      done:true}
    ])
  function add() {
    
    
    const obj = {
    
    
      content: title.value,
      done: false
    };
    todoList.value.push(obj);
    title.value = "";
  }
  function clear() {
    
      
    todoList.value = todoList.value.filter((v) => !v.done)
  }
  let active=computed(()=>{
    
    
    return todoList.value.filter((v) => !v.done).length
  })
  let all = computed(() => todoList.value.length);
  let allDone = computed(
    {
    
     
      get: function () {
    
     
        return active.value === 0; 
      }, 
      set: function (value) {
    
    
        todoList.value.forEach((todo) => {
    
     todo.done = value; });
      },
    }
  );
  return {
    
    title,todoList,add,clear,active,all,allDone}
}

//其实你可以把组件内部的任何一段代码,从组件文件里抽离出一个独立的文件进行维护。
//再在这个组件中使用,于是这些东西就不依赖于this上下文了,这里再解构赋值出来
let {
    
     title, todoList, add, clear, active, all, allDone } = useTodos();


import {
    
    useMouse} from '../utils/mouse'
let {
    
    x,y} = useMouse()

</script>

<style scoped>
</style>

这里又可以看到两个新的改变:

3,computed不再在return default里面,而是通过vue导入来使用,具体的计算属性作为参数传入。
4,和这个表单相关的功能,我们用useTodos函数包裹起来,又因为是ref实现的,和本组件解耦了,于是可以在想要的地方维护。不一定要放在本组件中,只要需要时引入使用即可。

二,解耦功能js代码的示例:

例如一个获取鼠标实时位置的功能,可以在util中新建这个文件:

import {
    
    ref, onMounted,onUnmounted} from 'vue'

export function useMouse(){
    
    
    const x = ref(0)
    const y = ref(0)
    function update(e) {
    
    
      x.value = e.pageX
      y.value = e.pageY
      console.log("测试鼠标",x.value,y.value)
    }
    onMounted(() => {
    
    
      window.addEventListener('mousemove', update)
    })
  
    onUnmounted(() => {
    
    
      window.removeEventListener('mousemove', update)
    })
    return {
    
     x, y }
}

然后只要在想要的地方引入使用就可以了:

import {
    
    useMouse} from '../utils/mouse'
let {
    
    x,y} = useMouse()

三,css样式中也可以使用属性绑定js中的变量

<template>
  <div class="todoBox">
    <div class="title">
      <input type="text" @keypress.enter="add" v-model="title" />
       <button v-if="active < all" @click="clear">清理</button>
    </div>
    <div class="content">
      <ul v-if="todoList.length">
        <li v-for="(item, index) in todoList" :key="index">
          <input type="checkbox" v-model="item.done" />
          <span :class="[item.done ? 'inactive' : 'active']">
            {
    
    {
    
     item.content }}
          </span>
        </li>
      </ul>
      <div v-else>暂无数据</div>
    </div>
    全选 {
    
    {
    
     active }} / {
    
    {
    
     all }}
  </div>
</template>

<script setup>
import {
    
    ref,computed} from "vue"

//把这个useTodo解耦出来
function useTodos() {
    
    
  let title=ref("")
  let todoList=ref([
    {
    
    
      content:"五湖四海皆一望",
      done:false
    },{
    
    
      content:"千江有水千江月",
      done:true}
    ])
  function add() {
    
    
    const obj = {
    
    
      content: title.value,
      done: false
    };
    todoList.value.push(obj);
    title.value = "";
  }
  function clear() {
    
      
    todoList.value = todoList.value.filter((v) => !v.done)
  }
  let active=computed(()=>{
    
    
    return todoList.value.filter((v) => !v.done).length
  })
  let all = computed(() => todoList.value.length);
  let allDone = computed(
    {
    
     
      get: function () {
    
     
        return active.value === 0; 
      }, 
      set: function (value) {
    
    
        todoList.value.forEach((todo) => {
    
     todo.done = value; });
      },
    }
  );
  return {
    
    title,todoList,add,clear,active,all,allDone}
}

//其实你可以把组件内部的任何一段代码,从组件文件里抽离出一个独立的文件进行维护。
//再在这个组件中使用,于是这些东西就不依赖于this上下文了,这里再解构赋值出来
let {
    
     title, todoList, add, clear, active, all, allDone } = useTodos();

import {
    
    useMouse} from '../utils/mouse'
let {
    
    x,y} = useMouse()

//定义这个color变量
let color=ref("red")
</script>

<style scoped>
.active{
    
    
  color:v-bind(color)
}
</style>

需要注意的是,color不能写在函数useToDo里面,因为函数外部读取不到,如果写里面,则还需要return,然后解构赋值才能使用。

实现的效果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42349568/article/details/121063696