@Ui3

Как лучше создать дерево через Proxy?

Есть код, но он не учитывает вложенность.
const builder = (cb) => {
  let res = [];
  let cur;

  let prox = new Proxy(() => {}, {
    apply(target, _, ...args) {
      if (!cur.attrs) {
        cur.attrs = args;
      } else {
        cur.inner = args;
      }
      return prox;
    },
    get(target, name) {
      if (name === "__build") {
        return () => res;
      }
      cur = { name };
      res.push(cur);
      return prox;
    },
  });

  return cb(prox);
};


В таком случае не учитывает:
const res = builder((b) =>
  b.div(`id="div"`)("Hello").input.button(`id="btn"`)(
    "before span",
    b.span(`id="span"`)("inner span"),
    "after span"
  )
);
console.log(res.__build());


А вот так норм:
const res = builder((b) =>
  b.div(`id="div"`)("Hello").input.button(`id="btn"`)(
    "before span",
    "after span"
  )
);
console.log(res.__build());


Подскажите плиз как сделать поддержку вложенности.
Так же интересует можно ли как то красивее сделать, именно без колбеков с таким синтаксисом. Нужно создать кусок html максимально коротким синтаксисом.
  • Вопрос задан
  • 160 просмотров
Решения вопроса 2
liaFcipE
@liaFcipE
const $ = new Proxy(
  {},
  {
    get(_, n) {
      return (children, attrs) => {
        const _ = document.createElement(n);
        [children]
          .flat()
          .forEach(v => v && _.appendChild(typeof v !== "object" ? document.createTextNode(v) : v));
        Object.entries(attrs || {})?.forEach(([k, v]) => _.setAttribute(k, v));
        return _;
      };
    },
  }
);

const DOM = $.div(
  [
    $.span("first child span"),
    $.span([
      "second child span",
      $.button("button inside second span", { type: "button", id: "nicebutton" }),
    ]),
  ],
  { id: "root" }
);

console.log(DOM);


648c6fc8a7407953194956.png
Ответ написан
@Ui3 Автор вопроса
Сделал так:
const $ = new Proxy(() => {}, {
  apply(t, _, v) {
    return v.join("");
  },
  get(_, tag) {
    return (attrs, ...children) => {
      return (
        "<" +
        tag +
        (attrs ? " " + attrs : "") +
        (children.length ? ">" + children.join("") + "</" + tag + ">" : " />")
      );
    };
  },
});

const DOM = $(
  "Hello World",
  $.input(`value="123"`),
  "Lol",
  $.button(`id="btn"`, "Nice button", $.span(0, "the span"))
);
console.log(DOM);


Получаем:
Hello World<input value="123" />Lol<button id="btn">Nice button<span>the span</span></button>
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы