美文网首页微信小程序开发技术干货JavaScript 进阶营
前端框架响应式简单实现及代码分析

前端框架响应式简单实现及代码分析

作者: 老邵 | 来源:发表于2019-10-21 21:25 被阅读0次
// 只有先执行了依赖收集,才能在属性更新的时候派发更新

class Dep {
constructor() {
    this.subs = []
}
//添加依赖
addSub(sub) {
    this.subs.push(sub)
}
//更新 
notify() {
    this.subs.forEach(sub=>{
        sub.update()
    })
}
}

Dep.target = null

//当需要依赖收集的时候调用 addSub,当需要派发更新的时候调用 notify

//在组件挂载时会先对所有需要的属性调用 Object.defineProperty()
//然后实例化 Watcher,传入组件更新的回调
//在实例化的过程中会对模板的属性进行求值,触发依赖收集

class Watcher {
constructor(obj,key,cb) {
    // 将 Dep.target 指向自己
    // 然后触发属性的 getter 添加监听
    //最后将 Dep.target 置空
    Dep.target = this
    this.cb = cb
    this.obj = obj 
    this.key = key
    this.value = obj[key] //此处触发属性的 getter
    Dep.target = null
}

update() {
    //获取新值
    this.value = this.obj[this.key]
    //调用 update 更新 Dom
    this.cb(this.value)
}
}

//在执行构造函数时将 Dep.target 指向自身,
//从而收集到对应的 Watcher,在派发    更新的时候取出对应的 Watcher,然后执行 update 函数


function observe(obj) {
if(!obj || typeof obj !== 'object'){
    return
}

for(let key in obj) {
    defineReactive(obj,key,obj[key])
}
}

function defineReactive(obj,key,value) {
observe(value)

let dp = new Dep()
Object.defineProperty(obj,key,{
    enumerable:true,
    cinfigurable:true,
    get:function() {
        if(Dep.target) {
            dp.addSub(Dep.target)
        }
        return value
    },
    set:function(newValue) {
        value = newValue
        dp.notify()
    }
})
}

let obj = {a:1}


observe(obj)

new Watcher(obj,'a',function(v) {
//document.querySelector().innerText = v //更新 DOM
console.log("改变DOM")
})

obj.a = 3 //改变 DOM

我将最后一小段代码与上面分开,因为具体过程用最后一小段代码就可以逐步深入的分析。

首先是声明一个对象,这无需多说。

接着,调用 observe 方法,将 obj 作为参数传入。observe 首先判断 obj 是不是对象,遍历对象的键。然后通过 defineReactive 函数为每个对象的属性添加属性描述符,重点是改变每个属性的 getter 和 setter 行为。具体改变了什么行为我们下面再说。

接下来,新建一个 Watcher 对象,参数是对象、属性以及回调函数。这一部分较难理解。需要结合整体来看。新建 Watcher 对象时,首先调用 Watcher 类中的 constructor。其中先设置 Dep.target 为 this,接着代码中的 obj[key] 触发了 key 的 getter 行为。

在属性的 get 方法中,先检测 Dep.target 有没有值,如果有就通过 Dep 实例的 addSub 添加到实例的数组中,这一步叫做依赖收集。如果声明了多个 Watcher,它们都会被添加到这个实例的数组中,形成一个 Watcher 数组。

我们回到 Watcher 对象,这个对象还有一个 update 方法,调用回调函数并将 obj[key] 这个值传入。

最后对 obj.a 进行赋值时,会调用属性的 set 方法,在 set 后的函数中, Dep 实例的 notify 方法调用了 subs 数组中每个 Watcher 的 update 方法,而 update 方法会调用声明 Watcher 时传入的回调,回调中会进行 DOM 节点的更新。

NASA 2015-11-06 10-26-56 .jpg

相关文章

  • 前端框架响应式简单实现及代码分析

    我将最后一小段代码与上面分开,因为具体过程用最后一小段代码就可以逐步深入的分析。 首先是声明一个对象,这无需多说。...

  • MD的web框架之一Materialize(使用)

    Materialize Materialize 是一个响应式的前端框架,设计样式及组件元素丰富。 下面简单介绍一下...

  • Runtime - 基于isa-swizzling实现消息监听,

    前言 在上一篇文章《函数式编程 - 实现响应式框架》中,我实现了一个非常简单小巧的函数式响应式框架,并对它做了与C...

  • Material_Design风格的web框架

    Materialize Materialize 是一个响应式的前端框架,设计样式及组件元素丰富。 Material...

  • Vue响应式原理浅析

    最近在学习前端框架Vue ,对其响应式原理做一些简单的分析 大致原理: 当把一个普通的 JavaScript 对象...

  • 数据响应Object.defineProperty

    背景    前端vue框架大火,面试时经常碰到,数据响应是这么实现的。今天快速简单带你实现数据响应 核心Objec...

  • vue实现数据响应式的过程

    1.怎样更形象的解释vue.js的响应式系统? 在前端框架中,vue.js的灵魂所在就是其“数据响应式”,简单的描...

  • Bootstrap介绍

    Bootstrap是基于HTML、CSS、JavaScript的前端框架 Bootstrap用于响应式前端布局,移...

  • 前端响应式布局简单实现

    这个方法是监控页面大小,设置页面大小的范围,加载不同的css文件 例子如下 例子中设置如果页面大小最大宽度为500...

  • 响应式前端框架

    1. 响应式前端框架 [TOC] 1.1. 什么是响应式开发 wiki上的解释 reactive programm...

网友评论

    本文标题:前端框架响应式简单实现及代码分析

    本文链接:https://www.haomeiwen.com/subject/uqjxvctx.html