面试官:请你简单的说说什么是Vue的响应式。
小明:mvvm就是视图模型模型视图,只有数据改变视图就会同时更新。
面试官:说的很好,回去等通知吧。
小明:....
Vue响应式原理
先看官方的说法
简单理解就是实例data,Vue通过遍历data中所有对象通过Observer劫持监听所以属性,然后数据一旦发生变化,就通知编译解析变化,更新视图。
首先创建一个data,需要将data变成响应式数据,创建Observer 函数传值data,如果data不是一个对象或者是空就不用处理直接return
<script>
function Observer(targer){
if(typeof targer !== 'object' || targer ===null){
return targer
}
}
const data = {
name:'海海',
age:18,
info:{
address:'广州'
},
fava:[1,2,3,4,5]
}
Observer(data)
</script>
其他的处理
这里只处理数组,其他
判断是否等于数组,如果等于,如果不等于就循环target,声明响应式函数 defineReactive
传值targer,循环的key和targer[key],然后在?defineReactive调用我们的?Object.defineProperty
function Observer(targer){
if(typeof targer !== 'object' || targer ===null){
return targer
}
if(Array.isArray(targer)) {
// 数组
}else{
for(let key in targer){
// 响应式数据的函数
defineReactive(targer,key,targer[key])
}
}
}
Object.defineProperty
? ?(Object.defineProperty() ?方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。)
传入我们的参数
拿到get set方法
get
初始值 直接return 我们的value
set
第一个参数是最新的值 newValue
判断如果我们传入的value和newValue不相等,那么就把newValue赋值给value
function defineReactive(targer,key,value){
Object.defineProperty(targer,key,{
get(){
return value
},
set(newValue){
if(newValue !== value) {
value =newValue
}
}
})
}
?那么问题又来了,如果是一个对象需要监听,我们刚刚的操作只监听到了第一层,如果监听的内容是上面的info就相当于监听了整个对象,答案也很简单,我们只需要在调用defineReactive的时候在调用一次Observer在进入一次循环,当不是object就自动结束了
function defineReactive(targer,key,value){
Observer(value)
Object.defineProperty(targer,key,{
get(){
return value
},
set(newValue){
if(newValue !== value) {
value =newValue
}
}
})
}
视图更新
我们这里在模仿一下视图更新 定义函数 updataView
function updataView(){
console.log('视图更新了')
}
调用
?显示视图更新。
数组
先定义一个值 oldArrayProperty 然后将Array.prototype赋值给oldArrayProperty,
然后针对原型对象创建?Object.create()
定义一个 arrProto 来接收。
然后声明数组? ['push','pop','unshift','shift','reverse','sort','splice']? 进行循环
const oldArrayProperty =Array.prototype
const arrProto = Object.create(oldArrayProperty)
const fn = ['push','pop','unshift','shift','reverse','sort','splice']
fn.forEach((method)=>{
arrProto[method] = function(){
}
})
然后调用更新视图 updataView? return?将oldArrayProperty对应的方法匹配上return出来
const oldArrayProperty =Array.prototype
const arrProto = Object.create(oldArrayProperty)
const fn = ['push','pop','unshift','shift','reverse','sort','splice']
fn.forEach((method)=>{
arrProto[method] = function(){
updataView()
return oldArrayProperty[method].call(this,...arguments)
}
})
然后回到Observer方法中,将arrProto赋值给?targer的__proto__原型链上,最后在将targer循环调用Observer,进行数据更新。
if(Array.isArray(targer)) {
// 数组
targer.__proto__ =arrProto
for(let i=0;i<targer.length;i++) {
Observer(targer[i])
}
}
测试
?到这里我们的监听数据变化并自动更新就完成了。
完整代码
<script>
function defineReactive(targer,key,value){
Observer(value)
Object.defineProperty(targer,key,{
get(){
return value
},
set(newValue){
if(newValue !== value) {
value =newValue
updataView()
}
}
})
}
const oldArrayProperty =Array.prototype
const arrProto = Object.create(oldArrayProperty)
const fn = ['push','pop','unshift','shift','reverse','sort','splice']
fn.forEach((method)=>{
arrProto[method] = function(){
updataView()
return oldArrayProperty[method].call(this,...arguments)
}
})
function Observer(targer){
if(typeof targer !== 'object' || targer ===null){
return targer
}
if(Array.isArray(targer)) {
// 数组
targer.__proto__ =arrProto
for(let i=0;i<targer.length;i++) {
Observer(targer[i])
}
}else{
for(let key in targer){
// 响应式数据的函数
defineReactive(targer,key,targer[key])
}
}
}
function updataView(){
console.log('视图更新了')
}
const data = {
name:'海海',
age:18,
info:{
address:'广州'
},
fava:[1,2,3,4,5]
}
Observer(data)
</script>
如果你还有什么问题你可以选择↓↓↓
http://img.haihaina.cn/qr.jpg
|