Vue----watch监测数据变化

本文详细介绍了Vue.js中Watch特性的使用方法及其应用场景。包括基本的普通数据监听、数组变化监听、对象属性监听等内容,并提供了如何正确监听对象新增属性的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.为什么要用 watch
当某些数据一旦发生变化,我们就想要采取某种措施时使用
示例

当 price 一旦发生变化时,我们想要计算出 priceDifferences
<template>
    <div class="watch">
        <h2>{{price}}</h2>
        <h2>{{priceDifferences}}</h2>
        <button @click="addprice">price *2</button>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                priceDifferences:0,
                price:100
            }
        },
        watch:{
            price:function(newVal,oldValue){
                this.priceDifferences = newVal - oldValue
                console.log(this.priceDifferences)
            }
        },
        methods:{
            addprice(){
                this.price =  this.price *2 
            }
        }
    }
</script>

二.watch的用法

1.普通监听(data 里的普通数据)

<template>
    <div class="watch">
        <div>{{msg}}</div>
        <button @click="changemsg">changemsg</button>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                msg:'这是一个普通监听'
            }
        },
        watch:{
            msg:function(newval,oldval){
                console.log('由',oldval,'到',newval)
            }
        },
        methods:{
            changemsg(){
                this.msg = "嘿嘿嘿,是不是监听到了呢"
            }
        }
    }
</script>

运行结果
点击前
在这里插入图片描述
点击后
在这里插入图片描述
控制台输出
在这里插入图片描述
2.监听数组

<template>
    <div class="watch">
        <div v-for="(a,aindex) in arr" :key="aindex">{{a}}</div>
        <button @click="changearr">changearr</button>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                arr:[1,2,3]
            }
        },
        watch:{
            arr:{
                handler:function(newVal){
                    console.log('arr newVal',newVal)
                }
            }
        },
        methods:{
            changearr(){
                this.arr = this.arr.reverse();
            }
        }
    }
</script>

运行结果
点击前
在这里插入图片描述
点击后
在这里插入图片描述
控制台输出
在这里插入图片描述
3.监听对象
监听对象时有两种方法:

1)
obj:{
   handler:function(newVal){
   console.log('newVal',newVal)
  },
   deep:true
}
2)
'obj.course':function(newval,oldval){
	console.log("这是第二种监测方法",newval)
 }
完整的代码
<template>
    <div class="watch">
        <h1>{{obj.name}}</h1>
        <h2>{{obj.age}}</h2>
        <div>{{obj.sex}}</div>
        <h3 v-for="(cou,couindex) in obj.course" :key="couindex">{{cou}}</h3>
        <button @click="addAge">age ++</button>
        <button @click="changeCourse">change course</button>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                obj:{
                    course:{
                        one:'chinese',
                        two:'english',
                        three:'math'
                    }
                }
            }
        },
        watch:{
        //第一种方法
            obj:{
                handler:function(newVal){
                    console.log('newVal',newVal)
                },
                deep:true
            },
            //第二种方法
            'obj.course':function(newval,oldval){
                console.log("这是第二种监测方法",newval)
            }
        },
        methods:{
        		changeCourse(){
                this.obj.course = {
                    one:'语文',
                    two:'英语',
                    three:'数学'
                }
            }
        }
    }
</script>

运行结果
点击前
在这里插入图片描述
点击后
在这里插入图片描述
控制台输出
在这里插入图片描述
注意:当监听对象时 增加属性时监测不到,因为该属性没有在 data 里注册,不是响应式的
解决办法:Vue.set(object, key, value)或者vm.$set方法(全局 Vue.set 方法的别名)

<template>
    <div class="watch">
        <h1>{{obj.name}}</h1>
        <h2>{{obj.age}}</h2>
        <div>{{obj.sex}}</div>
        <h3 v-for="(cou,couindex) in obj.course" :key="couindex">{{cou}}</h3>
        <button @click="addsex">addsex</button>
    </div>
</template>
<script>
    export default{
        data(){
            return{
                obj:{
                    name:'lily',
                    age:'23',
                    course:{
                        one:'chinese',
                        two:'english',
                        three:'math'
                    }
                }
            }
        },
        watch:{
            obj:{
                handler:function(newVal){
                    console.log('newVal',newVal)
                },
                deep:true
            }
        },
        methods:{
            addsex(){
            //监测不到,控制台不会打印改变后的值
            // this.obj.sex = "female" 
            //使用 $set 之后可以监测到值
                this.$set(this.obj,'sex','female')
            }
        }
    }
</script>

运行结果
点击前
在这里插入图片描述
点击后
在这里插入图片描述
控制台输出
在这里插入图片描述

