设计模式初探:观察者模式,实现微信公众号返回事件的监听。

最近看到了技术公众号的推送文章,js的几大设计模式,闷着头看了一下。阅读大佬们的文章总是很有收货。用科学的方法来设计一个页面逻辑。比自己瞎摸索快速的多。先是仿着写了一个demo,后来碰到问题需要写一写逻辑,也算是刚好用的上。

什么是观察者模式?

Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
了解这个模式之后发现好多框架在设计的时候都用到了这个模式,如:

  1. js 的事件机制 addEventListener
  2. vue的$emit(‘xx’)

demo

<button id='off'>解绑</button>
		class observer {
            constructor() {
                this.events = {}
            }
            on(eventsType, handle) {
                // 订阅事件
                if (!this.events[eventsType]) this.events[eventsType] = []
                this.events[eventsType].push(handle)
            }
            emit(eventsType, ...args) {
                // 触发事件
                if (this.events[eventsType]) {
                    this.events[eventsType].forEach((item, key, arr) => {
                        item.apply(null, args)
                    })
                }
            }
            off(eventsType, handle) {
                // 解除事件
                if (this.events[eventsType]) {
                    this.events[eventsType].forEach((item, key, arr) => {
                        if (item == handle) {
                            this.events[eventsType].splice(key, 1)
                            console.log(eventsType, '解绑成功')
                        }
                    })
                }
            }
        }
        let testFun = function(data) {
            console.log("demo加载好了啊", data)
        }
        // 初始化
        let demo = new observer()
        // 注册事件
        demo.on('ready', testFun)
        setTimeout(() => {
            // 通知
            demo.emit("ready", new Date())
        }, 5000, );
        $("#off").click(function() {
            // 接触绑定
            demo.off("ready", testFun)
        })

问题:

公众号进入之后,页面的返回时返回上一页,但是有些页面不能返回上一层。比如:A=》B=》C ,在C页面的时候,单击返回,就会回到B页面,但是我不想让他去B,在C页面只能返回到A页面,这里就是问题了

解决思路

监听浏览器的返回事件,加上自定义的事件来控制页面的返回逻辑

跟观察者模式有什么关系?

我的理解:观察者模式是一个平台,允许同时存在好几种不同的事件,各自注册各自的,各自触发各自的。在C页面订阅一个返回按钮事件,在首页监听返回按钮触发,然后通知订阅返回事件的各个页面,触发各自的订阅事件。代码如下,公司项目,不方便贴出全部,只是粘贴部分:

// 工具类中写核心注册代码
export class BackEvent {
  constructor() {
    this.handles = {}
  }
  on(eventType, handle) {
    // 订阅事件
    if (!this.handles[eventType]) this.handles[eventType] = []
    this.handles[eventType].push(handle)
  }
  emit(eventType, ...args) {
    // 发布事件
    if (this.handles[eventType]) {
      this.handles[eventType].forEach((item, key, arr) => {
        item.apply(null, args)
      })
    }
  }
  toUrl(url = '', title = '/#/') {
  // 此方法是在页面加载前,往history中push一条数据,在A页面返回时就不会退出页面了
    var state = { title, url }
    window.history.pushState(state, state.title, state.url)
  }
}
// main.js中挂载到vue的prototype中
import { BackEvent } from '@/common/js/index'

Vue.prototype.$backEvent = new BackEvent()
// APP.vue中监听浏览器返回事件,并触发事件
mounted() {
    this.back()
  },
  methods: {
    back() {
      const that = this
      that.$backEvent.toUrl()
      window.addEventListener(
        'popstate',
        function(e) {
        // 此处将router的name当做每个页面的唯一标识,实际使用中可以自定义变量
          that.$backEvent.emit(that.$route.name)
        },
        false
      )
    }
  }
// C页面中 订阅返回事件
mounted() {
    this.$backEvent.on(this.$route.name, () => {
      this.$router.push({
        path: '/home/meeting'
      })
    })
  },

结语

其实不使用这个模式,也能解决问题。或者可能是更简单,比如监听返回事件部分不变,改为触发vuex的变量,然后对应页面watch监听vuex变量来调用自己的返回函数,都能解决。只是这是个方向,实践的第一步,同时,也开辟了这个事件平台,如果再有类似的需求,也可以注册别的事件。方法很多。 设计模式博大精深,还是继续看吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值