文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue3的沙箱机制是什么

2023-06-14 13:08

关注

今天就跟大家聊聊有关vue3的沙箱机制是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

vue3 沙箱主要分两种

  1. 浏览器编译版本,浏览器版本是使用with语法加上proxy代理拦截

  2. 本地预编译版本,通过在模版预编译阶段转换阶段,使用转换插件transformExpression将非白名单标识符挂在在组件代理对象下

浏览器编译版本

render 函数编译结果

<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 ),          _createVNode(            "div",            null,            _toDisplayString(Math.floor(1)),            1           ),        ],        64       )    );  }};

从上面的代码,我们能发现,变量标识符没有增加前缀,只是用with语法包裹了一下,延长作用域链,那么是如何做到 js 沙箱拦截的呢?例如变量test,理论上说,当前作用域链没有test变量,变量会从上一层作用域查找,直到查找到全局作用域,但是,实际上只会在_ctx上查找,原理很简单,_ctx是一个代理对象,那么我们如何使用Proxy做拦截,示例代码如下:

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,不触发get 拦截,从上一层作用域查找变量    // 如果不是 全局对象 返回true,触发get 拦截    return !isGloballyWhitelisted(key);  },});

代码很简单,为什么这么简单的代码就能做到拦截?
因为 with 语句会触发 has 拦截,当 has 返回 true,就会 触发代理对象 get 拦截,如果返回 false, 则代理对象 get 拦截不会触发,变量不在当前代理对象查找,直接查找更上一层作用域

本地预编译版本

<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 ),        _createVNode(          "div",          null,          _toDisplayString(Math.floor(1)),          1         ),      ],      64     )  );}

从上面的代码我们可以发现,非白名单标识符都添加了_ctx 变量前缀,那么是如何做到的呢?当本地编译 template 时,处于转换阶段时会对 变量表达式节点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编译复杂表达式比如:箭头函数。

看完上述内容,你们对vue3的沙箱机制是什么有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