我的编程空间,编程开发者的网络收藏夹
学习永远不晚

关于vue2响应式缺陷的问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

关于vue2响应式缺陷的问题

vue2响应式缺陷

响应式 : 数据改变 ==> 视图跟着改变

vue2响应式缺陷

1.对象新增的属性没有响应式

对象,新增属性b,修改b的值,值改变但视图并未更新

解决方案 : 使用vue提供的 api $set(对象,属性名,值) 效果如属性c

2.数组的部分操作没有响应式

数组中有7种操作有响应式

  • array.pop()
  • array.push()
  • array.shift()
  • array.unshift()
  • array.sort()
  • arry.reverse()
  • array.splice()

以上7中API会修改原数组(vue2的内部重写了这7个API)

其他的操作都不会有响应式

示例:

1.修改数组的第一个元素的值

// 直接通过下标来修改,没有响应式
fn1() {
    this.arr[0] = 100
}

通过下标直接赋值,没有响应式

2.修改数组的长度为0

//修改数组的length
fn2 () {
    this.arr.length = 0
}

修改数组的length,没有响应式

如何修改数组的值有响应式

fn1 () {
    // 方法1: 先删除,再添加
    this.arr.splice(0,1,100)
},
fn2 () {
    // 方法2: $set
    this.$set(this.arr, "0", 100)
}

vue2与vue3的响应式原理

给大家分享一下Vue2和Vue3的响应式原理;说到响应式无非就是监听属性的获取,修改及删除...,了解逻辑之后再去实现底层代码岂不是快了许多=_=

vue2响应式

原理:利用defineReactive方法,通过defineProperty对属性进行劫持,数组则是通过重写其方法来进行劫持,每个属性值都拥有自己的dep属性,用来存取所依赖的watch,当数据发生改变时,触发相应的watch去更新数据

代码实现:

const { arrayMethods } = require('./array')
 
class Observer {
    constructor(value) {
        Object.defineProperty(value, '__ob__', {
            value: this,
            enumerable: false,
            writable: true,
            configurable: true
        })
        if(Array.isArray(value)) {
            value.__proto__ = arrayMethods
            this.observeArray(value)
        } else {
            this.walk(value)
        }
    }
 
    walk(data) {
        let keys = Object.keys(data)
        for(let i = 0; i < keys.length; i++) {
            const key = keys[i]
            const value = data[key]
            defineReactive(data, key, value)
        }
    }
 
    observeArray(items) {
        for(let i = 0; i < items.length; i++) {
            observe(items[i])
        }
    }
}
 
function defineReactive(data, key, value) {
    const childOb = observe(value)
 
    const dep = new Dep()
 
    Object.defineProperty(data, key, {
        get() {
            console.log('获取值')
            if (Dep.target) {
                dep.depend()
 
                if (childOb) {
                    childOb.dep.depend()
 
                    if (Array.isArray(value)) {
                        dependArray(value)
                    }
                }
            }
            return value
        },
        set(newVal) {
            if (newVal === value) return
            observe(newVal)
            value = newVal
            dep.notify()
        }
    })
}
 
function observe(value) {
    if (Object.prototype.toString.call(value) === '[object Object]' || Array.isArray(value)) {
        return new Observer(value)
    }
}
 
function dependArray(value) {
    for(let e, i = 0, l = value.length; i < l; i++) {
        e = value[i]
 
        e && e.__ob__ && e.__ob__.dep.depend()
 
        if (Array.isArray(e)) {
            dependArray(e)
        }
    }
}
 
// array.js
const arrayProto = Array.prototype
 
const arrayMethods = Object.create(arrayProto)
 
const methodsToPatch = [
    'push',
    'pop',
    'shift',
    'unshift',
    'splice',
    'reverse',
    'sort'
]
 
