最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3中的數(shù)據(jù)劫持的最新實(shí)現(xiàn)方案的proxy示例詳解

 更新時(shí)間:2024年11月25日 14:45:10   作者:風(fēng)清云淡_A  
Vue3中使用Proxy實(shí)現(xiàn)數(shù)據(jù)劫持,解決了Vue2中數(shù)組和對(duì)象劫持的遺留問(wèn)題,Proxy可以修改某些操作的默認(rèn)行為,通過(guò)get和set方法實(shí)現(xiàn)數(shù)據(jù)的劫持和保護(hù)機(jī)制,感興趣的朋友跟隨小編一起看看吧

vuejs中實(shí)現(xiàn)數(shù)據(jù)的劫持,v2中使用的是Object.defineProperty()來(lái)實(shí)現(xiàn)的,在大版本v3中徹底重寫了這部分,使用了proxy這個(gè)數(shù)據(jù)代理的方式,來(lái)修復(fù)了v2中對(duì)數(shù)組和對(duì)象的劫持的遺留問(wèn)題。

proxy是什么

Proxy 用于修改某些操作的默認(rèn)行為,等同于在語(yǔ)言層面做出修改,所以屬于一種“元編程”(meta programming),即對(duì)編程語(yǔ)言進(jìn)行編程。
Proxy 可以理解成對(duì)源對(duì)象進(jìn)行一個(gè)封裝,在操作源對(duì)象之前,做了一系列額外的操作,最終返回我們需要的新數(shù)據(jù)對(duì)象。

基礎(chǔ)使用

let obj = new Proxy(
  {},
  {
    get(target, prop, receiver) {
      console.log("get", prop);
      if (!target[prop]) target[prop] = 120;
      return Reflect.get(target, prop, receiver);
    },
    set(target, prop, value, receiver) {
      console.log("set", prop);
      return Reflect.set(target, prop, value, receiver);
    },
  }
);
obj.count = 1;
obj.count;
obj.count;
obj.count;
console.log(obj.count);
obj.age;
console.log(obj.age);

proxy實(shí)例有兩個(gè)參數(shù),一個(gè)是目標(biāo)對(duì)象,一個(gè)是操作方法的hash集合

取值函數(shù)get,賦值函數(shù)set。

對(duì)特定屬性的劫持

const proxyObj = new Proxy(
  { name: "Tom", age: 18 },
  {
    get: function (target, prop) {
      if (prop === "age") return target[prop] - 1;
      return 35;
    },
  }
);
proxyObj.time;
console.log("?? ~ proxyObj.time:", proxyObj.time);
proxyObj.age;
console.log("?? ~ proxyObj.time:", proxyObj.age);

把實(shí)例方法封裝在對(duì)象內(nèi)部

const object = {
  name: "Tom",
  age: 18,
  sayHi() {
    console.log("sayHi");
  },
  proxy() {
    return new Proxy(this, {
      get(target, prop) {
        console.log("?? ~ get ~ prop:", prop);
        if (prop in target) {
          return Reflect.get(target, prop);
        } else {
          return "no prop";
        }
        return Reflect.get(target, prop);
      },
    });
  },
};
const newProxy = object.proxy();
// newObjj.age;
console.log("?? ~ newObjj.age;:", newProxy.age);
console.log("?? ~ newObjj.name;:", newProxy.sex);

對(duì)數(shù)組進(jìn)行負(fù)值索引的操作

function createArray(...elements) {
  let handler = {
    get(target, prop, receiver) {
      let index = Number(prop);
      if (index < 0) {
        prop = String(target.length + index);
      }
      return Reflect.get(target, prop, receiver);
    },
  };
  let target = [];
  target.push(...elements);
  return new Proxy(target, handler);
}
let arr = createArray("a", "b", "c");
arr[-1];
console.log("?? ~ arr[-1]:", arr[-1]);
console.log("?? ~ arr[-1]:", arr[-2]);
console.log("?? ~ arr[-1]:", arr[-3]);

實(shí)現(xiàn)數(shù)據(jù)的鏈?zhǔn)秸{(diào)用

var double = (n) => n * 2;
var pow = (n) => Math.pow(n, 2);
var reverse = (n) => String(n).split("").reverse().join("");
const pipe = function (value) {
  var funcStack = [];
  var oProxy = new Proxy(
    {},
    {
      get: function (target, key) {
        console.log("?? ~ pipe ~ key:", key);
        if (key === "get") {
          return funcStack.reduce(function (val, func) {
            return func(val);
          }, value);
        }
        // 把方法存儲(chǔ)到棧中
        funcStack.push(window[key]);
        console.log("?? ~ funcStack:", funcStack);
        return oProxy;
      },
    }
  );
  return oProxy;
};
const data1 = pipe(3).double.pow.reverse.get;
console.log("?? ~ data:", data1);

注意:三個(gè)方法必須是var聲明的,let/const都會(huì)報(bào)錯(cuò)

上面代碼設(shè)置 Proxy 以后,達(dá)到了將函數(shù)名鏈?zhǔn)绞褂玫男Ч?/p>

