vue 发布订阅模式
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 发布订阅模式相关推荐
- vue发布订阅模式,发布订阅模型
1.什么是发布订阅模式 (又叫做观察者模式) 他定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都将得到通知. 2.发布订阅模型 1.发布者会给订阅者提供一个方法以便 ...
- 发布订阅模式 仿写Vue事件监听手写js实现
Vue组件中,可以使用 $emit,$on,$off 分别来分发.监听.取消监听事件实现组件通信,比较方便: 最近空闲时间手撸代码实现了发布订阅模式,可以进行组件通信. 话不多说,直接上代码 /*** ...
- 从发布-订阅模式到Vue响应系统
概念 发布-订阅模式又称为观察者模式,它定义的是一种一对多的依赖关系,当一个状态发生改变的时候,所有以来这个状态的对象都会得到通知. 生活中的发布-订阅模式 上面事发布-订阅模式的一个比较正式的解释, ...
- 前端Vue之发布订阅模式
目录 1.什么是发布订阅模式 2.实现简单的发布订阅 3.收集更新函数 4.触发更新函数 5.总结 一个响应式数据可能会有多个视图部分都需要依赖,也就是响应式数据变化之后,需要执行的更新函数可能不止一 ...
- 深入Vue原理_全面剖析发布订阅模式
文章目录 发布订阅模式优化 优化思路思考 理解发布订阅模式(自定义事件) 收集更新函数 触发更新函数 6.5 总结 总结 写在最后 本期推荐 欢迎各位小伙伴们! 为大家推荐一款刷题神奇哦 点击链接访问 ...
- Vue响应式原理探究之“发布-订阅”模式
前言 在面试题中经常会出现与"发布订阅"模式相关的题目,比如考察我们对Vue响应式的理解,也会有题目直接考验我们对"发布订阅"模式或者观察者模式的理解,甚至还会 ...
- JavaScript 发布-订阅模式
发布-订阅模式,看似陌生,其实不然.工作中经常会用到,例如 Node.js EventEmitter 中的 on 和 emit 方法:Vue 中的 $on 和 $emit 方法.他们都使用了发布-订阅 ...
- JavaScript中发布/订阅模式的理解
订阅发布模式的介绍 发布订阅模式,它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到. 在生活中我们常常遇到这样一种情况,我们在 ...
- 设计模式-发布订阅模式
这段时间在看vue的双向绑定原理,知道了vue的核心三大件:Observer, Complie, Watcher. Observer用于监听属性的变化,如有变动就通知 Watcher. Compile ...
最新文章
- go操作网页元素_UI自动化21heliumS元素定位方式
- nginx小总结(五)
- 【人工智能】人工智能的发展历程
- SVG 动画实现弹性的页面元素效果
- Send data format set as XML
- Win11 恢复 Win10经典右键菜单 亲测有效
- java图形旋转动画_Java动画:旋转图像
- 55个好习惯可令世界更美好(2)
- 创建型模式专题总结:Creational Pattern(转自Terrylee)
- 用C语言实现字符串的右旋
- 【C语言】输出100内素数
- Niushop 砸金蛋营销活动
- 简单的APP与PLC通讯
- Git操作流程(非常详细)
- ICEM-圆柱与长方体相切
- 1812. 方形牧场
- 在接口自动化测试中,如何利用Pytest + JSONPath 进行接口响应断言
- Python学习笔记——绘图设置(三)箱线图
- 如何制作带照片的工作证
- 集多功能为一体的智能WiFi模块Linux多线程处理器openwrt开发板工业4G路由器网口有线转无线WiFi
热门文章
- 电脑连不上网,怎么办
- 2012网络流行语 - 收集
- KingbaseES 数据库软件卸载
- element-ui生成二维码
- 软件测试及Bug管理经验谈
- 【基于JS 函数式编程 -1】什么是函数式编程 | 纯函数 | 命令式与声明式 | 优点
- 疫情患者活动轨迹查询-小程序
- 服务器中电池可以维修吗,电池修复到底有没有效果?一个维修工的遭遇揭开真相!...
- 前端实现带二维码的工厂物料标签,发票生成以及打印(vue框架),以及监听浏览器打印事件的钩子函数
- 怎么用java做水滴动画_‘纯css实现Material Design中的水滴动画按钮’的js体验优化...