跟着尚硅谷学vue-day5

计算属性和watch监视

一.姓名案例

1.姓名案例-插值语法

复制代码
<div id="root">
        姓:<input type="text" value="张" v-model="firstname">
        <br/><br/>
        名:<input type="text" value="三" v-model="lastname">
        <br/><br/>
        全名:<span>{{firstname.slice(0,3)}} - {{lastname}}</span>
</div>

因为插值语法有局限性,如果需要对一个变量进行比较复杂的操作,推荐的是按照方法。

2.姓名案例-方法属性

复制代码
 <div id="root">
        姓:<input type="text" value="张" v-model="firstname">
        <br/><br/>
        名:<input type="text" value="三" v-model="lastname">
        <br/><br/>
        全名:<span>{{fullName()}}</span>
</div>
<script type="text/javascript">
        Vue.config.productionTip = false;
        new Vue({
            el:'#root',
            data:{
                firstname:'李',
                lastname:'四'
            },
            methods:{
                fullName(){
                    return this.firstname + '-' + this.lastname
                }
            }
        })
</script>

全名:<span>{{fullName()}}</span> 不加小括号,代表把函数写上去 ,加了小括号,会得到方法的返回值。如果是回调使用(比如绑定按钮的点击事件方法等等),小括号可加可不加。

在 Vue.js 中,当绑定的数据发生变化时,Vue 的响应式系统会自动检测到这些变化 ,并触发视图更新,而不需要手动操作 DOM。这是 Vue 的核心特性之一,称为响应式数据绑定

3.姓名案例-计算属性

计算属性:

1.定义:要用的属性不存在,要通过已有属性算得来。

2.原理:底层借助了objcet.defineproperty方法提供的getter和setter

3.get所数什么时候执行?

(1).初次读取时会执行一次。

(2).当依赖的数据发生改变时会被再次调用。

4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。缓存体现在初次刷新的时候,只调用计算属性一次get方法。

5.备注:

1.计算属性最终会出现在vm上,直接读取使用即可。

2.如果计算属性要被修改,那必须写set的数去响应修改,且set中要引起计算时依赖的数据发生

复制代码
    <div id="root">
        姓:<input type="text" value="张" v-model="firstname">
        <br/><br/>
        名:<input type="text" value="三" v-model="lastname">
        <br/><br/>
        全名:<span>{{fullName}}</span> <br/><br/>
        全名:<span>{{fullName}}</span> <br/><br/>
        全名:<span>{{fullName}}</span> <br/><br/>
        全名:<span>{{fullName}}</span> <br/><br/>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;
        const vm = new Vue({
            el:'#root',
            data:{
                firstname:'李',
                lastname:'四'
            },
            computed:{
                fullName:{
                    get(){
                        console.log('get被调用了')
                        return this.firstname + '-' +this.lastname;
                    },
                    set(value){
                        const arr = value.split('-');
                        this.firstname = arr[0];
                        this.lastname = arr[1];
                    }   
                }

            }
        })
     </script>

在 Vue.js 中,data选项用于定义组件的响应式数据属性(属性名:属性值),而计算属性(computed properties)则是基于已有的响应式数据属性,通过逻辑运算或加工生成新的属性。

在computed属性中,必须要有get,且当有人读取fullName时get就会被调用,且返回值就作为fullName的值,所以vm._data.fullName = undefined ,因为计算好之后,就会立即渲染。

计算属性的结果会被缓存,只有当依赖的响应式属性发生变化时,才会重新计算。

getter 的调用时机?

初次读取 fullName 时:当你在模板中首次访问 {``{ fullName }},或者在 JavaScript 代码中首次访问 vm.fullNamegetter 会被调用。

所依赖的数据发生变化时:如果 firstNamelastName 发生变化,fullName 的缓存会失效,下次访问 fullName 时,getter 会再次被调用。

getter 中,this 指向当前的 Vue 实例(vm),因此你可以访问 this.firstNamethis.lastName

定义 setter

默认情况下,计算属性是只读的。如果你尝试直接赋值给 fullName(例如:vm.fullName = 'Jane Smith'),Vue 会抛出一个警告:[Vue warn]: Computed property "fullName" was assigned to but it has no setter.

如果 需要fullName 是可写的,需要显式地定义一个 settersetter 会在尝试修改 fullName 时被调用。在 setter 中,建议解析新的值并更新依赖的数据属性(如 firstNamelastName)。

示例解释

Getter :在初次读取或依赖数据变化时,getter 会被调用,返回计算后的值。

Setter :当你尝试修改 fullName 时,setter 会被调用,解析新的值并更新 firstNamelastName

firstNamelastName 发生变化,计算属性get会重新调用。

