计算属性可以根据已有的一个或多个数据,通过同步计算返回一个新的用于显示的数据。在计算数据的依赖数据发生变化时,计算属性函数会重新执行并返回一个新的值进行显示。但有的时候,在依赖数据发生变化时,我们需要让其产生一些“副作用”。例如,直接更新DOM,或者执行异步操作后,更新其他数据。此时我们可以使用Vue的监听语法来实现。
在选项式API中,我们可以通过watch选项配置一个函数来监听某个响应式属性的变化。监听回调函数默认在数据发生变化时回调,且接收新值和旧值两个参数。其语法格式如下。
下面我们利用监听来实现如图2-14所示的页面效果。
图2-14 页面效果
现有两个需求,具体如下。
①输入标题,实时同步显示到页面标题上。
②输入标题,实时AJAX请求获取一个最匹配的问题并显示到输入框下面。
下面我们对需求进行分析:输入的标题可以通过v-model收集到data对象中的title属性上,同时用watch选项来监听title属性的变化,在监听回调函数中将最新的值设置给文档的标题。同时发送AJAX请求,根据title属性获取一个最匹配的问题并设置给data对象中的question属性,显示到输入框下面。
实现代码如下所示。
Vue代码如下。
JavaScript代码如下。
运行代码后,我们在输入框中输入Vue,会发现1秒后显示问题。
其实watch选项不仅可以监听data对象中外部的属性,还可以监听其内部的属性。现有一个person对象,内部有name和age两个属性,我们使用watch选项对name属性进行监听。其语法格式如下。
watch回调默认是在数据发生变化时自动调用,如果我们需要在初始化时就执行一次监听的回调,那么要如何实现呢?
Vue的watch语法也支持这种场景需求,但是用法有些许差别,watch的属性不能再是一个函数了,需要是一个配置对象,并通过handler配置来指定监听回调函数。同时我们可以通过配置immediate为true来指定监听回调函数在初始化过程中执行第1次,当然在被监听数据发生改变时也会执行。
思考下面代码的运行效果。
Vue代码如下。
JavaScript代码如下。
运行代码后,页面上展示了person中的name属性和likes属性,如图2-15所示。
由于我们配置了immediate为true,因此watch的回调在初始化时就会执行1次。我们又通过定时器模拟异步向后台提交请求,即提交当前person的信息数据,如图2-16所示。
图2-15 页面效果(1)
图2-16 模拟异步向后台提交请求(1)
点击“更新人员信息”按钮,直接将当前person更新为一个新的人员对象,监听的回调也会执行,用来模拟异步向后台提交请求,发送最新的人员信息,如图2-17和图2-18所示。
图2-17 点击“更新人员信息”按钮后页面发生变化
图2-18 模拟异步向后台提交请求(2)
watch默认是浅层监听,只有在被监听属性本身发生变化时才会触发回调,它监听不到属性对象内部的数据变化。
对于上面的案例来说,如果只是更新person对象中的内部属性,比如name属性,那么watch的回调就不会执行。
点击“更新人员信息”按钮后,页面上的name属性值会发生改变,但是不会触发watch中的异步操作,因此页面上不会弹出警告提示,如图2-19所示。
图2-19 点击“更新人员信息”按钮后的页面效果
那么如何才能深度监听到对象或数组内任意数据的变化呢?其实可以通过将deep配置为true来实现。也就是说,deep的默认值为false,因此之前watch监听不到内部数据的修改。现在修改一下watch的配置,具体如下。
此时我们再次重复当前的操作,可以发现除了页面发生变化,1秒后还弹出了警告提示,证明此时已经监听到内部数据了,如图2-20所示。
图2-20 模拟异步向后台提交请求(3)
其实,无论是更新person对象的name属性,还是更新person对象中的likes属性,监听的回调都会调用,会将最新的人员信息提交给后台,如下代码所示。
重复点击“更新人员信息”按钮,这次likes属性的数组中新增了一项“atguigu”,这个修改同样被监听到了,也会异步向后台提交数据,如图2-21和图2-22所示。
图2-21 页面效果(2)
图2-22 模拟异步向后台提交请求(4)