Мне нужно использовать функцию, к которой у меня есть доступ только в кавычках, поэтому это строка.
Допустим, функция называется "м". Функция представляет собой пакет NPM. Я импортирую его в свой проект с помощью 'require'.
Предположим, что строка дана мне другой функцией. Поэтому у меня нет возможности просто удалить кавычки.
const m = require('mithril')
let vnode = "m('p', 'text')" // I need this string as a function
Я сделал свой поиск по сети и придумал два ответа. Использование eval() или Function().
Теперь eval
работает, как я ожидаю. Тем не менее я обнаружил много упоминаний о том, что eval()
- это зло, медленно и его следует избегать, даже если я думаю, что пришло время его использовать. Я пытаюсь создать одностраничное приложение на страницах github - просто для вашей информации - возможно, eval()
можно использовать в этом случае.
И Function()
действует странно. Когда я делаю Function("m('p', 'text')")
, он возвращает это (в виде строки):
function anonymous( ) { m("p", "text" ) }
... и когда я называю это Function("m('p', 'text')")()
, она возвращает ошибку, говоря:
ReferenceError: m is not defined
Я попытался снова require
mithril
модуль в вызове Function()
, но на этот раз он выдает ошибку о том, что require
не определен. Я предполагаю, что это потому, что Function
происходит из другой среды, а не из Nodejs.
Я просто ожидаю поведение функции eval
, без страха быть взломанным.
Есть идеи?
РЕДАКТИРОВАТЬ (пояснить далее):
Я заметил, что спрашиваю Y в проблеме X/Y. Вот Х моей проблемы.
Я развертываю одностраничное приложение на страницах Github с помощью Mithril JS. (мой репо)
Там мне нужно визуализировать математические выражения, в которые входит KaTeX.
KaTeX поставляется с простым API, renderToString()
возвращает HTML-элемент, который визуализируется в хорошо визуализированное математическое выражение.
С другой стороны, Mithril JS предоставляет VNodes, специальную функцию для описания HTML-тегов. Пример:
<div class="cont">
<p>
Text
</p>
</div>
... при преобразовании в vnodes...
m('div', {class:'cont'}, [
m('p', 'Text')
])
Теперь, чтобы Mithril правильно просматривал HTML-вывод KaTeX, тег html должен быть переведен во Vnodes. Я нашел конвертер здесь
Я добавил код конвертера в свой проект и импортировал его как функцию. Проблема, с которой я здесь сталкиваюсь, заключается в том, что конвертер прекрасно конвертирует HTML-структуры в VNodes, но возвращает их в виде строки в кавычках...
Решения, которые я могу придумать:
eval()
, которая делает то, что я хочу, но проблемы с безопасностью печально известны.Есть идеи другие?
Я прочитал ваш пост редактирования и не могу не задаться вопросом, почему вы должны конвертировать html
в vnode
, вместо того, чтобы передавать html напрямую в визуализированный vnode
?
После монтирования мифрилового компонента он вернет DOM-узел в oncreate
жизненного цикла oncreate
. Таким образом, вы можете написать функцию mathRenderer
следующим образом:
const renderMath = mathHTML => ({
oncreate: ({ dom }) => {
dom.innerHTML = mathHTML;
},
view: vnode => m("div", "math expression")
});
Вероятно, было бы более элегантно преобразовать строку eval
-like в массив параметров, а затем вызвать m
с этими параметрами. Например, если параметры всегда являются строками, разделенными символами '
s:
// const m = require('mithril')
// for demonstration purposes:
const m = (...args) => console.log('called with ' + args.join(','));
const vnode = "m('p', 'text')"
let match;
const pattern = /'([^']+)'/g;
const args = [];
while (match = pattern.exec(vnode)) {
args.push(match[1]);
}
m.apply(undefined, args);
Если имя функции также может меняться, то вместо отдельной переменной используйте объект с ключом m
:
// const m = require('mithril')
// for demonstration purposes:
const fns = {
m: (...args) => console.log('called with ' + args.join(','))
};
const vnode = "m('p', 'text')";
const fnName = vnode.match(/^[^(]+/)[0];
let match;
const pattern = /'([^']+)'/g;
const args = [];
while (match = pattern.exec(vnode)) {
args.push(match[1]);
}
fns[fnName].apply(undefined, args);
span.katex
, а другой - список со многими другими функциями m()
включая много списков в качестве второго аргумента и так далее. Внутри этих вложенных списков функций m()
некоторые из них имеют вышеупомянутые списки в качестве третьего аргумента, а вторым аргументом является JSON, описывающий атрибуты и значения тегов HTML. Вы можете перейти к следующим фламам, чтобы увидеть типичный vnode, с которым мне нужно иметь дело. Есть другие идеи?
eval
? (Ваша ссылка, кажется, не работает, лучше всего разместить информацию в самом вопросе)
Поскольку моя проблема может иметь много решений на разных этапах, вот как решить ReferenceError: m is not defined
проблема.
Как это описано в MDN, существует проблема закрытия с функцией Function
. Чтобы обойти это, можно указать параметр для Function
и передать переменную m
(которая определена только в локальной области видимости) в качестве аргумента.
const m = require('mithril');
const f = new Function("m", "return m('p', {class:'red'}, 'text')");
f(m);
Большое спасибо Сами Хульт, который ответил в оригинальном месте: qaru.site/questions/16847592/...