vue高级

148 阅读3分钟

vue响应式原理

在实现整个Vue响应式代码之前,我们先来了解几个概念。

第一个:数据驱动

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

开发过程中仅仅需要关注数据本身,不需要关心数据是如何渲染到视图中的。主流的MVVM框架都已经实现了数据响应式与双向绑定,所以可以将数据绑定到DOM上。

数据驱动的内容

数据响应式:当我们修改数据时,视图会进行更新

双向绑定:数据改变,视图改变,视图改变,数据也随之改变( 通过这句话,我们可以看到在双向绑定中是包含了数据响应式的内容)

第二个:响应式的核心原理

关于Vue2.x的响应式原理在官方文档中也有介绍。cn.vuejs.org/v2/guide/re…

在该文档中,我们注意如下一段内容: 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法降级(shim) 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

通过以上的文字,我们可以看到,在Vue2.x中响应式的实现是通过Object.defineProperty来完成的

Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

下面我们来看一下Object.defineProperty基本使用,修改data对象中的msg属性的值,实现视图的更新.(这也就是我们所说的响应式),如下:

image.png

image.png 在上面的代码中,我们是将一个对象中的属性转换成了getter/setter的形式,那么这里我们还有一个问题: 如果有一个对象中多个属性需要转换getter/setter,那么应该如何处理?

答:我们可以通过循环遍历的方式,将对象中的多个属性转换成getter/setter  如下:

image.png

image.png

Vue2响应式有一个缺点,需要通过循环递归遍历对象,性能不高。

Vue3响应式原理

 Vue3的响应式原理是通过Proxy来完成的。

Proxy直接监听对象,而非属性,所以将多个属性转换成getter/setter的时候,不需要使用循环。

Proxy是ES6课程中新增的,IE不支持

Hello

image.png

image.png

第三个:发布订阅模式和观察者模式

发布订阅模式

发布订阅模式:订阅者,发布者,信号中心

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

Vue 的自定义事件就是基于发布订阅模式来实现的

下面通过Vue中兄弟组件通信过程,来理解发布订阅模式,如下:

App组件



</div>
<script>
    let eventBus = new Vue()
    let Aa = {
        template: `<div class="wrap">A组件:<button @click="sendMsg">发布</button></div>`,
        data() {
            return {
                Amsg: '我是来自A组建的信息',
            }
        },
        methods: {
            sendMsg() {
                eventBus.$emit('eat', this.Amsg)
                eventBus.$emit('drink', this.Amsg)
            }
        }
    }
    let Bb = {
        template: `<div><h3>B组件:{{Bmsg}}</h3></div>`,
        created() {
            eventBus.$on('eat', (txt) => {
                console.log("start eat...", txt);
            })
            eventBus.$on('drink', (txt) => {
                console.log("start drink...", txt);
            })
        },
        data() {
            return {
                Bmsg: '我是B组件',
            }
        },
        methods: {
            sendMsg() {

            }
        }
    }
    let vm = new Vue({
        el: "#app",
        components: {
            Aa,
            Bb,
        }
    })
</script>

image.png

image.png

image.png

当一个事件发生了,做什么?只能做一件吗?

答:一个事件发生了,可以做多件事,如下:

原生JS模拟实现自定义事件,如下:

image.png

image.png

Vue的响应式机制使用了观察者模式,所以我们首先要先了解一下观察者模式

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

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

目标(发布者) --Dep

subs 数组:存储所有的观察者

addSub() 添加观察者,将其保存到subs数组中

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

image.png

image.png

下面我们看一下观察者模式与发布订阅模式的区别。

观察者模式:被观察者需要记录所有观察者

发布订阅模式:发布者和订阅者之间没有任何关系,彼此不知道对象的存在