首页 > 解决方案 > 如何将 JSON 字符串转换并执行为带参数的函数?

问题描述

IntersectionObserver 旨在在某些滚动点执行功能。我在回调下的 data-options 属性中给出了这些函数。

现在的问题是,如何触发相应的功能?看起来像这样:

modal ('default-modal');
notify ('subscribe-newsletter', 'bottomLeft');

我的带有 JSON 字符串的 HTML 节点:

<section id="section-90" data-trigger="observer" data-options="{'root':null,'rootMargin':'0px','threshold':[0,0.1,0.2,0.3,0.4,0.7,1],'callbacks':{'modal':[{'id':'default-modal','position':'center'}],'notify':[{'id':'subscribe-newsletter','position':'bottomLeft'},{'id':'become-distributor','position':'bottomRight'}]}}">

格式化的 JSON(仅在这里以获得更好的概述:):

{
  "root": "null",
  "rootMargin": "0px",
  "threshold": [
    0,
    0.25,
    0.5,
    0.75,
    1
  ],
  "callback": {
    "modal": [
      {
        "id": "default-modal",
        "position": "center"
      }
    ],
    "notify": [
      {
        "id": "subscribe-newsletter",
        "position": "bottomLeft"
      },
      {
        "id": "become-distributor",
        "position": "bottomRight"
      }
    ]
  }
}

使用选项解析字符串并过滤回调

let str = target.dataset.options; // options from HTML node
let optStr = str.replace(/'/g, '"');
options = JSON.parse(optStr);
let callbacks = options.callbacks; // store only callbacks

for (const key of Object.keys(callbacks)) {
  console.log(key, callbacks[key]);

  /*
  Output:
  modal -> [{"id":"default-modal"}]
  notify -> [{"id":"subscribe-newsletter","position":"bottomLeft"},{"id":"become-distributor","position":"bottomRight"}]
  */
}

如何使用输出中的参数调用函数?

modal('default-modal');
notify('subscribe-newsletter', bottomLeft)

标签: javascriptjson

解决方案


可以通过调用以非常hacky 的方式执行此操作,eval()但强烈建议不要这样做,因为它允许各种 XSS 攻击。将函数列入白名单并显式调用它们会好得多。请参阅下面的示例。

//fake funciton calls
function modal(x) { console.log('fake modal() call', x); }
function notify(a, b) { console.log('fake notify() call', a, b); }

//parse the HTML string
var elem = document.getElementById('section-90');
var optionsStr = elem.getAttribute('data-options').replace(/'/g, '"');
var options = JSON.parse(optionsStr);

//Call the known functions
Object.keys(options.callbacks).forEach(key => {
  if (key === "modal") {
    modal(options.callbacks.modal[0].id)
  } else if (key === "notify") {
    notify(options.callbacks.notify[0].id, options.callbacks.notify[1].id)
  } else {
    throw Error("Unknown function attempted to be called!");
  }
});
<section id="section-90" data-trigger="observer" data-options="{'root':null,'rootMargin':'0px','threshold':[0,0.1,0.2,0.3,0.4,0.7,1],'callbacks':{'modal':[{'id':'default-modal','position':'center'}],'notify':[{'id':'subscribe-newsletter','position':'bottomLeft'},{'id':'become-distributor','position':'bottomRight'}]}}">


推荐阅读