定义了setter,在控制台修改计算属性,页面会进行刷新最新属性值。

4.计算属性简写和完整写法对比

复制代码
computed:{
                //完整写法
                fullName:{
                       get(){
                        console.log('get被调用了')
                        return this.firstname + '-' +this.lastname;
                    },
                       set(value){
                           const arr = value.split('-');
                           this.firstname = arr[0];
                           this.lastname = arr[1];
                     }
                 }
                //简写  只考虑读取不考虑修改
                fullName(){
                    return this.firstname + '-' +this.lastname;
                }
}

二.天气案例

1. 表达式的形式

<h2>今天天气很{{ishot ? '炎热' :'凉爽'}}</h2>

2. 计算属性

<h2>今天天气很{{info}}</h2>

<button>切换天气</button>

复制代码
   computed:{

                info(){

                    return this.ishot ? '炎热' :'凉爽'

                }

            },

 methods:{

                changeweather(){

                    this.ishot = !this.ishot

                }

            }

3.在button上面进行直接写

<button @click="ishot = !ishot">切换天气</button> 可以做一些简单的语句@click="ishot = !ishot;x++"

但如果是比较难的,alert

在 Vue.js 中,如果你在组件的方法或计算属性中直接调用 alert(1),JavaScript 的作用域链解析规则如下:

