暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【Vue系列4】—— 监视属性侦听器

酉时Coding课堂 2021-11-26
467
上节我们说了Vue的计算属性,本篇介绍一下 监视属性 我们可以使用watch来监听指定数据的变换,进而调用对应的逻辑处理数据,嗯......有的读者可能就会问了,计算属性就是获取数据的计算结果,这个监视属性好像有点像呀!不慌我们先看监听属性怎么实现,再对比它们的区别。

监视属性实现


<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
<input type="text" v-model="fullName" />
</div>
</body>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el: "#app",
data: {
firstName: "A",
lastName: "B",
fullName: "AB"
},
// 监视属性
watch: {
firstName(value) {
this.fullName = value + this.lastName
},
lastName(value) {
this.fullName = this.firstName + value
}
}
})
</script>
</html>


运行结果如下


就是三个输入框,前两个可以用户填写内容,最后一个来显示前两个输入框拼接而成的内容,其中就是使用 v-model 实现的一个双向绑定 


而计算属性的写法是这样的:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="text" v-model="firstName" />
<input type="text" v-model="lastName" />
<input type="text" v-model="fullName" />
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
const app = new Vue({
el: "#app",
data: {
firstName: "A",
lastName: "B"
},
computed: {
fullName() {
return this.firstName + " " + this.lastName;
}
}
})
</script>
</html>


实现的效果相同,看两者的代码,发现我们使用计算属性来说好像更合适,答案也确实是的,无论代码量还是代码格式,计算属性都要更优。



虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的监视器。这就是为什么 Vue 通过 watch
 选项提供了一个更通用的方法,响应数据的变化。当数据变化时执行异步或开销较大的操作,这个方式是最有用的。

我们看一下下边的例子:我们提出一个问题,通过ajax发送异步请求,之后通过线上问题库获取答案。
<div id="watch-example">
<p>
    输入一个肯定或者否定的问题:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>


<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。-->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
    answer'请提问,否则我无法给出答案!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = '等你停止打字才可给出答案...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
        this.answer = '问题是包含?号的. ;-)'
return
}
this.answer = '思考中...'
var vm = this
// 发送异步请求
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
          vm.answer = '错误无法访问接口! ' + error
})
}
}
})
</script>

执行效果如下:

PS:这接口竟然不识别中文,怀疑人生一秒钟!


以上案例如果使用计算属性怎么能有这么良好的交互呢?这就是监听属性的用武之地


1、当数据变化时执行异步或开销较大的操作时,使用监听属性

2、在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。


计算属性


  1. 支持缓存,只有依赖数据发生改变,才会重新进行计算

  2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化

  3. computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值

  4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed

  5. 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。


监视属性watch

  1. 不支持缓存,数据变,直接会触发相应的操作;

  2. watch支持异步;

  3. 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

  4. 当一个属性发生变化时,需要执行对应的操作;一对多;

  5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,

    1. immediate:组件加载立即触发回调函数执行,

    2. deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。

    注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。


    END

文章转载自酉时Coding课堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论