搜尋
首頁web前端Vue.jsvue2&vue3資料響應式原理分析及手動實作(實例詳解)

本篇文章為大家帶來了vue2&vue3數據響應式原理分析及手動實現的相關知識,數據響應式視圖跟數據是自動更新的,數據更新的時候視圖是自動的更新的追踪數據的變化,希望對大家有幫助。

vue2&vue3資料響應式原理分析及手動實作(實例詳解)

資料響應式

  • 檢視跟資料是自動更新的,資料更新的時候檢視是自動的更新的
  • #追蹤資料的變化,在讀取資料或設定資料的時候能夠做一些劫持的一些動作
  • vue2 使用defineProperty
  • vue3 改用Proxy

使用defineProperty

如何追蹤變化

var obj = {}var age 
Object.defineProperty(obj, 'age', {
    get: function() {
        consoel.log('get age ...')
        return age    },
    set: function(val) {
        console.log('set age ...')
        age = val    }})obj.age =100 //set age ...console.log(obj.age)//get age ...

物件obj在取age屬性的時候會呼叫資料劫持的get方法
在給age屬性賦值的時候會呼叫set方法

那怎麼使用Object.defineProperty實作一個資料回應式呢

function defineReactive(data) {
  if (!data || Object.prototype.toString.call(data) !== '[object Object]')
    return;
  for (let key in data) {
    let val = data[key];
    Object.defineProperty(data, key, {
      enumerable: true, //可枚举
      configurable: true, //可配置
      get: function() {
        track(data, key);
        return val;
      },
      set: function() {
        trigger(val, key);
      },
    });
    if (typeof val === "object") {
      defineReactive(val);
    }
  }}function trigger(val, key) {
  console.log("sue set", val, key);}function track(val, key) {
  console.log("sue set", val, key);}const data = {
  name:'better',
  firends:['1','2']}defineReactive(data)console.log(data.name)console.log(data.firends[1])console.log(data.firends[0])console.log(Object.prototype.toString.call(data))

這個函數defineReactve用來對Object.defineProperty進行封裝,從函數名稱可以看出,運作就是定義一個響應式資料,封裝後只需要傳遞data,key和val就行
每當從data讀取key的時候觸發track函數,往data的key設定資料時,set函數中的trigger函數觸發

陣列的響應式

我們透過Array原型上的方法來改變陣列的內容不會觸發getter和setter
整理發現Array原型中可以改變陣列本身內容的方法有7個,分別push pop#shift unshift splice sort reverse
vue2 改寫了這7種方法
實作方式:
以Array.propertype為原型建立一個arrayMethods物件,再使用Object.setPropertypeOf(o, arryMethods)將o的__proto__指向arrayMethods

vue2&vue3資料響應式原理分析及手動實作(實例詳解)

如何收集依賴

使用

<template><p>{{name}}</p></template>

該範本中使用資料name, 我們要觀察資料, 當資料的屬性改變的時候, 可以通知哪些使用的地方,
這就是我們要先收集依賴,即把用到資料name的地方收集起來,然後等資料變化的時候,把之前收集好的依賴循環觸發一遍,總結來說就是getter中收集依賴,在setter中觸發依賴

使用proxy

Proxy物件用於建立一個物件的代理, 從而實現基本操作的攔截和定義(如屬性查找、賦值、枚舉、函數掉用等)

const p = new Proxy(target, handler)
  • target

  • 要使用 Proxy 包裝的目標物件(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理) 。

  • handler

  • 一個通常以函數為屬性的對象,各屬性中的函數分別定義了在執行各種操作時代理 p 的行為。
    reflect是內建對象, 他提供攔截javascript操作的方法, 這些方法和Proxy handlers相同

Reflect.set將值分配給屬性的函數。傳回一個Boolean 如果更新成功則回傳true

Reflect.get取得物件身上某個屬性的值,類似target[name]

如何實作劫持

const dinner = {
  meal:'111'}const handler = {
  get(target, prop) {
    console.log('get...', prop)
    return Reflect.get(...arguments)
  },
  set(target, key, value) {
    console.log('get...', prop)
    console.log('set',key,value)
    return Reflect.set(...arguments)
  }}const proxy = new Proxy(dinner, handler)console.log(proxy.meal)console.log(proxy.meal)

程式碼中dinner 物件代理到handler上
defineProperty區別
defineProperty的屬性需要遍歷才能監管所有屬性

使用proxy可以將物件所有屬性進行代理

用proxy實作一個模擬響應式

