阅读 112

mini-vue开发准备工作

数据驱动

  • 数据响应式、双向绑定、数据驱动

  • 数据响应式

    • 数据模型仅仅是普通的javascript对象,而当我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率。

  • 双向绑定

    • 数据改变,视图改变,视图改变,数据也随之改变

    • 我们可以使用v-model在表单元素上创建双向数据绑定

  • 数据驱动时Vue最独特的特性之一

    • 开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图

vue2.x响应式原理

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

下面我们来演示下Object.defineProperty如何使用

<template>     <div id='app'>hello</div> </template> <script>     // 模拟vue中的data     let data = {         msg: 'hello'     }     // 模拟vue实例     let vm = {}     // 数据劫持: 当访问或者设置vm中的成员的时候,做一些干预操作     Object.defineProperty(vm, 'msg', {         // 可枚举         enumerable: true,         // 可配置         configurable: true,         // 取值操作         get() {             console.log('get:', data.msg)             return data.msg         },         // 设置值操作         set(newValue) {             if(newValue === data.msg) {                 return             }             data.msg = newValue                          document.querySelector('#app').textContent = data.msg         }     }) </script> 复制代码

上述代码我们演示了单个属性的转化方法,如果多个属性的话即需要循环的给属性添加defineProperty即可,这块不做演示了

vue3.x响应式原理

vue3.x中使用proxy来进行监听对象,而不是属性,此外proxy IE不支持。

下面我们通过代码来演示下proxy

// 模拟vue中的data     let data = {         msg: 'hello'     }     // 模拟vue实例     let vm = new Proxy(data, {         // 当访问vm对象的时候执行get方法         get(target, key) {             return target(key)         },         // 当设置vm的成员是会执行set方法         set(target, key, newValue) {             if(target[key] === newValue) {                 return             }             target[key] = newValue             document.querySelector('#app').textContent = target[key]         }     }) </script> 复制代码

发布订阅模式

我们假定存在一个‘信号中心’,某个任务执行完成,就向信号中心发布(publish)一个信号,其他任务可以向信号中心‘订阅(subscibe)’这个信号,从而知道什么时候自己可以开始执行,这就叫做‘发布/订阅模式’(publish-subscribe pattern)

我们用兄弟组件通信过程来演示下发布订阅模式

// eventBus.js // 事件中心 let eventBus = new Vue(); // ComponentA.vue // 发布者 addTodo: function() {     // 发布消息     eventBus.$emit('add-todo', {text: '发布新消息了'}) } // ComponentB.vue // 订阅者 create: function() {     //订阅消息     eventBus.$on('add-todo', () => {}) } 复制代码

下面我们来模拟下vue自定义事件

let vm = new Vue(); vm.$on('dataChange', () => {     console.log('dataChange') }) vm.$emit('dataChange') 复制代码

class EventEmitter {     constructor() {         this.subs = Object.create(null);     }          $on(eventType, handler) {         this.subs[eventType] = this.subs[eventType] || [];         this.subs[eventType].push(handler)     }          $emit(eventType) {         if(this.subs[eventType] && Array.isArray(this.subs[eventType])) {             this.subs[eventType].forEach(handler => {                 handler()             })         }              } } 复制代码

观察者模式

  • 观察者(订阅者)--Watcher

    • update() 当事件发生时,具体要做的事情

  • 目标(发布者)--Dep

    • subs数组 存储所有观察者

    • addSub() 添加观察者

    • notify() 当事件发生时,调用所有观察者的update方法

  • 没有事件中心

下面我们用一段代码演示观察者模式

// 发布者-目标 class Dep {     constructor() {         this.subs = []     }          addSub(sub) {         if(sub && sub.update) {             this.subs.push(sub)         }     }          notify() {         this.subs.forEach(sub => {             sub.update()         })     } } // 订阅者 Watcher class Watcher() {     update() {         console.log('update')     } } 复制代码

总结:

  • 观察者模式是有具体的目标调度,比如事件触发,Dep就会去调用观察者方法,所以观察者模式的订阅者与发布者之间时存在依赖的

  • 发布/订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。


作者:真不想写代码
链接:https://juejin.cn/post/7025533146456129550


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