观察者模式

模式构成

  • 观察者
    观察者又可称为信息改变后被通知的对象,例如:商品价格改变,通知那些关注此商品的顾客,此时顾客即为观察者。又例如,vue中响应式数据改变后,通知那些依赖做出响应(如:vue中插值表达式{{name}},name改变页面显示的数据也更新,也就是重新更新dom,此时更新dom操作即为观察者),依赖即为观察者
  • 被观察对象
    被观察者即为观察者观察的主体,如上例中的商品为被观察者,上例中的vue的响应式数据也为被观察者。

实现观察者模式

1.商品价格改变例子

class Subject {
    constructor() {
        this.observers = []
    }

    notify(val) {
        this.observers.forEach(observer => observer.update(val))
    }

    add(observer) {
        this.observers.push(observer)
    }

    remove(observer) {
        this.observers.splice(this.observers.findIndex(observer), 1)
    }

}

class Watcher {

    constructor() {}

    update(val) {
        console.log(`数据改变了${val}`)
    }
}

class Goods {
    _price = ''

    priceWatcher = null

    constructor() {
        this.priceWatcher = new Subject()
    }

    set price(val) {
        this._price = val

        this.priceWatcher.notify(val)
    }

    get price() {
        return this._price
    }

    addPriceWatcher(watcher) {
        this.priceWatcher.add(watcher)
    }
}

function focusPrice(good) {
    const watcher = new Watcher()

    good.addPriceWatcher(watcher)
}

2.vue中数据改变插值表达式例子

function defineReactive(obj, key, val) {
    const subject = new Subject()

    Object.defineProperty(obj, key, {
        get() {

            Subject.target && subject.add(Subject.target)

            return val
        },
        set(newVal) {
            console.log(newVal , val)
            if(newVal !== val) {
                val = newVal

               subject.notify() 
            }
        }
    })
}

// 主体
class Subject {
    constructor() {
        this.observers = []
    }
    
    add(dep) {
        this.observers.push(dep)
    }

    notify() {
        this.observers.forEach(dep => {
         
            dep.update()
        })
    }
}

class Watcher {
    constructor(vm, key, updateFn) {
        this.vm = vm

        this.key = key

        this.updateFn = updateFn

        Subject.target = this

        this.vm[this.key] // 触发get 收集依赖

        Subject.target = null

    }

    update() {
        console.log(this.vm, 'update')
        this.updateFn.call(this.vm, this.key)
    }
}

// 渲染

const obj = {time: Date.now()}

function compileText(node) {

    const reg = /\{\{(.+)\}\}/

    const textContent = node.textContent


    if(reg.test(textContent)) {

        const key =  RegExp.$1

        renderText(node, obj, key)
        
        new Watcher(obj, key, function(exp) {
         
            renderText(node, obj, exp)
        })
    }
}

function renderText(node, vm, exp) {
    console.log(vm, exp)
    node.textContent = vm[exp]
}

function compile() {
    const node = document.querySelector('#demo')

    compileText(node)
}



Object.keys(obj).forEach((key) => {
    defineReactive(obj, key, obj[key])
})

compile()

setInterval(() => {
    obj.time = Date.now()
}, 1000)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值