浅谈vue设计核心 01-数据响应式
2021-09-28 本文已影响0人
江川哇
vue的设计核心是 mvvm
mvvm的核心三要素:数据响应式、 模板引擎、 渲染
1、数据响应式:监听数据变化并且在视图中更新,vue中利用Object.defineProperty()实现变更检测
Object.defineProperty()
Proxy
简单实现:
const obj = {}
function definePropery(obj,key,val) {
Object.definePropery(obj,key,{
get() {
console.log('get',val)
}
set(newval) {
if(newval!=val) {
val = newval
}
}
})
}
definePropery(obj,'foo','foo')
obj.foo
obj.foo='fooooooo'
结合视图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
<script>
function defineReactive(obj,key,{
get(val) {
return val
}
set(newval) {
if(val!=newval) {
val = newval
update()
}
}
})
defineReactive(obj,'foo','')
obj.foo = new Date().toLocaleTimeString()
function update() {
app.innetText = obj.foo
}
setInterval (()=>{
obj.foo = new Date().toLocaleTimeString()
},1000)
</script>
</body>
</html>
遍历要响应的对象
//对象响应化,遍历每个key,定义getter setter
function observe(obj) {
if(typeof obj !='object' || obj==null) {
return
}
Object.keys(obj).forEach(key=>{
defineReactive(obj,key,obj[key])
})
}
const obj = {foo:'foo',bar:'bar',baz:{a:1}}
obj.foo
obj.foo = 'fff'
obj.bar
obj.bar = 'barrrrrr'
obj.baz.a = 2 //嵌套对象no ok
解决嵌套对象 用递归
function defineReactive(obj,key,val) {
observe(val)
Object.defineProperty(obj,key,{
//...
})
}
解决赋值是对象的情况
obj.baz = {a:1}
obj.baz.a = 10 //no ok
set(newval) {
if(newval!=val) {
observe(newval) //新值是对象的情况
notifyUpdate()
}
}
解决添加/删除新属性无法检测 类似vue的$set
obj.dong = 'dong'
obj.dong //并没有get信息
function set(obj,key,val) {
difineReactive(obj,key,val)
}
//测试
set(obj,'dong','dong')
obj.dong
完整代码
//对象响应式原理
//1 Object.defineProperty()
function defineReactive(obj, key, val) {
//val 可能是对象,需要递归处理
observe(val)
Object.defineProperty(obj, key, {
get() {
console.log('get', val)
return val
},
set(newval) {
if (newval != val) {
observe(newval)
console.log('set', newval)
val = newval
}
},
})
}
//对象响应式处理
function observe(obj) {
//判断obj类型必须是对象
if (typeof obj != 'object' || obj == null) {
return
}
Object.keys(obj).forEach((key) => defineReactive(obj, key, obj[key]))
}
//设置新的属性 类似$set
function set(obj, key, val) {
defineReactive(obj, key, val)
}
const obj = { name: 'aa', age: 11, baz: { a: 1 } }
observe(obj)
// obj.name
// obj.name = 'fffff'
//1 对象嵌套 就用到了递归,在defineReactive 里面再调用一次 observe(val)
// obj.baz.a
//2 这种情况 在set里面再调用一次observe(val)
//obj.baz={a:10}
//3 设置新的obj属性 类似$set
set(obj, 'dong', 'dong')
obj.dong
2、模板引擎:提供描述视图的模板语法
插值:{{}}
指令: v-bind v-on v-for v-if v-model
3、渲染:如何将模板转换成html
模板=> vdom =>dom