沉梦手记 沉梦手记
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端基础
  • Vue
  • React
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)

沉梦听雨

时间是最好的浸渍剂,而沉淀是最好的提纯器🚀
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 数据库基础
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • 网络通信
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 前端基础
  • Vue
  • React
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 运维与部署
  • 音视频处理
  • 随笔
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)
  • 前端基础

  • Vue

    • Vue-Router入门
    • Pinia入门
    • Vue3入门

      • Vue3简介与环境搭建
      • TypeScript基础
      • 模板语法与指令
      • 计算属性与侦听器
        • 计算属性
          • 1 计算属性
          • 2 计算属性的 Setter
        • Composition API 写法
        • 侦听器(watch)
          • Composition API:watch
      • 事件处理与表单输入
      • 组件与响应式API
      • 网络请求
      • UI组件库与项目实战
    • Vue3进阶
  • React

  • 前端学习
  • Vue
  • Vue3入门
沉梦听雨
2023-07-07
目录

计算属性与侦听器

# 计算属性与侦听器

对于任何包含响应式数据的复杂逻辑,都应该使用计算属性而非在模板中直接计算。侦听器则用于在数据变化时执行副作用。本章分别用 Options API 和 Composition API 两种风格演示。

# 计算属性

在如今编程都提出 MVC、MVP 或 MVVM 等模式的情况下,已经很少再将业务逻辑和视图层合在一起。

在 Vue3.0 中,在 HTML(相当于视图层)插值方式是可以负责计算(相当于业务逻辑),但不提倡你这么用,因为 Vue3.0 有计算属性。

# 1 计算属性

将计算放置在模板中,模板将不再是简单的和声明性的,此时,你必须先看一下它,然后才能意识到它执行的计算取决于 chen.lang。如果要在模板中多次包含此计算,则问题会变得更糟。

所以,对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性,听到了没?如果没有的话,那就看看代码吧。计算属性放在 computed 里面,函数放在 methods 里面。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Vue3.0计算属性</title>
    <script src="vue.global.js"></script>
</head>
<body>
<span id="app">
    <span>在插值中计算的结果:{{ chen.lang.length > 10 ? '太多了' : '还好' }}
    </span>
    <br/>
    <span>获取计算属性的结果:{{ langCount }}</span>
</span>
<script>
    Vue.createApp({
        data() {
            return {
                chen: {
                    name: 沉梦听雨
                    lang: [
                        'Python',
                        '前端',
                        '小程序',
                        'Java',
                        'Android App',
                        'iOS App'
                    ]
                }
            }
        },
        computed: {
            // 计算属性的 getter
            langCount() {
                return this.chen.lang.length > 10 ? '太多了' : '还好'
            }
        }
    }).mount("#app")
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

细心的朋友,可能就会问了,那我用函数计算行不行。如果不考虑性能的话,当然可以的。只是函数和计算属性的区别在于,计算属性有缓存的作用,而函数没有。

在操作过程中,如果内容没有改变,计算属性不会重新计算,而函数每次都会进行计算。用函数计算的代码,我发出来,你自己拷贝进去就好。

 <!--  新增函数计算部分  -->
    <br/>
    <span>函数计算属性的结果:{{ langFun() }}</span>
,
        methods: {
            // 函数中
            langFun() {
                return this.chen.lang.length > 10 ? '太多了' : '还好'
            }
        }
1
2
3
4
5
6
7
8
9
10

# 2 计算属性的 Setter

计算属性默认只有 getter,如果你想要一个 setter 的话,手动加上就好。

在函数里更新计算属性数据时,会调用 setter。你可以在 setter 里进行调整。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Vue3.0计算属性</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<span id="app">
<p>{{ fullName }}</p>
<p>{{ firstName }}</p>
<p>{{ lastName }}</p>
<button @click="sayHello()">点击调用set方法</button>
</span>
<script>
    Vue.createApp({
        data() {
            return {
                firstName: '程',
                lastName: '绪媛'
            }
        },

        computed: {
            // 计算属性
            fullName: {
                //getter
                get() {
                    return this.firstName + '' + this.lastName
                },
                //setter
                set(newValue) {
                    const names = newValue.split('或')
                    this.firstName = names[0]
                    this.lastName = '没有' + names[names.length - 1]
                }
            }
        },
        methods: {
            // sayHello: function() {
            //     this.fullName = '程绪媛'
            // }
            sayHello() {
                this.fullName = '程绪媛'
            }
        },
    }).mount("#app")
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

