iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >关于vue2响应式缺陷的问题
  • 240
分享到

关于vue2响应式缺陷的问题

2024-04-02 19:04:59 240人浏览 八月长安
摘要

目录Vue2响应式缺陷1.对象新增的属性没有响应式2.数组的部分操作没有响应式vue2与vue3的响应式原理vue2响应式vue3响应式雏形vue3的响应式相较于vue2的优势vue

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

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

--结束END--

本文标题: 关于vue2响应式缺陷的问题

本文链接: https://www.lsjlt.com/news/167308.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
  • 关于vue2响应式缺陷的问题
    目录vue2响应式缺陷1.对象新增的属性没有响应式2.数组的部分操作没有响应式vue2与vue3的响应式原理vue2响应式vue3响应式雏形vue3的响应式相较于vue2的优势vue...
    99+
    2024-04-02
  • vue2响应式的缺点影响
    前言: 响应式:数据改变-->视图跟着变 对象新增的属性没有响应式 数组的部分操作没有响应式    push(),pop(),shift(),unshift...
    99+
    2024-04-02
  • 关于vue3vuex4store的响应式取值问题解决
    场景: 在页面中点击按钮,数量增加,值是存在store中的,点击事件,值没变。 <script setup lang="ts"> import { useStore } ...
    99+
    2024-04-02
  • 关于springboot响应式编程整合webFlux的问题
    在servlet3.0标准之前,是每一个请求对应一个线程。如果此时一个线程出现了高延迟,就会产生阻塞问题,从而导致整个服务出现严重的性能情况,因为一旦要调用第三方接口,就有可能出现这...
    99+
    2024-04-02
  • Vue 如何关掉响应式问题
    目录Vue如何关掉响应式例子v-onceVue响应式的处理过程Vue如何关掉响应式 大家都知道Vue有双向数据绑定 ,但是很少人知道怎样把它这个功能关掉 比如想要让某个值的改变不改变...
    99+
    2024-04-02
  • 关于Vue3中的响应式原理
    目录一、简介二、响应核心1.核心源码2.逐步分析上述示例代码3.收集依赖和触发依赖更新三、V3.2的响应式优化四、后话一、简介 本章内容主要通过具体的简单示例来分析Vue3是如何实现...
    99+
    2024-04-02
  • 面试中如何响应关于Go和Linux的问题?
    在当今互联网行业中,Go语言和Linux操作系统已经成为了非常热门的技术。因此,在面试时,面试官通常会问到与这两个技术相关的问题。本文将为大家总结一些面试中常见的与Go和Linux相关的问题,并提供一些解决方案和演示代码。 Go语言的特...
    99+
    2023-08-22
    linux 响应 面试
  • 关于python 缺少dbm模块问题
    今天在 CentOS 5.6  64位的机器上配置Func被控端时,在安装设置完 Func 及 Certmaster 后,启动 Funcd 提示如下错误 [root@certmaster ~]#service funcd start  St...
    99+
    2023-01-31
    模块 python dbm
  • 关于Centos7中Vscode无响应的问题及解决方法
    版本信息 虚拟机版本:VMware® Workstation 16 Pro 16.1.2 build-17966106 Linux系统:CentOS7 问题描述 在CentO...
    99+
    2024-04-02
  • Vue2/Vue3的响应式原理是什么
    本篇内容主要讲解“Vue2/Vue3的响应式原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue2/Vue3的响应式原理是什么”吧!在讲解之前,我们先了解一下数据响应式是什么?所谓数据...
    99+
    2023-07-05
  • 一文详解Vue2/Vue3的响应式原理
    this.$delete(this.student, 'name');// 删除student对象属性name this.$set(this.student, 'age', '21');// ...
    99+
    2023-05-14
    Vue.js
  • 面试官问你Vue2的响应式原理该如何回答?
    目录前言响应式对象响应式开始的地方Observer实现响应式的defineReactivedepwatcher依赖收集派发更新总结前言 可能很多小伙伴之前都了解过 Vue2实现响应式...
    99+
    2022-12-14
    Vue2响应式原理 Vue 响应式原理 Vue 响应式
  • 关于vue2使用element UI中Descriptions组件的遍历问题详解
    目录需求描述:问题描述:导致原因:处理办法:以下为其他思考解决方式(不推荐)总结需求描述: 展示信息时其中部门区域是未知数量的,需要通过遍历进行展示。如下图举例,其中地址和备注是一一...
    99+
    2023-02-08
    vue结合elementui遍历数据 elementui descriptions组件 elementui组件
  • Python opencv缺陷检测的实现及问题解决
    题目描述 利用opencv或其他工具编写程序实现缺陷检测。 实现过程 # -*- coding: utf-8 -*- ''' 作者 : 丁毅 开发时间 : 2021/4/21 ...
    99+
    2024-04-02
  • 一篇搞懂Vue2、Vue3响应式源码的原理
    目录前言Vue2响应式操作响应式函数的封装Depend类的封装监听对象的变化Vue3响应式操作Proxy、ReflectVue3响应式前言 我们在编写Vue2,Vue3代码的时候,经...
    99+
    2023-01-08
    Vue2响应式原理 Vue3响应式原理
  • VB关于FindWindowEx的问题
    FindWindowEx函数用于在指定窗口的子窗口中查找符合指定条件的窗口。它的声明如下:Public Declare Functi...
    99+
    2023-08-08
    VB
  • 关于Java应用日志与Jaeger的trace关联的问题
    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernet...
    99+
    2024-04-02
  • 关于vue中的时间格式转化问题
    目录vue时间格式转化问题1. 效果图2. 需求:前台展示一律用的时间规格vue转换时间格式(适用于uni-app)1. 前端获取实时时间2. 运用过滤...
    99+
    2024-04-02
  • vue2中provide/inject的使用与响应式传值详解
    目录前言一、基本用法二、响应式1.方法一:传递的参数用一个方法返回2.方法二:把需要传递的参数定义成一个对象总结前言 官网概念:这对选项需要一起使用,以允许一个祖先组件向其所有子孙后...
    99+
    2024-04-02
  • 关于React中使用window.print()出现页面无响应问题解决记录
    目录一、问题背景:二、问题原因: 三、问题解决:总结:一、问题背景: window.print()页面打印出现页面无响应 看了网上很多办法都是让用window.locat...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作