我正在建造一辆带有刺激的购物车。购物车回顾页面显示多个购物车项目。购物车有单价和数量。每个购物车项组件都有一个数量选择器,当数量编号发生变化时,cartitem元素的总价将被重新计算为totalCartItem = unitPrice x Quantity,如果购物车还必须重新计算totalCartPrice = sum(totalCartItem),则为总价。
以下是html结构的简化
<div class="cart" data-controller='cart'>
<div class="cart-item" data-controller='cart-item'>
<p class='unit-price'>20</p>
<input type="number" name="quantity" value="1">
<p class='total-price' data-target='cart-item.totalPrice' data-action="change->cart-item#update" data-target='cart-item.quantity'>20</p>
</div>
<div class="cart-item" data-controller='cart-item'>
<p class='unit-price'>10</p>
<input type="number" name="quantity" value="2" data-action="change->cart-item#update" data-target='cart-item.quantity'>
<p class='total-price' data-target='cart-item.totalPrice'>20</p>
</div>
<div class="cart-total">
40
</div>
</div>我的购物车项目控制器工作得非常好,并正确地更新了UI中的购物车项目totalPriceFor。
export default class extends Controller {
static targets = ["totalPrice", "quantity"]
static values = {
unitPrice: String,
}
connect() {
console.log("hello from StimulusJS")
}
update(){
this.totalPriceTarget.textContent = parseFloat(this.unitPriceValue) * parseInt(this.quantityTarget.value)
}
}但是,我现在不知道如何更新totalCartPrice。我觉得这应该是封装cartController元素的cartItems的响应性,但是我不知道实现这个目标的正确方法是什么。我觉得我应该为每个购物车的数量在每个数字输入选择器上添加change->cart#update,但是我应该在cart#update方法中添加什么来重新计算每个购物车项目的总数呢?
export default class extends Controller {
static targets = ["total"]
connect() {
console.log("hello from StimulusJS")
}
update(){
// let details = event.detail;
// this.cartItemChildren.forEach((item) => console.log(item.totalValue))
}
}发布于 2022-06-03 21:59:31
根据刺激文档,从HTML开始总是最好的选择。通过扩展,最好以一种可访问的方式构造您的HTML,并查看浏览器给您带来的东西,而不需要重新发明任何东西。
在构建表单时,最好使用form元素,即使没有提交此表单。https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement
还有一个非常有用的output元素,它帮助您根据某些输入值分配输出值。https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output#attr-for
最后,表单元素有一个DOM,它允许您通过其name属性访问表单的各个部分,这就是form.elements。https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
把这些结合在一起,我们可以从以下HTML开始。
HTML
input都有一个唯一的ID,每个output元素都使用for属性通过这个id引用输入--这对于可访问性来说更好,但是当我们想解析值和更新输出时会很方便。<form class="cart" data-controller='cart' data-action="change->cart#updateTotals">
<div class="cart-item">
<span class='unit-price' data-price-for="cart-item-1">20</span>
x
<input type="number" name="quantity" value="1" id="cart-item-1">
=
<output class="total-price" for="cart-item-1" name="item-total">20</output>
</div>
<div class="cart-item">
<span class='unit-price' data-price-for="cart-item-2">10</span>
x
<input type="number" name="quantity" value="1" id="cart-item-2">
=
<output class="total-price" for="cart-item-2" name="item-total">10</output>
</div>
<div class="cart-total">
Total: <span data-cart-target="total">30</span>
</div>
</form>JavaScript (控制器)
this.element。update方法,并试图更具体地处理updateTotals。elements API获取名称为'item-total'的元素(注意输出名称没有提交)。https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elementsfor和输入的id找到相关的输入元素,然后通过数据属性来找到价格。import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['total'];
connect() {
this.updateTotals();
}
updateTotals() {
// parse the form elements to get all data
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
const cartItems = [...this.element.elements['item-total']].map(
(outputElement) => {
const forId = outputElement.getAttribute('for');
const priceElement = document.querySelector(`[data-price-for='${forId}']`);
const price = Number(priceElement.textContent);
const quantity = Number(document.getElementById(forId).value);
return { outputElement, total: quantity * price };
}
);
// calculate the grand total
const grandTotal = cartItems.reduce(
(runningTotal, { total }) => runningTotal + total,
0
);
// update the grand total
this.totalTarget.textContent = grandTotal;
// update totals for each cart item
cartItems.forEach(({ outputElement, total }) => {
outputElement.textContent = total;
});
console.log('form updated', { grandTotal, cartItems });
}
}https://stackoverflow.com/questions/72476371
复制相似问题