<think>嗯,用户想用vue-virtual-scroller在聊天页面实现高效滚动效果。首先,我需要回顾一下这个库的基本用法。根据引用内容,这个库有三个组件:RecycleScroller、DynamicScroller和DynamicScrollerItem。聊天消息的高度可能不固定,比如有的消息长,有的短,还可能包含图片,所以应该用DynamicScroller来处理动态高度的情况。 接下来,我需要确认如何在Vue3项目中正确导入和使用这些组件。引用里提到在main.ts中导入并注册,但用户可能需要局部导入。不过,通常组件库推荐全局注册,这样使用起来更方便。然后,用户需要设置虚拟滚动的容器,确保高度正确,否则滚动可能不会生效。这时候需要检查CSS样式,比如设置容器的高度为固定值,并启用overflow-y: auto。 然后是数据绑定的部分,聊天消息通常是一个数组,需要传递给items属性。DynamicScroller必须搭配DynamicScrollerItem使用,每个消息项需要用scoped slot来渲染,并且要设置size和key。这里需要注意,key必须是唯一的,通常用消息的id,而size可以是动态计算的高度,或者使用自动高度检测。 性能优化方面,可能需要分页加载数据,避免一次性加载过多消息。结合触底事件来加载更多数据,这时候需要监听scroll事件,判断是否滚动到底部。另外,保持滚动位置的稳定,特别是在新消息到来时,可能需要自动滚动到底部,但如果有用户向上查看历史消息,则不应自动跳转,这需要逻辑控制。 最后,用户可能需要具体的代码示例,包括模板结构、数据绑定和事件处理。同时,常见问题如高度计算不正确、滚动跳动、数据更新问题,都需要在回答中提及解决方案。比如使用observe-dom来监测高度变化,或者确保数据更新的方法正确调用。 现在需要将这些思考整理成步骤,确保结构清晰,同时引用相关的文档内容。可能还需要提醒用户注意版本兼容性,以及检查依赖是否正确安装。另外,动态高度可能需要更多的计算资源,适当优化减少不必要的渲染。</think>### 使用 vue-virtual-scroller 实现聊天页面滚动效果的步骤 #### 1. **组件选择与配置** 聊天页面的消息通常高度不固定(如文字、图片混合),需使用 **DynamicScroller** 组件[^1]。配置时需注意: - 安装依赖:`npm install vue-virtual-scroller` - 全局注册组件(推荐在 `main.ts` 中): ```typescript import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' import VueVirtualScroller from 'vue-virtual-scroller' app.use(VueVirtualScroller) ``` #### 2. **基础模板结构** ```html <DynamicScroller :items="chatMessages" :min-item-size="40" // 最小高度预估值 class="scroller-container" @scroll="handleScroll" > <template v-slot="{ item, index, active }"> <DynamicScrollerItem :item="item" :active="active" :size-dependencies="[item.content]" // 依赖变化时重新计算高度 > <div class="message-bubble"> {{ item.content }} </div> </DynamicScrollerItem> </template> </DynamicScroller> ``` #### 3. **关键配置参数** | 参数 | 说明 | 示例值 | |------|------|--------| | `:items` | 绑定的消息数组 | `chatMessages: Message[]` | | `:min-item-size` | 动态高度的最小预估 | `40`(单位:px) | | `key-field` | 唯一标识字段名(默认`id`) | `id` | | `page-mode` | 启用原生滚动条 | `true`(适合全屏) | #### 4. **性能优化技巧** - **分页加载**:结合滚动触底事件动态加载历史消息 ```typescript const handleScroll = (e: Event) => { const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLElement if (scrollHeight - (scrollTop + clientHeight) < 50) { loadMoreMessages() } } ``` - **自动滚动**:新消息到达时自动到底部(需判断是否已在底部) ```typescript watch(() => chatMessages.length, (newVal, oldVal) => { if (newVal > oldVal) { nextTick(() => { scrollerRef?.scrollToBottom() }) } }) ``` #### 5. **样式要求** ```css .scroller-container { height: 80vh; /* 必须设置固定高度 */ overflow-y: auto; } .message-bubble { margin: 8px; padding: 12px; background: #f0f0f0; border-radius: 12px; } ``` #### 6. **常见问题解决** - **高度计算不准确**:添加 `observe-dom` 插件监测DOM变化 ```javascript import { observeDom } from 'vue-virtual-scroller' app.use(observeDom) ``` - **滚动跳动**:确保 `:min-item-size` 接近实际最小高度 - **数据更新问题**:使用 `Vue.set` 或响应式数组方法更新数据 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值