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

詳解vue3的沙箱機制

 更新時間:2021年04月15日 10:19:32   作者:不知道寫啥筆名  
這篇文章主要介紹了vue3的沙箱機制的相關(guān)資料,幫助大家更好的理解和學(xué)習使用vue框架,感興趣的朋友可以了解下

前言

vue3 沙箱主要分兩種

  1. 瀏覽器編譯版本,瀏覽器版本是使用with語法加上proxy代理攔截
  2. 本地預(yù)編譯版本,通過在模版預(yù)編譯階段轉(zhuǎn)換階段,使用轉(zhuǎn)換插件transformExpression將非白名單標識符掛在在組件代理對象下

瀏覽器編譯版本

render 函數(shù)編譯結(jié)果

<div>{{test}}</div>
<div>{{Math.floor(1)}}</div>

to

const _Vue = Vue;

return function render(_ctx, _cache, $props, $setup, $data, $options) {
  with (_ctx) {
    const {
      toDisplayString: _toDisplayString,
      createVNode: _createVNode,
      Fragment: _Fragment,
      openBlock: _openBlock,
      createBlock: _createBlock,
    } = _Vue;

    return (
      _openBlock(),
      _createBlock(
        _Fragment,
        null,
        [
          _createVNode("div", null, _toDisplayString(test), 1 /* TEXT */),
          _createVNode(
            "div",
            null,
            _toDisplayString(Math.floor(1)),
            1 /* TEXT */
          ),
        ],
        64 /* STABLE_FRAGMENT */
      )
    );
  }
};

從上面的代碼,我們能發(fā)現(xiàn),變量標識符沒有增加前綴,只是用with語法包裹了一下,延長作用域鏈,那么是如何做到 js 沙箱攔截的呢?例如變量test, 理論上說,當前作用域鏈沒有test變量,變量會從上一層作用域查找,直到查找到全局作用域,但是,實際上只會在_ctx上查找, 原理很簡單,_ctx是一個代理對象,那么我們?nèi)绾问褂肞roxy做攔截,示例代碼如下:

const GLOBALS_WHITE_LISTED =
  "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI," +
  "decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array," +
  "Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt";

const isGloballyWhitelisted = (key) => {
  return GLOBALS_WHITE_LISTED.split(",").includes(key);
};

const hasOwn = (obj, key) => {
  return Object.prototype.hasOwnProperty.call(obj, key);
};

const origin = {};
const _ctx = new Proxy(origin, {
  get(target, key, reciever) {
    if (hasOwn(target, key)) {
      Reflect.get(target, key, reciever);
    } else {
      console.warn(
        `Property ${JSON.stringify(key)} was accessed during render ` +
          `but is not defined on instance.`
      );
    }
  },
  has(target, key) {
    // 如果是 全局對象 返回false,不觸發(fā)get 攔截,從上一層作用域查找變量
    // 如果不是 全局對象 返回true,觸發(fā)get 攔截
    return !isGloballyWhitelisted(key);
  },
});

代碼很簡單,為什么這么簡單的代碼就能做到攔截? 因為 with 語句會觸發(fā) has 攔截,當 has 返回 true,就會 觸發(fā)代理對象 get 攔截,如果返回 false, 則代理對象 get 攔截不會觸發(fā),變量不在當前代理對象查找,直接查找更上一層作用域

本地預(yù)編譯版本

<div>{{test}}</div>
<div>{{Math.floor(1)}}</div>

to

import {
  toDisplayString as _toDisplayString,
  createVNode as _createVNode,
  Fragment as _Fragment,
  openBlock as _openBlock,
  createBlock as _createBlock,
} from "vue";

export function render(_ctx, _cache, $props, $setup, $data, $options) {
  return (
    _openBlock(),
    _createBlock(
      _Fragment,
      null,
      [
        _createVNode("div", null, _toDisplayString(_ctx.a), 1 /* TEXT */),
        _createVNode(
          "div",
          null,
          _toDisplayString(Math.floor(1)),
          1 /* TEXT */
        ),
      ],
      64 /* STABLE_FRAGMENT */
    )
  );
}

從上面的代碼我們可以發(fā)現(xiàn),非白名單標識符都添加了_ctx 變量前綴,那么是如何做到的呢?當本地編譯 template 時,處于轉(zhuǎn)換階段時會對 變量表達式節(jié)點NodeTypes.SIMPLE_EXPRESSION進行添加前綴處理,示例代碼如下:

const GLOBALS_WHITE_LISTED =
  "Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI," +
  "decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array," +
  "Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt";

