vue 发布订阅模式

为什么要使用发布订阅模式

  • vue 中数据反映到视图中的方式主要是采取声明式渲染+模板编译
    声明式渲染: 例如v-mdoe等指令的形式渲染
    模板编译原理:
  • 简单来讲就是获取app下所有的childNodes
  • 通过循环找到符合的元素节点,node.nodeType === 1
  • 拿到所有元素节点的attributes属性,遍历attributes
  • 其中包括了两个关键属性nodeName、nodeValue
  • 其中nodeName 就是指令:例如v-mode, nodeValue就是v-mode绑定的值如 v-mode=“name” 中的name
  • nodeValue刚好就是data被绑定对象的key,如此 node.innerText = data[arrt.nodeValue] 就建立了连接。
  • 以上有个缺点:多个标签都是用v-mode就会导致,暴力更新的问题,就是不管值有没有改变,统一都更新。
  • 代码
 <div id="app"><!-- <input id="input" v-mode="inputVal" /> --><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span><br /><span v-mode="age"></span><br /></div>let data = {inputVal: 'vue发布订阅模式',age: 15,}// 数据代理const proxyReative = (data) => {observe(data)return new Proxy(data, {get(target, key) {return target[key]},set(target, key, newVal) {if (target[key] === newVal) returntarget[key] = newVal// 执行更新compile()},})}const observe = (data) => {Object.keys(data).forEach((key) => {if (typeof data[key] === 'object') {data[key] = proxyReative(data[key])}})}const vm = proxyReative(data)// 模板编译const compile = () => {const appRef = document.getElementById('app')const childNodes = appRef.childNodeschildNodes.forEach((node) => {// 1 元素节点     3 文本节点if (node.nodeType === 1) {const arrts = node.attributesArray.from(arrts).forEach((arrt) => {if (arrt.nodeName === 'v-mode') {// 初次渲染赋值node.innerText = data[arrt.nodeValue]}})}})}

问题展示

  • 虽然我们只是更新了age的值但由于元素绑定的都是v-mode下面代码会执行,所以都会执行更新操作
