如何在两个JavaScript文件中复用相同函数?
问题描述
我用JavaScript开发了一个简单的电商商店,原本采用单HTML文件+单JS文件的架构,包含商品展示和购物车功能。现在需要将其拆分为两个HTML文件(商品页、购物车页)及对应的两个JS文件。目前函数存在相互依赖关系,需要在两个JS文件中复用部分函数,我已尝试过import/export语法以及通过localStorage传递数据的方式,请问如何实现跨JS文件复用相同函数?
原单页HTML代码
<!DOCTYPE html> <html id="lang1" lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta id="mode" name="color-scheme" content="light"> <link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style/scss.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha512-MV7K8+y+gLIBoVD59lQIYicR65iaqukzvf/nwasF0nqhPay5w/9lJmVM2hMDcnK1OnMGCdVK+iQrJ7lzPJQd1w==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <title>Hamburger</title> </head> <body> <div class="square"> <picture> <source media="(min-width:751px)" srcset="https://cdn-icons-png.flaticon.com/512/5499/5499206.png"> <img> </picture> <div class="lang"><a href="/cart/cart.html"><i class="fa-solid fa-cart-shopping"></i></a><div class="lang1"></div></div> <div class="height"><i id="bar" class="fa-solid fa-bars"></i> </div> <div> <ul class="menu hidden" id="menu" > <li id="home">Home</li> <li id="about">About</li> <li id="contact">Contact</li> </ul> </div> <div class="grid" id="container"> </div> </div> <div class="footer"> <div>copyright<i class="fa-regular fa-copyright"></i>Sneakerstore</div> <br> <div>info@sneakerstore.com</div> <i class="fa-brands fa-facebook-messenger"></i> <i class="fa-brands fa-instagram"></i> </div> <div class="shoppingcontainer"> </div> <button class="clearCart">Clear cart</button> <div> <div class="subtotal">Total price(0 items):</div> <button class="checkout">Checkout</button> </div> <script src="/script.js"></script> </body> </html>
原单页JS代码
const buyBtn = document.querySelector('button') let cartNr = document.getElementById('cartNr') const lang1 = document.querySelector('.lang1') cartNr = 1 //add to cart array let cart = [] //hämta från firebase render in DOM const wrapper = document.querySelector('.grid') let lager = 10 async function getProducts(){ try{ const baseURL = 'https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/' const url = baseURL + 'Products.json' const response = await fetch(url) let data = await response.json() console.log(data) const generatedHTML = Object.keys(data).reduce((accum, i) => wrapper.innerHTML= accum + `<div class="div-container"> <div class="image"><img class="skor-img" src="${data[i].img}" alt=""></div> <div class="beskrivning"><strong class="text">${data[i].namn}</strong><br><br><p class="text2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatum quas quasi praesentium voluptates minima deleniti enim sint quidem expedita sed ut officiis hic dolore dolor quaerat atque earum tenetur necessitatibus, maiores odit illo molestias voluptatibus adipisci quos? Vero necessitatibus tempora inventore, accusamus illo, maiores quisquam quo odit nesciunt qui nisi hic est non aliquid ex numquam earum aperiam? Recusandae excepturi eligendi nemo magni praesentium assumenda, placeat rem numquam illo provident earum officia eveniet tempora commodi laborum molestias animi expedita nihil sint explicabo quos modi at. Odio vel a voluptas explicabo pariatur.</p></div> <div class="pris"><p>lager: ${lager}</p> <button class="euro" onclick="addToCart(${data[i].id})">Buy:${data[i].pris}kr</button></div></div>` ,'' ) document.getElementById('container').innerHTML =generatedHTML }catch(error){ console.log(error) } } getProducts() //add products to cart function from firebase function addToCart(id){ async function getAndAddToCart(){ const baseURL = 'https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/' const url = baseURL + 'Products.json' const response = await fetch(url) let data = await response.json() lang1.innerHTML = `<div id="cartNr">${cartNr++}</div>` if(cart.some((item) => item.id === id)){ changeNumberOfUnit("plus", id) }else{ const arrayOfProductObjects = Object.values(data); const theProductToAdd = arrayOfProductObjects.find(product => product.id === id); console.log(theProductToAdd) cart.push({ ...theProductToAdd, numberOfUnits: 1 }) console.log(cart) } } getAndAddToCart() //updateCart() } //save in sessionstorage // function saveinLocalStorage(){ // localStorage.setItem('addedItems', JSON.stringify(cart)) // console.log(cart) // } // const getLocalStorage = JSON.parse(localStorage.getItem('addedItems')) // console.log(getLocalStorage) // cart.push(getLocalStorage) ///update Cart function updateCart(){ renderCartItems() renderSubtotal() } /// set TotalPrice const subtotal = document.querySelector('.subtotal') function renderSubtotal(){ let totalPrice = 0 cart.forEach((item) =>{ totalPrice += item.pris * item.numberOfUnits }) subtotal.innerHTML = `Total price ${totalPrice}kr:` } ///render shoppingCart in DOM const shoppingcontainer = document.querySelector('.shoppingcontainer') function renderCartItems(){ console.log(cart) shoppingcontainer.innerHTML = '' cart.forEach((item ) =>{ shoppingcontainer.innerHTML += ` <div class="cart-item"> <div class="item-info"> <h4>${item.namn}</h4> </div> <div class="unit-price"> <small>${item.pris}kr</small> </div> <div class="units"> <div class="btnminus" onclick"changeNumberOfUnit('minus', ${item.id})">-</div> <div class="number">${item.numberOfUnits}</div> <div class="btnplus" onclick"changeNumberOfUnit('plus', ${item.id})">+</div> </div> </div> ` }) } ///ClearCart remove items from cart const clearCart = document.querySelector('.clearCart') clearCart.addEventListener('click', (e) =>{ e.preventDefault() removeItemsFromCart() }) function removeItemsFromCart(){ //saveinSessionStorage() cart = [] updateCart() } function changeNumberOfUnit(action, id){ cart = cart.map((item) =>{ let oldnumberOfUnits = item.numberOfUnits if(item.id === id){ if(action === 'minus' && oldnumberOfUnits){ oldnumberOfUnits-- }else if(action === 'plus' && oldnumberOfUnits < item.lager){ oldnumberOfUnits++ } } return{ ...item, numberOfUnits: oldnumberOfUnits } }) updateCart() } //checkout buy //Om användaren väljer att genomföra köpet ska saldot på firebase uppdateras och kundvagnen tömmas const checkoutbtn = document.querySelector('.checkout') checkoutbtn.addEventListener('click', e => { e.preventDefault() checkout() }) //checkout function checkout( id){ async function patchPost(obj){ const baseURL = `https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/` const url = baseURL + 'Products.json' const init = { method: 'PATCH', body: JSON.stringify(obj), headers: { "Content-type": "application/json; charset=UTF-8", } }; const response = await fetch(url, init) const data = await response.json() console.log(data) } cart = cart.map((item) =>{ let newLager = item.lager - item.numberOfUnits if(item.id === id){ } return{ lager: newLager } }) let obj = cart.reduce(function(acc, cur, i) { acc[i] = cur; return acc[i]; }, {}); patchPost(obj) console.log(obj) removeItemsFromCart() }
解决方案
一、抽离公共函数到独立模块(推荐ES模块方式)
把两个页面都需要用到的函数(比如购物车数据操作、数量修改、总价计算等)抽出来放到单独的common.js文件中,通过ES模块的export/import语法实现复用,同时结合localStorage同步购物车数据。
1. 创建公共模块文件 common.js
// 保存购物车到localStorage export function saveCartToLocalStorage(cart) { localStorage.setItem('cart', JSON.stringify(cart)); } // 从localStorage读取购物车 export function getCartFromLocalStorage() { return JSON.parse(localStorage.getItem('cart')) || []; } // 修改商品数量 export function changeNumberOfUnit(action, id, cart) { return cart.map((item) => { let oldnumberOfUnits = item.numberOfUnits; if (item.id === id) { if (action === 'minus' && oldnumberOfUnits > 1) { oldnumberOfUnits--; } else if (action === 'plus' && oldnumberOfUnits < item.lager) { oldnumberOfUnits++; } } return { ...item, numberOfUnits: oldnumberOfUnits }; }); } // 计算购物车总价 export function calculateSubtotal(cart) { return cart.reduce((total, item) => total + item.pris * item.numberOfUnits, 0); } // 清空购物车 export function clearCart() { localStorage.removeItem('cart'); return []; }
2. 商品页JS(product.js)调用公共函数
import { saveCartToLocalStorage, getCartFromLocalStorage, changeNumberOfUnit } from './common.js'; // 初始化购物车数据 let cart = getCartFromLocalStorage(); const lang1 = document.querySelector('.lang1'); // 更新购物车数量显示 function updateCartCount() { lang1.innerHTML = `<div id="cartNr">${cart.length}</div>`; } // 获取商品并渲染 const wrapper = document.querySelector('.grid'); async function getProducts() { try { const baseURL = 'https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/'; const url = baseURL + 'Products.json'; const response = await fetch(url); let data = await response.json(); let generatedHTML = ''; Object.keys(data).forEach(i => { generatedHTML += ` <div class="div-container"> <div class="image"><img class="skor-img" src="${data[i].img}" alt=""></div> <div class="beskrivning"><strong class="text">${data[i].namn}</strong><br><br><p class="text2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptatum quas quasi praesentium voluptates minima deleniti enim sint quidem expedita sed ut officiis hic dolore dolor quaerat atque earum tenetur necessitatibus, maiores odit illo molestias voluptatibus adipisci quos? Vero necessitatibus tempora inventore, accusamus illo, maiores quisquam quo odit nesciunt qui nisi hic est non aliquid ex numquam earum aperiam? Recusandae excepturi eligendi nemo magni praesentium assumenda, placeat rem numquam illo provident earum officia eveniet tempora commodi laborum molestias animi expedita nihil sint explicabo quos modi at. Odio vel a voluptas explicabo pariatur.</p></div> <div class="pris"><p>lager: ${data[i].lager}</p> <button class="euro" onclick="addToCart(${data[i].id})">Buy:${data[i].pris}kr</button></div> </div> `; }); document.getElementById('container').innerHTML = generatedHTML; } catch (error) { console.log(error); } } // 添加商品到购物车 async function addToCart(id) { const baseURL = 'https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/'; const url = baseURL + 'Products.json'; const response = await fetch(url); let data = await response.json(); const arrayOfProductObjects = Object.values(data); const theProductToAdd = arrayOfProductObjects.find(product => product.id === id); if (cart.some(item => item.id === id)) { cart = changeNumberOfUnit('plus', id, cart); } else { cart.push({ ...theProductToAdd, numberOfUnits: 1 }); } saveCartToLocalStorage(cart); updateCartCount(); } // 初始化 getProducts(); updateCartCount(); // 暴露addToCart到全局,因为HTML的onclick需要调用 window.addToCart = addToCart;
3. 购物车页JS(cart.js)调用公共函数
import { saveCartToLocalStorage, getCartFromLocalStorage, changeNumberOfUnit, calculateSubtotal, clearCart } from '../common.js'; let cart = getCartFromLocalStorage(); const shoppingcontainer = document.querySelector('.shoppingcontainer'); const subtotalEl = document.querySelector('.subtotal'); // 渲染购物车商品 function renderCartItems() { shoppingcontainer.innerHTML = ''; if (cart.length === 0) { shoppingcontainer.innerHTML = '<p>购物车为空</p>'; return; } cart.forEach(item => { shoppingcontainer.innerHTML += ` <div class="cart-item"> <div class="item-info"> <h4>${item.namn}</h4> </div> <div class="unit-price"> <small>${item.pris}kr</small> </div> <div class="units"> <div class="btnminus" onclick="updateUnitCount('minus', ${item.id})">-</div> <div class="number">${item.numberOfUnits}</div> <div class="btnplus" onclick="updateUnitCount('plus', ${item.id})">+</div> </div> </div> `; }); } // 更新商品数量并同步 function updateUnitCount(action, id) { cart = changeNumberOfUnit(action, id, cart); saveCartToLocalStorage(cart); renderCartItems(); renderSubtotal(); } // 渲染总价 function renderSubtotal() { const total = calculateSubtotal(cart); subtotalEl.innerHTML = `Total price ${total}kr:`; } // 清空购物车按钮事件 document.querySelector('.clearCart').addEventListener('click', () => { cart = clearCart(); renderCartItems(); renderSubtotal(); }); // 结账按钮事件(保留原有逻辑) document.querySelector('.checkout').addEventListener('click', async () => { async function patchPost(obj) { const baseURL = `https://webstore-22fa4-default-rtdb.europe-west1.firebasedatabase.app/`; const url = baseURL + 'Products.json'; const init =
相关产品推荐
相关产品推荐

