首页 > 其他分享 >Vue3笔记 - 浅析Vue2和Vue3响应式原理及两者差异

Vue3笔记 - 浅析Vue2和Vue3响应式原理及两者差异

时间:2022-11-20 19:00:22浏览次数:77  
标签:name person 响应 添加 Vue2 Vue3 浅析

浅析Vue2和Vue3响应式原理及两者差异

目录

vue2的响应式

  • 对象类型:通过Object.defineProperty()对属性的读取、修改进行拦截(数据劫持)
  • 数组类型:通过重写更新数组的一系列方法来实现拦截(对数组的变更方法进行了包裹)

vue2中为数据添加响应式

  • 添加属性:无法直接添加,需要使用set额外设置响应式,否则无法被渲染
  • 删除属性:无法直接删除,需要使用delete删除,否则无法被渲染
  • 修改属性:对于已设置响应式的数据,可以自由修改;对于数组内的数据,必须使用数组提供的方法,否则无法被渲染
<template>
  <div>
    <h1>Vue2写的效果</h1>
    <h2>姓名:{{person.name}}</h2>
    <h2>年龄:{{person.age}}</h2>
    <h2 v-show="person.sex">性别:{{person.sex}}</h2>
    <h2>爱好:{{person.hobby}}</h2>
    <button @click="addSex">添加一个sex属性</button>
    <button @click="deleteName">删除name属性</button>
    <button @click="changeSomething">修改name属性和hobby属性</button>
  </div>
</template>

<script>
import Vue from 'vue'
export default {
    name: 'App',
    data() {
        return {
            person:{
              name:'张三',
              age:18,
              hobby:['学习','吃饭']
            }
        }
    },
    methods:{
      addSex(){
        //属性确实被添加了,但是无法在页面中显示,因为这个属性没有响应式
        this.person.sex = '女' //无效

        //添加响应式数据的方法1
        this.$set(this.person,'sex','女') //有效
        // 添加响应式数据的方法2
        Vue.set(this.person,'sex','女') //有效
      },
      deleteName(){
        //属性确实被添加了,但是无法在页面中显示,【即便】这个属性具有响应式
        delete this.person.name //无效
        //移除响应式数据的方法1
        this.$delete(this.person,'name') //有效
        //移除响应式数据的方法2
        Vue.delete(this.person,'name') //有效
      },
      changeSomething(){
        //已经具有响应式的数据可以直接修改
        this.person.name = '李四'  //有效
        
        //但是如果数据存储在数组中,就必须使用数组的方法修改
        this.person.hobby[0] = '打游戏' //无效
        this.$set(this.person.hobby,0,'打游戏') //有效
        this.person.hobby.splice(0,1,'打游戏') //有效
      }
    }
}
</script>

模拟Vue2实现响应式原理

let person = {
    name:'张三',
    age:18
}

//模拟vue2实现响应式
let p = {}
Object.defineProperty(p,'name',{
    configurable:true,
    //读取name时调用
    get(){
        return perosn.name
    },
    //修改name时调用
    set(value){
        console.log("name属性被修改,更新页面");
        person.name = value
    }
    //vue2响应式到这里就结束了,defineProperty无力支持删除操作,需要额外使用Vue.delete来删除响应式数据
})

vue3的响应式

  • 通过Proxy代理:拦截对象中任意属性的变化
  • 通过Reflect反射:对被代理对象中的属性进行操作

vue3中为数据添加响应式

  • 只要数据被reactive包裹,所有的增删改查都可以直接操作,不用考虑响应式
<template>
  <div>
    <h1>Vue3写的效果</h1>
    <h2>姓名:{{person.name}}</h2>
    <h2>年龄:{{person.age}}</h2>
    <h2 v-show="person.sex">性别:{{person.sex}}</h2>
    <h2>爱好:{{person.hobby}}</h2>
    <button @click="addSex">添加一个sex属性</button>
    <button @click="deleteName">删除name属性</button>
    <button @click="changeHobby">修改hobby属性</button>
  </div>
</template>

<script>
import {reactive} from 'vue'
export default {
    name: 'App',
    setup() {
      let person = reactive({
        name:'张三',
        age:18,
        hobby:['学习','吃饭']
      })

      //所有的增删改查都可以直接操作
      function addSex() {
        this.person.sex = '女'
      }
      function deleteName(){
        delete this.person.name
      }
      function changeHobby(){
        this.person.hobby[0] = '打游戏'
      }

      return{
        person,
        addSex,
        deleteName,
        changeHobby,
      }
    }
}
</script>