function reactive(obj) {
  const handler = {
    get(target, prop, receiver) {
      track(target, prop);
      const value =  Reflect.get(...arguments);
      if(typeof value === 'Object') {
        reactive(value)
      }else {
        return value      }
    },
    set(target,key, value, receiver) {
      trigger(target,key, value);
      return Reflect.set(...arguments);
    },
  };
  return new Proxy(obj,handler)}function track(data, key) {
  console.log("sue set", data, key);}function trigger(data, key,value) {
  console.log("sue set", key,':',value);}const dinner = {
  name:'haochi1'}const proxy  =reactive(dinner)proxy.name
proxy.list = []proxy.list.push(1)

執行後自動列印

vue2&vue3資料響應式原理分析及手動實作(實例詳解)

#思考:為啥只在get中使用遞歸,set不使用呢?

賦值也需要先get

#簡單總結:

  1. #vue2 (淺響應式)
  • 遍歷data,使用defineProperty攔截所有屬性
  • 當使用者操作檢視,會觸發set攔截器
  • set先改變目前資料, 再通知wartch, 讓watch去通知檢視更新
  • 檢視重繪, 再次從get中取得對應的資料
  1. vue3 (深度回應式) :
  • 使用proxy 進行代理;攔截data任意屬性的任意操作(13種), 包括屬性的讀寫, 屬性的添加, 屬性的刪除等等

  • 使用Reflect進行反射;動態對被代理的物件的對應屬性進行特定的操作

  • 代理物件(proxy)的反射物件(reflect)必須相互配合才能實現響應式

兩者的不同

Proxy能劫持整個物件,而Object.defineProperty只能劫持物件的屬性; 前者遞歸回傳屬性對應的值的代理即可實現響應式,後者需要深度遍歷每個屬性,後者對數組的操作很不友好.

更多編程相關知識,請訪問:編程入門! !

以上是vue2&vue3資料響應式原理分析及手動實作(實例詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:CSDN。如有侵權,請聯絡admin@php.cn刪除
分享两个可以绘制 Flowable 流程图的Vue前端库分享两个可以绘制 Flowable 流程图的Vue前端库Sep 07, 2022 pm 07:59 PM

前端有没有现成的库,可以直接用来绘制 Flowable 流程图的?下面本篇文章就跟小伙伴们介绍一下这两个可以绘制 Flowable 流程图的前端库。

vue是前端css框架吗vue是前端css框架吗Aug 26, 2022 pm 07:37 PM

vue不是前端css框架,而是前端JavaScript框架。Vue是一套用于构建用户界面的渐进式JS框架,是基于MVVM设计模式的前端框架,且专注于View层。Vue.js的优点:1、体积小;2、基于虚拟DOM,有更高的运行效率;3、双向数据绑定,让开发者不用再去操作DOM对象,把更多的精力投入到业务逻辑上;4、生态丰富、学习成本低。

聊聊Vue3+qrcodejs如何生成二维码并添加文字描述聊聊Vue3+qrcodejs如何生成二维码并添加文字描述Aug 02, 2022 pm 09:19 PM

Vue3如何更好地使用qrcodejs生成二维码并添加文字描述?下面本篇文章给大家介绍一下Vue3+qrcodejs生成二维码并添加文字描述,希望对大家有所帮助。

手把手带你利用vue3.x绘制流程图手把手带你利用vue3.x绘制流程图Jun 08, 2022 am 11:57 AM

利用vue3.x怎么绘制流程图?下面本篇文章给大家分享基于 vue3.x 的流程图绘制方法,希望对大家有所帮助!

一文深入详解Vue路由:vue-router一文深入详解Vue路由:vue-routerSep 01, 2022 pm 07:43 PM

本篇文章带大家详解Vue全家桶中的Vue-Router,了解一下路由的相关知识,希望对大家有所帮助!

手把手带你使用Vue开发一个五子棋小游戏!手把手带你使用Vue开发一个五子棋小游戏!Jun 22, 2022 pm 03:44 PM

本篇文章带大家利用Vue基础语法来写一个五子棋小游戏,希望对大家有所帮助!

通过9个Vue3 组件库,看看聊前端的流行趋势!通过9个Vue3 组件库,看看聊前端的流行趋势!May 07, 2022 am 11:31 AM

本篇文章给大家分享9个开源的 Vue3 组件库,通过它们聊聊发现的前端的流行趋势,希望对大家有所帮助!

手把手带你了解VUE响应式原理手把手带你了解VUE响应式原理Aug 26, 2022 pm 08:41 PM

本篇文章我们来了解 Vue2.X 响应式原理,然后我们来实现一个 vue 响应式原理(写的内容简单)实现步骤和注释写的很清晰,大家有兴趣可以耐心观看,希望对大家有所帮助!

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
1 個月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器