Vue.js中关于侦听器(watch)的高级用法示例


Posted in Javascript onMay 02, 2018

Vue侦听器watch

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

<div id="watch-example">
<p>
Ask a yes/no question:
<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: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
},
methods: {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
getAnswer: _.debounce(
function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this // this重定向
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
},
// 这是我们为判定用户停止输入等待的毫秒数
500
)
}
})
</script>

侦听器(watch)的高级用法

假设有如下代码:

<div>
  <p>FullName: {{fullName}}</p>
  <p>FirstName: <input type="text" v-model="firstName"></p>
</div>
new Vue({
 el: '#root',
 data: {
 firstName: 'Dawei',
 lastName: 'Lou',
 fullName: ''
 },
 watch: {
 firstName(newName, oldName) {
  this.fullName = newName + ' ' + this.lastName;
 }
 } 
})

上面的代码的效果是,当我们输入firstName后,wacth监听每次修改变化的新值,然后计算输出fullName。

handler方法和immediate属性

这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算。那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?我们需要修改一下我们的 watch 写法,修改过后的 watch 代码如下:

watch: {
 firstName: {
 handler(newName, oldName) {
  this.fullName = newName + ' ' + this.lastName;
 },
 // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
 immediate: true
 }
}

注意到handler了吗,我们给 firstName 绑定了一个handler方法,之前我们写的 watch 方法其实默认写的就是这个handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。

而immediate:true代表如果在 wacth 里声明了 firstName 之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行。

deep属性

watch 里面还有一个属性 deep,默认值是 false,代表是否深度监听,比如我们 data 里有一个obj属性:

<div>
  <p>obj.a: {{obj.a}}</p>
  <p>obj.a: <input type="text" v-model="obj.a"></p>
</div>
new Vue({
 el: '#root',
 data: {
 obj: {
  a: 123
 }
 },
 watch: {
 obj: {
  handler(newName, oldName) {
   console.log('obj.a changed');
  },
  immediate: true
 }
 } 
})

当我们在在输入框中输入数据视图改变obj.a的值时,我们发现是无效的。受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

默认情况下 handler 只监听obj这个属性它的引用的变化,我们只有给obj赋值的时候它才会监听到,比如我们在 mounted事件钩子函数中对obj进行重新赋值:

mounted: {
 this.obj = {
 a: '456'
 }
}

这样我们的 handler 才会执行,打印obj.a changed。

相反,如果我们需要监听obj里的属性a的值呢?这时候deep属性就派上用场了!

watch: {
 obj: {
 handler(newName, oldName) {
  console.log('obj.a changed');
 },
 immediate: true,
 deep: true
 }
}

deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler。

优化,我们可以是使用字符串形式监听。

watch: {
 'obj.a': {
 handler(newName, oldName) {
  console.log('obj.a changed');
 },
 immediate: true,
 // deep: true
 }
}

这样Vue.js才会一层一层解析下去,直到遇到属性a,然后才给a设置监听函数。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Javascript中各种trim的实现详细解析
Dec 10 Javascript
js简单实现Select互换数据的方法
Aug 17 Javascript
如何实现JavaScript动态加载CSS和JS文件
Dec 28 Javascript
JavaScript使用DeviceOne开发实战(四)仿优酷视频应用
Dec 02 Javascript
小心!AngularJS结合RequireJS做文件合并压缩的那些坑
Jan 09 Javascript
javascript使用btoa和atob来进行Base64转码和解码
Mar 20 Javascript
详解require.js配置路径的用法和css的引入
Sep 06 Javascript
Angular弹出模态框的两种方式
Oct 19 Javascript
vue组件实现可搜索下拉框扩展
Oct 23 Javascript
vue日历/日程提醒/html5本地缓存功能
Sep 02 Javascript
基于js实现复制内容到操作系统粘贴板过程解析
Oct 11 Javascript
Vue使用screenfull实现全屏效果
Sep 17 Javascript
Vue SSR 组件加载问题
May 02 #Javascript
基于jquery实现左右上下移动效果
May 02 #jQuery
关于Vue在ie10下空白页的debug小结
May 02 #Javascript
解析Json字符串的三种方法日常常用
May 02 #Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
May 02 #Javascript
vue中的模态对话框组件实现过程
May 01 #Javascript
vue如何通过id从列表页跳转到对应的详情页
May 01 #Javascript
You might like
色色整理的PHP面试题集锦
2012/03/08 PHP
PHP使用静态方法的几个注意事项
2014/09/16 PHP
在云虚拟主机部署thinkphp5项目的步骤详解
2017/12/21 PHP
Laravel 加载第三方类库的方法
2018/04/20 PHP
php中文语义分析实现方法示例
2019/09/28 PHP
laravel model模型处理之修改查询或修改字段时的类型格式案例
2019/10/17 PHP
js中几种去掉字串左右空格的方法
2006/12/25 Javascript
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
js单独获取一个checkbox看其是否被选中
2014/09/22 Javascript
jQuery中offset()方法用法实例
2015/01/16 Javascript
JS如何设置cookie有效期为当天24点并弹出欢迎登陆界面
2016/08/04 Javascript
Bootstrap 模态框实例插件案例分析
2016/12/28 Javascript
JQuery和HTML5 Canvas实现弹幕效果
2017/01/04 Javascript
boostrapTable的refresh和refreshOptions区别浅析
2017/01/22 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
2017/10/24 Javascript
在 webpack 中使用 ECharts的实例详解
2018/02/05 Javascript
Postman的下载及安装教程详解
2018/10/16 Javascript
node Buffer缓存区常见操作示例
2019/05/04 Javascript
vue router 跳转时打开新页面的示例方法
2019/07/28 Javascript
vue分页插件的使用方法
2019/12/25 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
关于Keras模型可视化教程及关键问题的解决
2020/01/24 Python
python MultipartEncoder传输zip文件实例
2020/04/07 Python
python speech模块的使用方法
2020/09/09 Python
Urban Outfitters德国官网:美国跨国生活方式零售公司
2018/05/21 全球购物
size?丹麦官网:英国伦敦的球鞋精品店
2019/04/15 全球购物
NYX Professional Makeup俄罗斯官网:世界知名的化妆品品牌
2019/12/26 全球购物
进程的查看和调度分别使用什么命令
2015/03/25 面试题
土木工程专业大学毕业生求职信
2013/10/13 职场文书
会计电算化应届生求职信
2013/11/03 职场文书
创业融资计划书
2014/04/25 职场文书
县委常委班子对照检查材料思想汇报
2014/09/28 职场文书
雨花台导游词
2015/02/06 职场文书
2016秋季运动会前导词
2015/11/25 职场文书
JavaScript实现复选框全选功能
2021/04/11 Javascript
解决numpy数组互换两行及赋值的问题
2021/04/17 Python