运行结果

image

点击调用 set 方法后

image


# Composition API 写法

在 <script setup> 中,使用 computed 函数定义计算属性。

有时在数据展示时要做简单的计算

<script setup lang="ts">
import { ref } from 'vue'
const firstName = ref('三')
const lastName = ref('张')

</script>

<template>
  <h2>{{lastName + firstName}}</h2>
  <h3>{{lastName + firstName}}</h3>
  <h4>{{lastName + firstName}}</h4>
</template>
1
2
3
4
5
6
7
8
9
10
11
12

看起来较为繁琐,可以用计算属性改进

<script setup lang="ts">
import { ref, computed } from 'vue'
const firstName = ref('三')
const lastName = ref('张')
const fullName = computed(() => {
  console.log('enter')
  return lastName.value + firstName.value
})
</script>

<template>
  <h2>{{fullName}}</h2>
  <h3>{{fullName}}</h3>
  <h4>{{fullName}}</h4>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • fullName 即为计算属性,它具备缓存功能,即 firstName 和 lastName 的值发生了变化,才会重新计算
  • 如果用函数实现相同功能,则没有缓存功能
<script setup lang="ts">
import { ref } from 'vue'
const firstName = ref('三')
const lastName = ref('张')
function fullName() {
  console.log('enter')
  return lastName.value + firstName.value
}
</script>
  
<template>
  <h2>{{fullName()}}</h2>
  <h3>{{fullName()}}</h3>
  <h4>{{fullName()}}</h4>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 侦听器(watch)

在输入框输入数据时,有时候,你需要实时获取到用户输入的每一个字符,才好在后台进行相关处理,像搜索引擎就是这样的。

在 Vue3.0 中,侦听用户输入,使用 watch 方法。

文本框输入一个广字,后台调用天气查询接口,这时有可能返回广州,也有可能返回广平等含有广字的城市的天气信息。当输入广州时,会再去查询一遍。侦听器一监听到有内容变化,就会去调用天气查询接口,再次查询数据。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="vue.global.js"></script>
    <script src="axios.min.js"></script>
</head>
<body>
<div id="app">
    <p>{{ weather }}</p>
    <input v-model="city" placeholder="请输入城市名称"/>
</div>
<script>
    Vue.createApp({
        data() {
            return {
                weather: '',
                city: ''
            }
        },
        watch: {
            city(newCity, oldQuestion) {
                this.getWeather()
            }
        },
        methods: {
            getWeather() {
                this.weather = '查询' + this.city + '天气中..'
                axios
                    .get('http://wthrcdn.etouch.cn/weather_mini?city=' + this.city)
                    .then(response => {
                        this.weather = response.data
                    })
                    .catch(error => {
                        this.weather = '获取不到:' + error
                    })
            }
        }
    }).mount("#app")
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# Composition API:watch

利用监听器,可以在【响应式】的基础上添加一些副作用,把更多的东西变成【响应式的】

  • 原本只是数据变化 => 页面更新

  • watch 可以在数据变化时 => 其它更新

<template>
  <input type="text" v-model="name" />
</template>

<script setup lang="ts">
import { ref, watch } from "vue";
function useStorage(name: string) {
  const data = ref(sessionStorage.getItem(name) ?? "");
  watch(data, (newValue) => {
    sessionStorage.setItem(name, newValue);
  });
  return data;
}
const name = useStorage("name");
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • 名称为 useXXXX 的函数,作用是返回带扩展功能的【响应式】数据
  • localStorage 即使浏览器关闭,数据还在
  • sessionStorage 数据工作在浏览器活动期间
上次更新: 2026/11/5 11:56:09
模板语法与指令
事件处理与表单输入

← 模板语法与指令 事件处理与表单输入→

Theme by Vdoing | Copyright © 2023-2026 沉梦听雨 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式