const isGloballyWhitelisted = (key) => {
  return GLOBALS_WHITE_LISTED.split(",").includes(key);
};
const isLiteralWhitelisted = (key)=>{
  return 'true,false,null,this'.split(',').includes(key)
}
export function processExpression(
  node
) {
  const rewriteIdentifier = (raw) => {
    return `_ctx.${raw}`
  }
  const rawExp = node.content
  if (isSimpleIdentifier(rawExp)) {
    const isAllowedGlobal = isGloballyWhitelisted(rawExp)
    const isLiteral = isLiteralWhitelisted(rawExp)
    if (!isAllowedGlobal && !isLiteral) {
      node.content = rewriteIdentifier(rawExp)
    }
    return node
  }

當然上面的代碼只是簡化版本,原版插件還做了精確到了__props $setup,減短變量查詢路徑,提高性能,還有通過babel編譯復(fù)雜表達式比如:箭頭函數(shù)。

總結(jié)

整個 vue3 js 沙箱機制就解釋結(jié)束了,當初瀏覽器編譯版本困擾了我很久,因為不知道 has 可以攔截 with 語句變量查詢

以上就是詳解vue3的沙箱機制的詳細內(nèi)容,更多關(guān)于vue3 沙箱機制的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue.js中修飾符.stop的用法解析

    vue.js中修飾符.stop的用法解析

    這篇文章主要介紹了vue.js中修飾符.stop的用法解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Vue中的無限加載vue-infinite-loading的方法

    Vue中的無限加載vue-infinite-loading的方法

    本篇文章主要介紹了Vue中的無限加載vue-infinite-loading的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • vue中實現(xiàn)滾動加載更多的示例

    vue中實現(xiàn)滾動加載更多的示例

    下面小編就為大家?guī)硪黄獀ue中實現(xiàn)滾動加載更多的示例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • Vue.js暴露方法給WebView的使用操作

    Vue.js暴露方法給WebView的使用操作

    這篇文章主要介紹了Vue.js暴露方法給WebView的使用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解vue.js下引入百度地圖jsApi的兩種方法

    詳解vue.js下引入百度地圖jsApi的兩種方法

    這篇文章主要介紹了詳解vue.js下引入百度地圖jsApi的兩種方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Vue3中的常見組件通信之mitt使用詳解

    Vue3中的常見組件通信之mitt使用詳解

    這篇文章主要介紹了Vue3中的常見組件通信之mitt使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 解決前端調(diào)用后端接口返回200但數(shù)據(jù)返回的是html標簽

    解決前端調(diào)用后端接口返回200但數(shù)據(jù)返回的是html標簽

    這篇文章主要給大家介紹了關(guān)于如何解決前端調(diào)用后端接口返回200但數(shù)據(jù)返回的是html標簽的相關(guān)資料,文中通過圖文將解決的過程介紹的非常詳細,對同樣遇到這個問題的朋友具有一定的參考解決價值,需要的朋友可以參考下
    2024-05-05
  • vue中的雙向數(shù)據(jù)綁定原理與常見操作技巧詳解

    vue中的雙向數(shù)據(jù)綁定原理與常見操作技巧詳解

    這篇文章主要介紹了vue中的雙向數(shù)據(jù)綁定原理與常見操作技巧,結(jié)合實例形式詳細分析了vue中雙向數(shù)據(jù)綁定的概念、原理、常見操作技巧與相關(guān)注意事項,需要的朋友可以參考下
    2020-03-03
  • vue實現(xiàn)右鍵彈出菜單

    vue實現(xiàn)右鍵彈出菜單

    這篇文章主要為大家詳細介紹了vue實現(xiàn)右鍵彈出菜單,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • elementui實現(xiàn)表格自定義排序的示例代碼

    elementui實現(xiàn)表格自定義排序的示例代碼

    本文主要介紹了elementui實現(xiàn)表格自定義排序的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2023-07-07

最新評論

夏邑县| 邹平县| 黔东| 拉萨市| 蕉岭县| 巴林左旗| 德兴市| 汕头市| 红原县| 稻城县| 建水县| 广东省| 安阳市| 漠河县| 泗洪县| 孟村| 阿荣旗| 手机| 鸡泽县| 新平| 临潭县| 敦煌市| 东乡族自治县| 颍上县| 民和| 泸西县| 桦南县| 玛纳斯县| 襄汾县| 阳西县| 巨野县| 碌曲县| 鸡西市| 普陀区| 保山市| 旌德县| 广河县| 文水县| 封开县| 锡林浩特市| 兴海县|