vue设计的初衷:
1.将视图view的状态和行为抽象化,使得UI和业务逻辑分开
2.mvvm:model=>view=>viewmodel
数据响应式原理
数据变更能够在视图中,就是数据响应式。vue2中利用Object.defineProperty()实现实时变化检测
1、数据响应式:监听数据变化并在视图中更新
// 实现defineReactive数据响应式
function defineReactive(obj, key, val) {
// 如果当前的值是obj那么继续递归
// 解决多层嵌套问题
observe(val)
Object.defineProperty(obj, key, {
get() {
console.log('get', key)
return val
},
set(newVal) {
if (newVal !== val) {
console.log('set', key, newVal)
// 为了防止重新对已经绑定的值再次重新赋值
observe(val)
// 赋值
val = newVal
}
}
})
}
// 遍历obj所有的key 对所有属性绑定响应式
function observe(obj) {
if (typeof obj !== 'object' || obj === null) {
return
}
// 遍历所有的key,做响应式处理
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
// $set方法转发defineReactive
function set(obj, key, val) {
defineReactive(obj, key, val)
}
// 绑定数据
const obj = {
foo: 'foo',
bar: 'bar',
data: {
a: 1,
c: {
h: 19999
}
}
}
observe(obj)
// 以下是修改值和赋值一些操作测试
// 有了以上封装好的方法后 下面修改对象obj就可以实现数据响应效果
obj.foo = '牛逼绑定1'
obj.bar = '牛逼绑定2'
obj.data.a = '哈哈哈哈哈'
obj.data.c.h = '多层递归监听到了没'
// 重新赋值对象
// defineReactive方法中重新调用observe方法递归实现绑定响应式
obj.data = {
k: '重新赋值'
}
// 无法拦截直接添加新的属性
// 需要重新调用defineReactive设置值解决
// vue中使用的$set的方法其实就是调用defineReactive再次设置响应式值
obj.foo1 = '动态值1'
console.log(obj.foo1)
// 这种是可以实现响应式绑定的
set(obj, 'foo2', '动态值2')
console.log(obj.foo2)
defineReactive实现数据响应式在html的应用实例
xx.html
<div id="app"></div>
<script>
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('get', key)
return val
},
set(newVal) {
if (newVal !== val) {
console.log('set', key, newVal)
val = newVal
updated()
}
}
})
}
// 测试
const obj = {}
defineReactive(obj, 'foo', '')
setInterval(() => {
obj.foo = new Date().toLocaleTimeString()
}, 1000)
// 更新函数
function updated() {
app.innerHTML = obj.foo
}
</script>
最终可以看到时间视图不断在更新