利用get攔截,實(shí)現(xiàn)一個(gè)生成各種 DOM 節(jié)點(diǎn)的通用函數(shù)dom

const dom = new Proxy(
  {},
  {
    get(target, prop) {
      return function (arrts, ...children) {
        const el = document.createElement(prop);
        for (let prop of Object.keys(arrts)) {
          el.setAttribute(prop, arrts[prop]);
        }
        for (let child of children) {
          console.log("?? ~ get ~ child:", child);
          if (typeof child === "string") {
            child = document.createTextNode(child);
          }
          el.appendChild(child);
        }
        return el;
      };
    },
  }
);
const el = dom.div(
  {},
  "Hello, my name is ",
  dom.a({ href: "http://example.com" }, "Mark"),
  ". I like:",
  dom.ul(
    {},
    dom.li({}, "The web"),
    dom.li({}, "Food"),
    dom.li({}, "…actually that's it")
  )
);
document.body.appendChild(el);

第三個(gè)參數(shù),它總是指向原始的讀操作所在的那個(gè)對(duì)象

const proxy = new Proxy(
  {},
  {
    get: function (target, prop, receiver) {
      console.log("?? ~ prop:", prop);
      return receiver;
    },
  }
);
const isSame = proxy.getReceiver === proxy;
console.log("?? ~ isSame:", isSame);
const d = Object.create(proxy);
console.log("ddd", d.a === d);

如果一個(gè)屬性不可配置(configurable)且不可寫(writable),則 Proxy 不能修改該屬性

const target = Object.defineProperties(
  {},
  {
    foo: { value: "bar", enumerable: false, configurable: false },
  }
);
const handler = {
  get(target, prop) {
    return "abc";
  },
};
const proxy2 = new Proxy(target, handler);
proxy2.foo;

上面通過(guò) Proxy 對(duì)象訪問(wèn)該屬性會(huì)報(bào)錯(cuò)。

攔截方法的執(zhí)行

上面的都是object對(duì)象的屬性進(jìn)行劫持,也可以作為方法調(diào)用時(shí)進(jìn)行劫持。

var target = function () {
  return "I am the target";
};
var handler = {
  apply(target, thisArg, argumentsList) {
    console.log("?? ~ apply ~ argumentsList:", argumentsList);
    const res = target();
    console.log("?? ~ apply ~ res:", res);
    return "I am the proxy" + " " + argumentsList.join(",");
  },
};
const p = new Proxy(target, handler);
const a = p("a", "b");
console.log("?? ~ a:", a);

變量p是 Proxy 的實(shí)例,當(dāng)它作為函數(shù)調(diào)用時(shí)(p()),就會(huì)被apply方法攔截,返回一個(gè)字符串

function sum(left, right) {
  return left + right;
}
var twice = {
  apply(target, context, args) {
    console.log("?? ~ apply ~ context:", context);
    console.log("?? ~ apply ~ args:", args);
    return Reflect.apply(target, context, args) * 2;
  },
};
const proxy = new Proxy(sum, twice);
const data = proxy(1, 2);
console.log("?? ~ data:", data);
const data2 = proxy.call(null, 2, 5);
console.log("?? ~ data2:", data2);
const data3 = proxy.apply(null, [5, 5]);
console.log("?? ~ data3:", data3);

當(dāng)執(zhí)行proxy函數(shù)(直接調(diào)用或call和apply調(diào)用),就會(huì)被apply方法攔截。

get和set方法,實(shí)現(xiàn)內(nèi)部屬性的保護(hù)機(jī)制

const proxy = new Proxy(
  {},
  {
    get(target, prop) {
      invariant(prop, "get");
      return Reflect.get(target, prop);
    },
    set(target, prop, value) {
      invariant(prop, "set");
      Reflect.set(target, prop, value);
      return true;
    },
  }
);
function invariant(key, action) {
  if (key[0] === "_") {
    throw new Error(`Invalid attempt to ${action} private "${key}" property`);
  }
}
// proxy._prop;
proxy._prop = "value";

攔截key in proxy的操作

var target = { _prop: "foo", prop: "foo" };
const proxy = new Proxy(target, {
  has(target, key) {
    if (key[0] === "_") {
      console.log("false");
      return false;
    }
    return key in target;
  },
});
"_prop" in proxy; // false

deleteProperty刪除屬性的劫持

const handler = {
  construct(target, args) {
    console.log("called: " + args.join(","));
    return new target(...args);
  },
  deleteProperty(target, prop) {
    if (prop === "age") return false;
    delete target[prop];
    return true;
  },
};
const P = new Proxy(function () {}, handler);
const p = new P(10);
P.value;
const p2 = new Proxy(
  {
    age: 20,
    name: "John",
    greet: () => console.log("hello"),
  },
  handler
);
delete p2.age;
delete p2.name;