if (arrt.nodeName === 'v-mode') {// 初次渲染赋值node.innerText = data[arrt.nodeValue]}

解决暴力更新的问题 — 发布订阅模式

  • 发布订阅模式的核心就是一对多的关系,一个发布者发起事件,所有的订阅者都会执行。
  • 利用这个特性,给每一个v-mode在进行细化,只有v-mode且v-mode=“age”的才进行更新操作
  • 代码
// 发布订阅模式const Dep = {map: {},// 收集事件 eventName:inputVal或者age// 形成的结构 /**map:age: [ƒ]inputVal: Array(4)0: () => {…}1: () => {…}2: () => {…}3: () => {…}*/collect(eventName, callback) {if (!this.map[eventName]) this.map[eventName] = []this.map[eventName].push(callback)},// 触发事件 只有key 对应的才触发回调事件trigger(nodeName) {this.map[nodeName].forEach((callback) => {callback()})},}console.log(Dep)

最终结果

完整代码

<!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" /><title>发布订阅模式</title></head><body><div id="app"><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span> <br /><span v-mode="inputVal"></span><br /><span v-mode="age"></span><br /></div></body><script>/*关键就是一个一对多的关系 */let data = {inputVal: 'vue发布订阅模式',age: 15,}// 数据代理const proxyReative = (data) => {observe(data)return new Proxy(data, {get(target, key) {return target[key]},set(target, key, newVal) {if (target[key] === newVal) returntarget[key] = newVal// compile()// 执行更新Dep.trigger(key)},})}const observe = (data) => {Object.keys(data).forEach((key) => {if (typeof data[key] === 'object') {data[key] = proxyReative(data[key])}})}const vm = proxyReative(data)// 发布订阅模式const Dep = {map: {},collect(eventName, callback) {if (!this.map[eventName]) this.map[eventName] = []this.map[eventName].push(callback)},trigger(nodeName) {this.map[nodeName].forEach((callback) => {callback()})},}console.log(Dep)// 模板编译const compile = () => {const appRef = document.getElementById('app')// const inputRef = document.getElementById('input')const childNodes = appRef.childNodeschildNodes.forEach((node) => {// 1 元素节点     3 文本节点if (node.nodeType === 1) {const arrts = node.attributesArray.from(arrts).forEach((arrt) => {if (arrt.nodeName === 'v-mode') {// 初次渲染赋值node.innerText = data[arrt.nodeValue]// 后续更新赋值 收集更新函数Dep.collect(arrt.nodeValue, () => {console.log('更新了', arrt.nodeValue)node.innerText = data[arrt.nodeValue]})}})}})}compile()</script>
</html>

vue 发布订阅模式相关推荐

  1. vue发布订阅模式,发布订阅模型

    1.什么是发布订阅模式 (又叫做观察者模式) 他定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都将得到通知. 2.发布订阅模型 1.发布者会给订阅者提供一个方法以便 ...

  2. 发布订阅模式 仿写Vue事件监听手写js实现

    Vue组件中,可以使用 $emit,$on,$off 分别来分发.监听.取消监听事件实现组件通信,比较方便: 最近空闲时间手撸代码实现了发布订阅模式,可以进行组件通信. 话不多说,直接上代码 /*** ...

  3. 从发布-订阅模式到Vue响应系统

    概念 发布-订阅模式又称为观察者模式,它定义的是一种一对多的依赖关系,当一个状态发生改变的时候,所有以来这个状态的对象都会得到通知. 生活中的发布-订阅模式 上面事发布-订阅模式的一个比较正式的解释, ...

  4. 前端Vue之发布订阅模式

    目录 1.什么是发布订阅模式 2.实现简单的发布订阅 3.收集更新函数 4.触发更新函数 5.总结 一个响应式数据可能会有多个视图部分都需要依赖,也就是响应式数据变化之后,需要执行的更新函数可能不止一 ...

  5. 深入Vue原理_全面剖析发布订阅模式

    文章目录 发布订阅模式优化 优化思路思考 理解发布订阅模式(自定义事件) 收集更新函数 触发更新函数 6.5 总结 总结 写在最后 本期推荐 欢迎各位小伙伴们! 为大家推荐一款刷题神奇哦 点击链接访问 ...

  6. Vue响应式原理探究之“发布-订阅”模式

    前言 在面试题中经常会出现与"发布订阅"模式相关的题目,比如考察我们对Vue响应式的理解,也会有题目直接考验我们对"发布订阅"模式或者观察者模式的理解,甚至还会 ...

  7. JavaScript 发布-订阅模式

    发布-订阅模式,看似陌生,其实不然.工作中经常会用到,例如 Node.js EventEmitter 中的 on 和 emit 方法:Vue 中的 $on 和 $emit 方法.他们都使用了发布-订阅 ...

  8. JavaScript中发布/订阅模式的理解

    订阅发布模式的介绍 发布订阅模式,它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到. 在生活中我们常常遇到这样一种情况,我们在 ...

  9. 设计模式-发布订阅模式

    这段时间在看vue的双向绑定原理,知道了vue的核心三大件:Observer, Complie, Watcher. Observer用于监听属性的变化,如有变动就通知 Watcher. Compile ...

最新文章

  1. go操作网页元素_UI自动化21heliumS元素定位方式
  2. nginx小总结(五)
  3. 【人工智能】人工智能的发展历程
  4. SVG 动画实现弹性的页面元素效果
  5. Send data format set as XML
  6. Win11 恢复 Win10经典右键菜单 亲测有效
  7. java图形旋转动画_Java动画:旋转图像
  8. 55个好习惯可令世界更美好(2)
  9. 创建型模式专题总结:Creational Pattern(转自Terrylee)
  10. 用C语言实现字符串的右旋
  11. 【C语言】输出100内素数
  12. Niushop 砸金蛋营销活动
  13. 简单的APP与PLC通讯
  14. Git操作流程(非常详细)
  15. ICEM-圆柱与长方体相切
  16. 1812. 方形牧场
  17. 在接口自动化测试中,如何利用Pytest + JSONPath 进行接口响应断言
  18. Python学习笔记——绘图设置(三)箱线图
  19. 如何制作带照片的工作证
  20. 集多功能为一体的智能WiFi模块Linux多线程处理器openwrt开发板工业4G路由器网口有线转无线WiFi

热门文章

  1. 电脑连不上网,怎么办
  2. 2012网络流行语 - 收集
  3. KingbaseES 数据库软件卸载
  4. element-ui生成二维码
  5. 软件测试及Bug管理经验谈
  6. 【基于JS 函数式编程 -1】什么是函数式编程 | 纯函数 | 命令式与声明式 | 优点
  7. 疫情患者活动轨迹查询-小程序
  8. 服务器中电池可以维修吗,电池修复到底有没有效果?一个维修工的遭遇揭开真相!...
  9. 前端实现带二维码的工厂物料标签,发票生成以及打印(vue框架),以及监听浏览器打印事件的钩子函数
  10. 怎么用java做水滴动画_‘纯css实现Material Design中的水滴动画按钮’的js体验优化...