methodsToPatch.forEach(method => {
    arrayMethods[method] = function (...args) {
        const result = arrayProto[method].apply(this, args)
 
        const ob = this.__ob__
 
        var inserted
 
        switch (method) {
            case 'push':
            case 'unshift':
                inserted = args
                break;
            case 'splice':
                inserted = args.slice(2)
            default:
                break;
        }
 
        if (inserted) ob.observeArray(inserted)
 
        ob.dep.notify()
 
        return result
    }
})
 

但是呢,Vue2的响应式还存在一些缺陷:1.对象新增属性,删除属性界面不会更新 2.通过数组下标修改数组内容界面不会更新

原因:1.Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的

2.通过数组下标修改数组不会触发响应,因为尤雨溪用了重写数组的方法来实现数据的响应绑定,当vue遇到push pop shift unshift splice sort reverse 的时候数组才会改变

 解决方案:1.对象:对象新增属性无法更新视图,通过Vue.$set(obj,key,value),组件中通过this.$set(obj,key,value)

2.数组:通过数组下标修改数组不会触发视图更新,可以通过Vue.$set(obj,key,value),也可以通过push pop shift unshift splice sort reverse方法来实现响应

 Vue3的响应式弥补了Vue2响应式的缺陷,并且还带来了许多优化,下面让我们来了解一下Vue3响应式的基本雏形

vue3响应式雏形

原理:利用了Proxy和Reflect来代替Vue2的Object.defineProperty()方法来重写响应式

这只是基本的代码:

        let person = {
            name: '张三',
            age: 18
        }
        const p = new Proxy(person, {
            get(target, propName) {
                console.log(`我的${propName}值被获取了`);
                return Reflect.get(target, propName)
            },
            set(target, propName, value) {
                console.log(`我的${propName}值被修改了`);
                Reflect.set(target, propName, value)
            },
            deleteProperty(target, propName) {
                console.log(`我的${propName}值被删除了`);
                Reflect.deleteProperty(target, propName)
            }
        })

target指的是整个person,propName指的是person中的某个属性,value指的是新值。

运行结果:

vue3的响应式相较于vue2的优势

用 Proxy 和 Reflect 来代替 vue2 中的 Object.definepeoperty()方法来重写响应式

vue3 中可以监听动态新增的属性

vue3 中可以监听删除的属性

vue3 中可以监听数组的索引和 length 属性

代码的执行效果更快

Proxy 可以直接监听对象而非属性

Proxy 可以直接监听数组的变化

Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的

Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改

Proxy 不需要初始化的时候遍历所有属性,另外有多层属性嵌套的话,只有访问某个属性的时候,才会递归处理下一级的属性 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

关于vue2响应式缺陷的问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

面试官问你Vue2的响应式原理该如何回答?

可能很多小伙伴之前都了解过 Vue2实现响应式的核心是利用了ES5的Object.defineProperty 但是面对面试官时如果只知道一些模糊的概念。只有深入底层了解响应式的原理,才能在关键时刻对答如流,本文就来和大家详细聊聊,感兴趣的可以收藏一下
2022-12-14

关于vue2使用element UI中Descriptions组件的遍历问题详解

最近element-ui遇到了很多坑,下面这篇文章主要给大家介绍了关于vue2使用element UI中Descriptions组件的遍历问题,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-02-08

如何解决Dreamweaver中关于应用CSS的小问题

这篇文章主要介绍了如何解决Dreamweaver中关于应用CSS的小问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。  Dreamweaver是集网页制作和管理网站于一身的
2023-06-08

vue中provide inject的响应式监听问题怎么解决

这篇文章主要介绍“vue中provide inject的响应式监听问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue中provide inject的响应式监听问题怎么解决”文章能帮助大
2023-06-30

关于asp读取大量数据的时候出现超过响应缓冲区限制的问题

在ASP中读取大量数据时,可能会出现超过响应缓冲区限制的问题。这是因为ASP默认情况下将响应缓冲区大小限制为4KB,如果超过这个限制,将会发生错误。要解决这个问题,可以采取以下几种方法:1. 增加响应缓冲区大小:可以在ASP页面的开头使用R
2023-08-08

编程热搜

目录