让 JavaScript 等到元素在页面上呈现,然后将 JS 对象绑定到它

Posted

技术标签:

【中文标题】让 JavaScript 等到元素在页面上呈现,然后将 JS 对象绑定到它【英文标题】:Make JavaScript wait until element is rendered on the page an after bind JS object to it 【发布时间】:2021-12-19 09:04:46 【问题描述】:

我正在从事某种项目,它需要动态的前端元素,但我没有时间学习 React 或其他东西。因此,我决定编写一些迷你逻辑,这意味着我向我的 DOM 添加了一些元素,并在将一些 JS 对象绑定到它之后,代表它的逻辑并提供它的方法。您可以在下面看到解释我的问题的示例。

`

function itemhtml(name,price)
  return  `
    <div class="item">
      <span class="item__name">$name</span>
      <span class="item__price">$price$</span>
      <button class="item__delete-button">X</button> 
    </div>
  `


class ContainerObj 
  constructor (self)
    this.self = self
    this.items = []
  
  add(item) 
    this.self.innerHTML += itemHTML(item.name,item.price)
    this.items.push(
      new ItemObj(
        self = this.self.querySelector(".item:last-child")
      )
    )
  


class ItemObj 
  constructor(self)
    this.self = self 
    this._name = self.querySelector(".item__name")
    this._price = self.querySelector(".item__price")
    this._deleteButton = self.querySelector(".item__delete-button")
    this._deleteButton.addEventListener("click",(event)=>
      this.self.remove()
    )
  
  get name() 
    return this._name
  
  get price() 
    return this._price
  
  set name(value) 
      this._name = value
  
  set price(value) 
      this._price = value
  


class AppenderObj 
  constructor (self,container) 
    this.self = self
    this.container = container 
    this._name = self.querySelector(".appender__name")
    this._price = self.querySelector(".appender__price")
    this._addButton = self.querySelector(".appender__add-button")
    this._addButton.addEventListener("click",(event)=>
        this.container.add(
          name:this._name.value,
          price:this._price.value
        )
        this._name.value = ""
        this._price.value = ""
    )
  


items = [
  
    name: "Apple",
    price: 5
  ,
  
    name: "Pen",
    price: 20
  
];

$container = new ContainerObj(
  self = document.querySelector("#container")
)

$appender = new AppenderObj(
  self = document.querySelector("#appender"),
  container = $container
)


items.forEach((item)=>
  $container.add(item)
)
#container
  border:1px solid black;

#appender
  margin-top: 10px;

.item
  display: flex;
  justify-content: space-between;
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
<div id="container">    </div>
<div id="appender">
    <input class="appender__name" type="text" placeholder="Name">
    <input class="appender__price" type="text" placeholder="Price">
    <input class="appender__add-button" type="button" value="add">
</div>

`

我不明白为什么它会真正添加但不能

感谢您的建议... 尽量少写:) 如果没有足够的问题信息,我会发送其余的。

【问题讨论】:

请澄清这里的问题 - sn-p 看起来工作正常。您可以添加新元素或删除它,这是什么问题? OK - 我看到你只能删除最后一项 如果你没有时间或勇气去学习一个“大”的框架,我推荐Knockout。它简洁、优雅、快速上手、没有依赖关系,并且它完全完成了您在此处尝试做的事情。 【参考方案1】:

问题在于您在ContainerObj 类中执行this.self.innerHTML += itemHTML(item.name,item.price) 的HTML 的串联。如果你改用insertAdjactentHTML,像这样:

this.self.insertAdjacentHTML('beforeend', itemHTML( item.name, item.price ) );

事件监听器将正常工作。

function itemHTML(name,price)
  return  `
    <div class="item">
      <span class="item__name">$name</span>
      <span class="item__price">$price$</span>
      <button class="item__delete-button">X</button> 
    </div>
  `;
;

class ContainerObj 
  constructor(n)
    this.self=n;
    this.items=[];
  
  
  add(item) 
    /* do not concatenate the HTML, insert new like this */
    this.self.insertAdjacentHTML('beforeend', itemHTML( item.name, item.price ) );
    this.items.push(
      new ItemObj( this.self.querySelector(".item:last-child") )
    )
  
;

class ItemObj 
  constructor(n)
    this._name = n.querySelector(".item__name");
    this._price = n.querySelector(".item__price");
    this._deleteButton = n.querySelector(".item__delete-button");
    
    this._deleteButton.addEventListener("click",(event)=>
      n.remove();
    )
  
  get name() 
    return this._name;
  
  get price() 
    return this._price;
  
  set name(value) 
      this._name = value;
  
  set price(value) 
      this._price = value;
  
;

class AppenderObj 
  constructor (n,container) 
    this.container = container;
    this._name = n.querySelector(".appender__name");
    this._price = n.querySelector(".appender__price");
    this._addButton = n.querySelector(".appender__add-button");
    
    this._addButton.addEventListener("click",(event)=>
        this.container.add(
          name:this._name.value,
          price:this._price.value
        )
        
        this._name.value = "";
        this._price.value = "";
    );
  
;


$container = new ContainerObj(
  document.querySelector("#container")
);
$appender = new AppenderObj(
  document.querySelector("#appender"),$container
);



const items = [
  
    name: "Apple",
    price: 5
  ,
  
    name: "Pen",
    price: 20
  
];

items.forEach(item=>
  $container.add(item)
);
#container
  border:1px solid black;

#appender
  margin-top: 10px;

.item
  display: flex;
  justify-content: space-between;
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
<div id="container"></div>
<div id="appender">
    <input class="appender__name" type="text" placeholder="Name" />
    <input class="appender__price" type="text" placeholder="Price" />
    <input class="appender__add-button" type="button" value="add" />
</div>

【讨论】:

以上是关于让 JavaScript 等到元素在页面上呈现,然后将 JS 对象绑定到它的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法让 cURL 等到页面的动态更新完成?

JS高级程序设计第三版——在HTML中使用JavaScript

在包含 SVG 标记元素的页面上使用基本标记无法呈现标记

从 Java 检索网页上动态呈现的 SVG

Flutter:如何让页面等到数据加载?

Vue Router - 路由加载后调用函数