当前组件实例(vm :首先会在当前 Vue 组件实例(通常称为 vm,即 ViewModel)的作用域中查找 alert 函数。

原型链:如果组件实例中没有找到,会沿着 JavaScript 的原型链向上查找。

全局作用域(window :如果原型链中也没有找到,最后会在全局作用域(浏览器中是 window 对象)中查找。

没找到就会报错,需要这样写window.alert(1), 然后再data当中进行写data{window}。所以还是要在回调函数当中写,方便点。

4.监视属性

监视属性watch:

1.当被监视的属性变化时,回调所数自动调用,进行相关操作

2.监视的属性必须存在,才能进行监视!!

3.监视的两种写法:

(1).new Vue时传入watch配置

(2).通过vm.$watch监视

new Vue时传入watch配置

监听 ishot 数据属性的变化

复制代码
 watch:{
       ishot:{
       immediate:true,
       handler(newValue,oldValue){
       console.log(newValue,oldValue)
       console.log('ishot被监视了,并且修改了')
       }
       }
}

immediate 选项:

当设置为 true 时,会在侦听器创建后立即调用 一次 handler,即使 ishot 的初始值没有变化也会触发,默认是 false(只有在值变化时才触发)

handler 函数:

ishot 的值发生变化时会被调用,接收两个参数:newValue:变化后的新值 oldValue:变化前的旧值

通过vm.$watch监视

复制代码
vm.$watch('ishot', {
    immediate: true,  // 初始化时立即调用 handler
    handler(newValue, oldValue) {
        console.log(newValue, oldValue);
        console.log('ishot被监视了,并且修改了');
    }
});

深度监视

(1).Vue中的watch默认不监测对象内部值的改变(一层)

(2).配置deep:true可以监测对象内部值改变(多层)。备注:

(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!

(2).使用watch时根据数据的具体结构,决定是否采用深度监视。

这里有两个侦听器:一个专门监听 numbers.a 的变化,另一个监听整个 numbers 对象的变化

复制代码
watch: {
    // 专门监听 numbers.a 的变化
    'numbers.a': {
        handler(newValue, oldValue) {
            console.log(newValue, oldValue);
            console.log('number.a累加');
        }
    },
    
    // 监听整个 numbers 对象的变化
    numbers: {
        deep: true,  // 深度监听对象内部的变化
        handler(newValue, oldValue) {
            console.log(newValue, oldValue);
            console.log('监测a,b的变化。');
        }
    }
}

监听嵌套属性 ('numbers.a')

使用点号表示法可以监听嵌套对象的属性

只有当 numbers.a 的值发生变化时才会触发 handler

不需要 deep: true,因为它只监听特定属性

监听整个对象 (numbers)

numbers 对象本身被重新赋值时,或者对象内部的任何属性(包括嵌套属性)发生变化时都会触发

deep: true 是必需的,否则只会监听对象引用的变化,而不会监听对象内部属性的变化

deep 选项

当设置为 true 时,Vue 会递归监听对象内部所有属性的变化

默认是 false(浅层监听)

注意事项

如果属性路径写错(如 'number.a' 而不是 'numbers.a'),Vue 不会报错,但侦听器不会生效

深度监听 (deep: true) 会带来性能开销,应谨慎使用

5.完整写法和简写

watch 完整写法和简写

复制代码
watch:{
                完整写法
                'ishot':{
                    immediate:true,//初始化时让handler调用一下,及时刚刷新好,那个会输出
                    handler(newValue,oldValue){
                            console.log(newValue,oldValue)
                            console.log('ishot被监视了,并且修改了')
                    }
                },
                简写
                ishot(newValue,oldValue){
                    immediate:true,//失效
                    console.log(newValue,oldValue)
                    console.log('ishot被监视了,并且修改了')
                }
}

vm.$watch 完整写法和简写

复制代码
 vm.$watch('ishot',{
            immediate:true,//初始化时让handler调用一下,及时刚刷新好,那个会输出
                handler(newValue,oldValue){
                        console.log(newValue,oldValue)
                        console.log('ishot被监视了,并且修改了')
                }
        });
        //简写
        vm.$watch('ishot',function(newValue,oldValue){
            console.log(newValue,oldValue)
            console.log('ishot被监视了,并且修改了')
            
 });

简写形式可以将handler当中的代码写入简写方式方法。但是不能将配置比如:immediate:true写入简写的方法。

三.computed和watch之向的区别

computed和watch之向的区别

1.computed能完成的功能,watch都可以完威。

2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的小原则:

1.所被Vue管理的的数,最好写成普通函数,这样this的指向才是vm或组件实例对象。

2.所有不被Vue所管理的的数(定时器的回调的数、ajax的回调数等),最好写成箭头的数,这样this的指向才是vm或组件实例对象。

小贴士

1.一些特定的函数和写法会被 Vue 的响应式系统自动管理

1. 回调函数(Methods)

Vue 会自动管理在 methods 选项中定义的函数,使其内部的 this 指向当前组件实例,并确保它们能访问响应式数据。

2. 计算属性(Computed)的 Getter/Setter

computed 中定义的函数会被 Vue 自动转换为响应式的 getter/setter,依赖的响应式数据变化时会触发重新计算。

3. 侦听器(Watch)的回调

watch 中定义的回调函数会被 Vue 管理,能访问组件实例,并在依赖变化时触发。

4. 生命周期钩子

Vue 内置的生命周期钩子(如 createdmounted)会被自动调用,函数内的 this 指向组件实例。

5. 简写的箭头函数问题

⚠️ 注意 :如果使用箭头函数(如 methods: { handleClick: () => {} }),this 不会指向组件实例,因为箭头函数绑定父级上下文。Vue 无法正确管理此类函数。

2.计算属性的核心特性?

立即返回值:计算属性必须是一个同步函数,直接返回一个值。

缓存机制:只有当依赖的响应式数据变化时,计算属性才会重新计算,否则直接返回缓存的结果。

纯函数:计算属性不应有副作用(如修改外部状态、发起异步请求等)。

3.为什么计算属性不能包含异步操作?

设计限制 :计算属性的返回值必须是一个确定的值,而异步操作(如 setTimeout 或 API 请求)会导致返回值是 undefined 或一个 Promise,这与计算属性的同步特性冲突。

缓存失效:异步操作的非确定性(如网络延迟)会破坏计算属性的缓存机制,导致无法预测何时更新。

虽然 watch 的回调函数本身是由 Vue 管理的(例如,自动绑定 this 上下文),但如果你在 watch 的回调函数中使用定时器(如 setTimeout),这些定时器是由 JavaScript 引擎的事件循环机制管理的,而不是直接由 Vue 管理。

4.watch 回调由 Vue 管理

Vue 会确保 watch 的回调函数中的 this 指向当前组件实例。

Vue 会自动追踪回调函数中使用的响应式依赖。

相关推荐
小墨宝24 分钟前
js 生成pdf 并上传文件
前端·javascript·pdf
HED39 分钟前
用扣子快速手撸人生中第一个AI智能应用!
前端·人工智能
DN金猿43 分钟前
使用npm install或cnpm install报错解决
前端·npm·node.js
丘山子44 分钟前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
志存高远661 小时前
Kotlin 的 suspend 关键字
前端
www_pp_1 小时前
# 构建词汇表:自然语言处理中的关键步骤
前端·javascript·自然语言处理·easyui
YuShiYue1 小时前
pnpm monoreop 打包时 node_modules 内部包 typescript 不能推导出类型报错
javascript·vue.js·typescript·pnpm
天天扭码2 小时前
总所周知,JavaScript中有很多函数定义方式,如何“因地制宜”?(ˉ﹃ˉ)
前端·javascript·面试
一个专注写代码的程序媛2 小时前
为什么vue的key值,不用index?
前端·javascript·vue.js
vvilkim2 小时前
React 与 Vue:两大前端框架的深度对比
vue.js·react.js·前端框架