模拟vue3实现响应式

//使用了es6新增的Proxy,对于p的所有改变都会被反馈到person身上
const p = new Proxy(person,{
    //读取数据,比如在p.sex的时候,propName=sex,这样就可以方便的读取任意属性
    get(target,propName){
        console.log(`读取了p上的${propName}属性`)
        return Reflect.get(target,propName)
    },
    //添加or修改数据
    set(target,propName,value){
        console.log(`修改了p上的${propName}属性,更新界面`)
        return Reflect.get(target,propName,value)
    },
    //删除数据
    deleteProperty(target,propName){
        console.log(`删除了p上的${propName}属性,更新界面`);
        return Reflect.deleteProperty(target,propName)
    }
})

对比Vue2和Vue3的响应式

  • 响应式主要就是通过数据劫持,依赖收集,派发更新的方式来实现的
  1. Vue2无法检测到直接添加的新数据,需要使用$set方法添加响应式

    Vue3可以自动检测到被reactive包裹的对象内的,直接添加的新数据,无需手动添加响应式;当然也可以逐个使用reactive和ref手动添加

  2. Vue2无法检测到直接删除的新数据,需要使用$delete方法添加响应式

    同1,Vue3可以自动检测到被删除的新数据

  3. Vue2无法检测到数组内部元素的更新,因为数组元素内部元素不具有响应式,必须通过数组提供的方法修改才能检测到

    Vue3可以自动检测到数组内部元素的更新

  4. 对于基本数据类型,Vue2和Vue3基本都通过Object.defineProperty()完成响应式添加

    对于对象类型,Vue2仍旧采用Object.defineProperty(),Vue3则采用reactive(或者说Proxy)添加响应式

 

标签:name,person,响应,添加,Vue2,Vue3,浅析
From: https://www.cnblogs.com/Solitary-Rhyme/p/16909213.html

相关文章

  • vue3和vue2的区别
    1、vue3完全支持typescript,提高项目的可维护性2、Fragment:模板更简单。vue3用到了一个虚拟的父级,可以多个根节点domvue2只能有一个父级节点3、vue2用newVue();vu......
  • vue3 基础-API-computed
    API-computed基本使用前些章节讲了一些常用的api如setup,ref,reactive,toRef...等,并以一个todoList的小案例来体现在vue3中如何进行......
  • vue3 基础-API-watch 和 watchEffect
    watch和watchEffect前篇对computed属性如何在api中基本使用,即从vue中引入,然后通过直接传函数或者传对象的方式,开箱即用,非常清晰易......
  • Vue3 之 ref、shallowRef、customRef
    ref把对象转化为响应式的;shallowRef是浅层响应式数据,即:只有对value整体修改,才能更新到视图层。而修改具体属性值时,不会更新视图。(shallowReactive和shallowRef一样的......
  • Vue3 npm 命令解析
    我们使用npmrunxxx命令,在nodeMoudles里面,vite目录做了一个软链接,然后去软链接下面的目录去找,有3个vite的配置,适应不同的平台做的(unix、windows、mac等)流程:1、本地n......
  • vue2 echarts 报错 mounted Initialize failed: invalid dom. 的一种解决方法
    如题参考了https://blog.csdn.net/weixin_52418790/article/details/123690752但是还是不行,后来发现我这个是在elementui的模态框里面写的,但是模态框还没有......
  • vite创建一个vue3项目
    vite创建vue3npmcreatevite@latest回车后输入项目名,选择vue即可安装vue-routernpminstallvue-router@4安装pinia使用pinia代替vuexnpminstallpini......
  • vue2 事件绑定1 $event 事件修饰符 .prevent .stop 按键修饰符
    $event:添加e,$event写法是固定的    二,事件修饰符e.prevetDefault()    事件修饰符优化后@click.revent="" ......
  • ES6 语法 浅析
    ECMAScript6(简称ES6)是于2015年6月正式发布的JavaScript语言的标准,正式名为ECMAScript2015(ES2015)。它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业......
  • vue3学习笔记(一)
    helloworld<!DOCTYPEhtml><html><head><metacharset="utf-8"/><title>ECharts</title><!--方法有用--><!--<scriptsrc="https://unpkg.c......