http://jsrun.net/Sz3Kp/edit?m...
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
{{formModel}}
<el-input v-model="formModel.a"></el-input>
<el-input v-model="formModel.b"></el-input>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data: function() {
return {
formModel: {
}
}
},
created() {
this.formModel = {}
// 只写上面可以,但是一旦这样写就没法输入,或者说只能读取上一次的值
// 既然vue官网说了这样写不会绑上getter setter那为何formModel里又有值
this.formModel.a = 'a' // 这行注释了就能输入
// 为啥formModel里啥都不写,直接v-model="formModel.x"又能直接被绑上呢?
}
})
</script>
</html>
为了了解为什么在created里面给formModel的a属值赋值以后,就导致a属性不具有响应式的效果以后我们得了解实际运行时组件的代码是怎样的
我们将上面的代码用Vue.complie编译得到该组件的渲染函数
上面的函数就是组件真正运行时的代码,现在我们可以去掉模板在页面中添加一下代码就可以将组件直接渲染出来了
可以看到vue自动给input添加一个
v-model
指令我们再看看vue的
v-model
指令都干了些什么vue的v-model指令为dom注册了onchange事件,并且dispatch了一个input事件,而和v-model指令一样,input的监听函数vue也会自动添加,这就能理解说为什么
v-model
是个语法糖了可以看到关键代码
$set(formModel, 'b', $event.target.value)
到这里我们就知道即使不用手动给formModel$set
属性,formModel在使用v-model时formModel上的属性也是响应式属性,因为vue会自己$set
,关键就在于如果在created方法里面如果提前给formModel设置一个非响应式属性比如
this.formModel.a = 'a'
那么后续事件触发时$set
看到已经存在该属性了,就不会帮formModel定义该响应式属性了,就导致该属性的响应式失效明明给他赋了值但没有触发视图更新结论: 要么formModel上的属性一个都不声明,等事件触发时vue会自动声明,或者自己手动声明时用
$set