Vue3从零开始——如何巧妙使用setup语法糖、computed函数和watch函数


在这里插入图片描述

下载 (14)

一、setup语法糖

之前我们在编写代码时每次都要编写setup()​ ,默认导出配置,还要返回变量和方法,有什么方法可以只写变量和方法,自动返回变量和方法?setup语法糖就可以帮助我们轻松解决这个麻烦。

下面为原本的代码:

<script>  
export default {
    setup() {
      // 创建一个响应式对象
      const state = reactive({
        count: 0,
        title: '计数器应用',
      });
  
      // 增加计数
      function increment() {
        state.count++;
      }
  
      // 重置计数
      function reset() {
        state.count = 0;
      }
      // 暴露定义的数据和函数
      return {
        state,
        increment,
        reset,
      };
    },
  };
</script>

使用setup​语法糖后:

<script setup>
import { reactive } from 'vue';
// 创建一个响应式对象
const state = reactive({
  count: 0,
  title: '计数器应用',
});

// 增加计数
function increment() {
  state.count++;
}

// 重置计数
function reset() {
  state.count = 0;
}

</script>

观察可以发现我们去除掉了export defaultsetup函数和其中的返回语句,而我们仅仅是在 script 标签上添加了setup就实现了同样的功能,可以看到代码变得更加简洁,并且不用再写返回内容了。

二、computed函数

computed​ 函数用于定义计算属性,它基于其他响应式状态自动计算其值,并且具有缓存机制,只有在依赖项变化时才会重新计算。

2.1 computed的基本用法

setup​ 中,使用 computed​ 创建计算属性。

使用步骤:

  1. 导入computed​函数
  2. computed​函数中传入一个getter​函数用来计算数据
  3. 函数返回计算好的数据,返回值为一个计算属性 ref
<template>
    <p>是否有出版书籍:</p>
    <span>{{ publishedBooksMessage }}</span>
</template>


<script setup>
// 1. 导入 computed 函数
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// 2. 传入getter函数计算数据,返回的计算属性 publishedBooksMessage
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

image

2.2 computed vs methods

与直接使用方法生成数据不同,computed​ 属性会缓存其结果,除非其依赖的响应式数据发生变化,否则不会重新计算。这对于性能优化非常重要。

前面代码的判断书籍数量是否大于0当然也可以使用函数来实现:

<template>
    <p>是否有出版书籍:</p>
    <p>{{ calculateBooksMessage() }}</p>
</template>


<script setup>
...

// 通过函数实现
function calculateBooksMessage() {
    return author.books.length > 0 ? 'Yes' : 'No'
}
</script>

两种方式在结果上确实是完全相同的,然而,不同之处在于使用computed会基于其响应式依赖被缓存。计算属性publishedBooksMessage​仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books​ 不改变,无论多少次访问 publishedBooksMessage​ 都会立即返回先前的计算结果,而不用重复执行 getter 函数。相比之下,方法调用总是会在重渲染发生时再次执行函数。

2.3 注意事项

  1. 避免直接修改计算属性值

由于从计算属性返回的值是一个“临时数据”,每当源状态发生变化时,就会创建一个新的数据。更改计算属性是没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的源状态以触发新的计算。

  1. Getter 不应有副作用

计算属性的 getter 应只做计算而没有任何其他的副作用,这一点非常重要。举例来说,不要改变其他状态、在 getter 中做异步请求或者更改 DOM!一个计算属性的声明中描述的是如何根据其他值派生一个值。因此 getter 的职责应该仅为计算和返回该值。

比如说下面的代码:在 computed​ 中引入了副作用

import { ref, computed } from 'vue';
 
const counter = ref(0);
const thresholdReached = ref(false);

// 错误:在 computed getter 中引入副作用
const checkThreshold = computed(() => {
    if (counter.value > 10) {
        thresholdReached.value = true; // 副作用:修改了外部状态
    }
    return counter.value;
});

在这个例子中,checkThreshold​ 是一个 computed​ 计算属性,但它在 getter​ 中修改了 thresholdReached​ 变量。这是一个副作用,违反了 computed​ 的最佳实践原则。解决这个问题的方法是使用侦听器watch​函数来根据其他响应式状态的变更来创建副作用。

import { ref, computed, watch } from 'vue';

const counter = ref(0);
const thresholdReached = ref(false);

// 正确:纯粹的计算属性
const checkThreshold = computed(() => {
    return counter.value;
});

// 使用 watch 监听 counter 的变化并执行副作用
watch(counter, (newVal) => {
    if (newVal > 10) {
        thresholdReached.value = true; // 副作用:修改外部状态
    }
});

三、watch函数

watch​ 函数用于监听响应式数据的变化,并执行副作用操作(如异步请求、手动修改DOM等)。在某些场景下,watch​ 比 computed​ 更适合处理复杂的副作用。

3.1 watch的基本用法

watch​ 允许我们在数据变化时执行某些操作,例如在用户输入时进行验证或发送请求。

使用步骤:

  1. 导入 watch​ 函数:从 vue​ 中导入 watch​ 函数。

  2. 定义响应式数据:使用 ref​ 或 reactive​ 定义你想要监听的响应式数据。

  3. 调用 watch​ 函数:传入要监听的响应式数据或计算属性,以及一个回调函数。当数据变化时,回调函数会被触发。

<template>
    <div>
        <input v-model="message" placeholder="输入一些内容">
        <p>输入内容:{{ message }}</p>
    </div>
</template>

<script setup>
// 1. 导入 watch 函数
import { ref, watch } from 'vue';

// 2. 定义响应式数据
const message = ref('');

// 3. 监听 message 的变化,传入回调函数
watch(message, (newValue, oldValue) => {
    console.log(`message changed from ${oldValue} to ${newValue}`);
});
</script>

代码分析:

模板部分的input​使用 v-model​ 实现双向绑定 message​,实时更新输入框的值。

当输入框的内容改变时,message​相应的也会改变,此时watch​函数监听到message​变化后也会相应的执行回调函数来输出log信息。

image
vue3 中说 watch 只能监视4种数据:

  • ref定义的数据
  • reactive 定义的数据
  • 函数返回一个值(getter函数)
  • 一个包含上述内容的数组

3.2 immediate和deep选项

watch​ 函数接受一个可选的第三个参数,可以用来配置监听的行为:

  • immediate​:是否立即执行回调,默认是 false​。如果为 true​,则在监听开始后立即执行一次回调。
  • deep​:是否深度监听对象内部的变化,默认是 false​。如果为 true​,则会深度监听对象及其嵌套属性的变化。
<script setup>
import { ref, watch } from 'vue';

const nestedObject = ref({ nested: { value: 1 } });

// 深度监听对象
watch(nestedObject, (newVal, oldVal) => {
    console.log('嵌套对象已更改:', newVal);
}, { deep: true });

</script>

四、综合小Demo

下面是一个结合了 setupcomputedwatch 的小Demo,在我们之前写的计数器的基础上实现以下功能:

  • 计数状态显示:根据当前计数值显示 “计数大于10” 或 “计数不大于10”。
  • 超限提示:当计数值超过 10 时,弹出提示框提醒用户 “计数已超过10!”。
<template>
    <div>
        <h1>{{ title }}</h1>
        <p>当前计数:{{ count }}</p>
        <p>计数状态:{{ countStatus }}</p>
        <button @click="increment">增加</button>
        <button @click="reset">重置</button>
    </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';


const title = ref('计数器');
const count = ref(0);

// 使用 computed 创建一个计算属性
const countStatus = computed(() => {
    return count.value > 10 ? '计数大于10' : '计数不大于10';
});

// 监听 count 的变化
watch(count, (newVal) => {
    if (newVal > 10) {
        alert('计数已超过10!');
    }
});

function increment() {
    count.value++;
}

function reset() {
    count.value = 0;
}

</script>

<style scoped>
button {
    margin: 5px;
    padding: 10px 20px;
    background-color: #4caf50;
    color: white;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #45a049;
}


p {
    font-size: 18px;
}
</style>

代码分析:

  • ref setup​:在 setup​ 函数中使用 ref​ 创建了 title​ 和 count​ 两个响应式变量。
  • computed​:通过 computed​ 创建了 countStatus​ 计算属性,用于动态显示计数的状态。
  • watch​:使用 watch​ 监听 count​ 变量,当其值大于10时,弹出提示框。

image

五、总结

setup​ 语法糖、computed​ 函数和 watch​ 函数是 Vue 3 组合式 API 的核心特性,提供了更灵活和高效的方式来组织组件逻辑。本文我们详细讲解了setup​ 语法糖、computed​ 函数和 watch​ 函数的基本使用语法和注意事项,通过合理使用这些特性,可以大大提升代码的可读性和可维护性。希望本文的内容对大家有所帮助☺️。


参考文章:

Vue官网

在这里插入图片描述

  • 141
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 244
    评论
对于Vue 3,我们可以同时使用`setup`函数和`setup`语法糖。在组件中,`setup`函数是一个特殊的函数,用于替代Vue 2中的选项式API(如created、mounted等)。它接收两个参数:props和context。 使用`setup`函数时,我们可以在其中访问到组件的props,并且可以返回响应式的数据、计算属性、方法等供模板使用。例如: ```javascript <script> import { ref, reactive } from 'vue'; export default { props: { message: String, }, setup(props) { const count = ref(0); // 响应式数据 const state = reactive({ name: 'John', age: 25, }); // 响应式对象 const increaseCount = () => { count.value++; }; // 响应式方法 return { count, state, increaseCount, }; }, }; </script> ``` 在模板中,我们可以直接使用`count`、`state`以及`increaseCount`: ```html <template> <div> <p>{{ message }}</p> <p>Count: {{ count }}</p> <p>Name: {{ state.name }}</p> <p>Age: {{ state.age }}</p> <button @click="increaseCount">Increase Count</button> </div> </template> ``` 除了使用`setup`函数外,Vue 3还引入了`<script setup>`语法糖,它可以更简洁地定义和使用响应式数据、计算属性、方法等。使用`<script setup>`时,我们无需再定义`props`选项,而是直接通过`defineProps`和`withDefaults`来声明和获取props。 下面是一个使用`<script setup>`的示例: ```html <template> <div> <p>{{ message }}</p> <p>Count: {{ count }}</p> <p>Name: {{ state.name }}</p> <p>Age: {{ state.age }}</p> <button @click="increaseCount">Increase Count</button> </div> </template> <script setup> import { ref, reactive } from 'vue'; const message = 'Hello Vue 3'; // 响应式数据 const count = ref(0); // 响应式数据 const state = reactive({ name: 'John', age: 25, }); // 响应式对象 const increaseCount = () => { count.value++; }; // 响应式方法 </script> ``` 可以看到,使用`<script setup>`可以使代码更简洁和易读。 综上所述,Vue 3中可以同时使用`setup`函数和`<script setup>`语法糖来定义组件的行为,并且它们可以混用,根据个人喜好和项目需求选择使用方式。
评论 244
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值