到此這篇關(guān)于vue3中的數(shù)據(jù)劫持的最新實(shí)現(xiàn)方案的proxy的詳解的文章就介紹到這了,更多相關(guān)vue proxy內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue + typescript + 極驗(yàn)登錄驗(yàn)證的實(shí)現(xiàn)方法

    vue + typescript + 極驗(yàn)登錄驗(yàn)證的實(shí)現(xiàn)方法

    這篇文章主要介紹了vue + typescript + 極驗(yàn) 登錄驗(yàn)證的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • vue的三種圖片引入方式代碼實(shí)例

    vue的三種圖片引入方式代碼實(shí)例

    這篇文章主要介紹了vue的三種圖片引入方式代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • vue3+vite2中使用svg的方法詳解(親測(cè)可用)

    vue3+vite2中使用svg的方法詳解(親測(cè)可用)

    vue2的時(shí)候使用的是字體圖標(biāo),缺點(diǎn)就是比較單一,到了vue3,相信瀏覽器的性能起來(lái),所以這里記錄一下,下面這篇文章主要給大家介紹了關(guān)于vue3+vite2中使用svg的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • vue項(xiàng)目如何通過(guò)url鏈接引入其他系統(tǒng)頁(yè)面

    vue項(xiàng)目如何通過(guò)url鏈接引入其他系統(tǒng)頁(yè)面

    這篇文章主要介紹了vue項(xiàng)目如何通過(guò)url鏈接引入其他系統(tǒng)頁(yè)面問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Vue報(bào)錯(cuò)Syntax?Error:TypeError:?this.getOptions?is?not?a?function的解決方法

    Vue報(bào)錯(cuò)Syntax?Error:TypeError:?this.getOptions?is?not?a?

    前幾天在vue運(yùn)行項(xiàng)目過(guò)程中報(bào)錯(cuò)了,所以下面這篇文章主要給大家介紹了關(guān)于Vue報(bào)錯(cuò)Syntax?Error:TypeError:?this.getOptions?is?not?a?function的解決方法,需要的朋友可以參考下
    2022-07-07
  • vue中如何使用唯一標(biāo)識(shí)uuid(uuid.v1()-時(shí)間戳、uuid.v4()-隨機(jī)數(shù))

    vue中如何使用唯一標(biāo)識(shí)uuid(uuid.v1()-時(shí)間戳、uuid.v4()-隨機(jī)數(shù))

    這篇文章主要給大家介紹了關(guān)于vue中如何使用唯一標(biāo)識(shí)uuid(uuid.v1()-時(shí)間戳、uuid.v4()-隨機(jī)數(shù))的相關(guān)資料,當(dāng)使用Vue.js生成UUID時(shí),我們可以使用uuid庫(kù)來(lái)幫助我們生成通用唯一標(biāo)識(shí)符(UUID),需要的朋友可以參考下
    2023-12-12
  • 如何使用elementUI組件實(shí)現(xiàn)表格的分頁(yè)及搜索功能

    如何使用elementUI組件實(shí)現(xiàn)表格的分頁(yè)及搜索功能

    最近在使用element-ui的表格組件時(shí),遇到了搜索框功能的實(shí)現(xiàn)問(wèn)題,這篇文章主要給大家介紹了關(guān)于如何使用elementUI組件實(shí)現(xiàn)表格的分頁(yè)及搜索功能的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • vue 打包后的文件部署到express服務(wù)器上的方法

    vue 打包后的文件部署到express服務(wù)器上的方法

    vue是目前最流行的前端框架,今天要介紹的是如何利用vue+webpack+express的方式進(jìn)行前后端分離的開(kāi)發(fā),下面通過(guò)本文給大家分享vue 打包后的文件部署到express服務(wù)器上的方法,感興趣的朋友一起看看吧
    2017-08-08
  • 基于Vue3實(shí)現(xiàn)列表虛擬滾動(dòng)效果

    基于Vue3實(shí)現(xiàn)列表虛擬滾動(dòng)效果

    這篇文章主要為大家介紹了如何利用Vue3實(shí)現(xiàn)列表虛擬滾動(dòng)效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定價(jià)值,需要的可以參考一下
    2022-04-04
  • vue3+element?plus實(shí)現(xiàn)側(cè)邊欄過(guò)程

    vue3+element?plus實(shí)現(xiàn)側(cè)邊欄過(guò)程

    這篇文章主要介紹了vue3+element?plus實(shí)現(xiàn)側(cè)邊欄過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論

遂平县| 轮台县| 绥芬河市| 长乐市| 准格尔旗| 海盐县| 施秉县| 贵州省| 德昌县| 长治县| 兴海县| 綦江县| 罗平县| 金堂县| 麻栗坡县| 无棣县| 通许县| 阿鲁科尔沁旗| 资阳市| 凤翔县| 巩留县| 南陵县| 昌图县| 青岛市| 崇文区| 南充市| 孟津县| 星子县| 清镇市| 莱芜市| 南皮县| 民县| 理塘县| 革吉县| 遂平县| 漠河县| 普安县| 蒙自县| 出国| 苍南县| 宣汉县|