# 持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情juejin.cn/post/714765…
在html中监听事件
你可能注意到这种事件监听的方式违背了关注点分离这个长期以来的优良传统。但不必担心,因为所有的vue.js事件处理方式和表达式都严格绑定在当前视图的viewModel上,她不会导致任何维护上的困难,实际上,使用v-on有几个好处:
- 扫一眼HTML模板就能轻松定位在js代码里对应的方法
- 因为你无须在js里手动绑定事件,你的viewModel代码可以是非常纯粹的逻辑,和DOM完全解耦,更易于测试
- 当一个viewModel被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理他们
表单输入绑定(onchange事件也可以)
先做onchange的示例:
vue中可以用v-model指定在表单input/textarea以及select元素上创建双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素。v-model本质上不过是语法糖。他负责监听用户的输入事件已更新数据,并对一些极端场景进行一些特殊处理
注意:
v-model会忽略所有表单元素的value、checked、selected属性的初始值,而总是将vue实例的数据作为数据来源,你应该通过js在组件的data选项中声明初始值
v-model可以传值,组件之间的传值
设置默认值:
实现原理
v-model只不过是一个语法糖而已,真正的实现靠的还是
- v-bind绑定响应式数据
- 触发oninput事件并传递数据
- 例如:
复选框(一个的时候存的是布尔值)
单个复选框,绑定到布尔值
多个复选框,绑定到同一个数组:
.lazy(把事件转成change事件)
只有失去焦点才验证
在默认情况下,v-model在每次input事件触发后将输入框的值与数据进行同步(除了上述输入法组合文字时)。你可以添加lazy修饰符,从而转为change事件以后,进行同步:
.number
如果想自动将用户的输入值转为数值类型,可以给v-model添加number修饰符:
这通常很有用,因为即使在type='number'时,HTML输入元素的值也总会返回字符串,如果这个值无法被parseFloat()解析,则会返回原始的值。
注意:如果输入的不是数值,是不会给转换的
.trim
如果要自动过滤用户输入的首位空白字符,可以给v-model添加trim修饰符。如下:
深入响应式原理
当你吧一个普通的js对象传入vue实例作为data选项,vue将遍历此对象所有的property,并使用Object.defineProperty(es5中的对象的一个方法。作用:直接在一个对象上添加一个新的属性,或修改原来就有的对象上的一个属性)把这些property全部转为getter/setter(取值函数和存值函数(拦截函数))修改和读取就被取值函数he存值函数监听(对用户是来是不可见的)。一修改UI就是更新Object.defineProperty,它是es5中一个无法shim的特性,这也就是vue不支持IE8以及更低版本浏览器的原因。
因为getter/setter对用户来说是不可见的,但是在内部他们让vue能够追踪依赖,在property被访问和修改时通知变更。这里需要之一的是不同浏览器在控制台打印数据对象时对getter/setter的格式化并不同,所以建议安装vue-devtools来获取对检查数据更加友好的用户界面
getter/setter组成一个对象,每个组件实例都对应一个water监听个(函数)实例,它会在组件渲染的过程中吧‘接触’过的数据property记录为依赖。之后当依赖项的setter触发时,会通知water,(调用虚拟dom渲染成真实dom)从而是它关联的组件重新渲染。
异步更新队列
可能你还没有注意到,vue在更新DOM时是异步执行的,只要侦听到数据变化,vue将开启一个队列,并缓冲在同一时间循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作时非常重要的。然后,在下一个的事件循环“tick”中。vue刷新队列并执行实际(已去重)工作。vue在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 this.$nextTick(callback)``(下一次事件轮询的时候进去,操作真实``dom``的方法写在这里,这里确保是更新后)。这样回调函数将在 DOM 更新完成后被调用。例如: