【问题标题】:Javascript ES6 Booklist bugJavascript ES6 书单错误
【发布时间】:2020-11-12 03:26:56
【问题描述】:

应用演示https://scannerbug.netlify.app/

这是一个简单的网络应用程序,它根据 API 检查扫描的条形码,并将返回的数据添加到书单中。

问题是,我第一次扫描一本书时,只添加了一本书,第二次添加了两本书(这使得它变成了三本书),第三次添加了三本书(这使得它变成了六本书列表)。这样,当我只扫描了三本书时,我就在列表中找到了 6 本书。

谁能帮帮我?如果您无法理解我的代码中的某些内容,我会提供所需的任何信息。

Pastebin JS 代码:https://pastebin.com/dj7Pi1JE

//SWIPER SETTING
document.addEventListener("DOMContentLoaded", () => {
    const swiper = new Swiper(".swiper-container", {
        effect: "coverflow",
        grabCursor: true,
        centeredSlides: true,
        slidesPerView: "auto",
        coverflowEffect: {
            rotate: 60,
            stretch: 0,
            depth: 150,
            modifier: 1,
            slideShadows: true,
        },
    });
});
//BOOK CLASS
 
class Book {
    constructor(url, cover, title, author, pages, isbn) {
        this.url = url;
        this.cover = cover;
        this.title = title;
        this.author = author;
        this.pages = pages;
        this.isbn = isbn;
    }
}
 
//UI CLASS
class UI {
    static displayBooks() {
        // let swiper = document.querySelector(".swiper-container").swiper;
        // swiper.removeAllSlides();
        const storedBooks = [
            {
                url: "www.google.com",
                title: "Test Title",
                author: "Test Author",
                pages: "230",
                isbn: "9778621466124",
            },
            {
                url: "www.isbndb.com",
                title: "Test Title",
                author: "Test Author",
                pages: "100",
                isbn: "9778621466124",
            },
        ];
 
        const books = storedBooks;
 
        books.forEach((book) => UI.addBookToList(book));
    }
 
    static addBookToList(book) {
        //INIT SWIPER ONLY AFTER ADDING BOOKS
        let swiper = document.querySelector(".swiper-container").swiper;
 
        swiper.appendSlide(`
        <div class="swiper-slide">
            <div class="book-cover">
                <img src="${book.cover}" alt="" />
            </div>
            <div class="book-info">
                <h2 class="book-title">${book.title}</h2>
                <h3 class="book-author">By ${book.author}</h3>
                <p class="book-pages">Pages: ${book.pages}</p>
                <p>ISBN: ${book.isbn}</p>
            </div>
 
            <div class="cta-buttons">
                <a href="${book.url}" class="read-more btn" target="_blank">Read More</a>
                <a href="#" class="delete btn">Remove Book</a>
            </div>
        </div>
        `);
 
        swiper.update();
    }
 
    static deleteBook(element) {
        if (element.classList.contains("delete")) {
            element.parentElement.parentElement.remove();
        }
 
        //INIT SWIPER ONLY AFTER ADDING BOOKS
        let swiper = document.querySelector(".swiper-container").swiper;
        swiper.update();
    }
 
    static clearFields() {
        document.querySelector("#result-form").reset();
    }
}
// STORAGE CLASS
 
//EVENT: DISPLAY BOOKS
document.addEventListener("DOMContentLoaded", UI.displayBooks);
//EVENT ADD A BOOK
function getMovies(searchText) {
    axios
        .get(
            `https://openlibrary.org/api/books?bibkeys=ISBN:${searchText}&format=json&jscmd=data`
        )
        .then((response) => {
            console.log(response);
            let path = `ISBN:${searchText}`;
            let data = response.data[`${path}`];
 
            let cover;
            if (data.cover) {
                cover = data.cover.medium;
            } else {
                cover = "./imgs/book-cover-placeholder.png";
            }
            let url = data.url;
            let title = data.title;
            let author = data.authors[0].name;
            let pages = data.number_of_pages;
            let isbn = searchText;
 
            const book = new Book(url, cover, title, author, pages, isbn);
 
            UI.addBookToList(book);
        })
        .catch((err) => {
            console.log(err);
        });
}
 
// EVENT: REMOVE A BOOK
document.querySelector(".swiper-wrapper").addEventListener("click", (e) => {
    UI.deleteBook(e.target);
});
 
//SCANNER CODE
document.getElementById("start-button").addEventListener("click", function () {
    document.getElementById("search-input").value = "";
    let selectedDeviceId;
    const codeReader = new ZXing.BrowserBarcodeReader();
    console.log("ZXing code reader initialized");
 
    //GET THE VIDEO DEVICE
    codeReader
        .getVideoInputDevices()
        .then((videoInputDevices) => {
            const sourceSelect = document.getElementById("sourceSelect");
            selectedDeviceId = videoInputDevices[0].deviceId;
            if (videoInputDevices.length > 1) {
                videoInputDevices.forEach((element) => {
                    const sourceOption = document.createElement("option");
                    sourceOption.text = element.label;
                    sourceOption.value = element.deviceId;
                    sourceSelect.appendChild(sourceOption);
                });
 
                sourceSelect.onchange = () => {
                    selectedDeviceId = sourceSelect.value;
                };
 
                // const sourceSelectPanel = document.getElementById("sourceSelectPanel");
                // sourceSelectPanel.style.display = "block";
            }
 
            //DECODE BARCODE FROM CAMERA
            (() => {
                codeReader
                    .decodeOnceFromVideoDevice(selectedDeviceId, "video")
                    .then((result) => {
                        let searchText = result.text;
 
                        console.log(result);
                        document.getElementById("search-input").value = searchText;
 
                        //GET MOVIES WHEN ADD BUTTON IS CLICKED
                        document
                            .getElementById("add-button")
                            .addEventListener("click", () => {
                                getMovies(searchText);
 
                                UI.clearFields();
                            });
                    })
                    .catch((err) => {
                        console.error(err);
                    });
            })();
 
            document.getElementById("stop-button").addEventListener("click", () => {
                codeReader.reset();
                console.log("Reset.");
            });
        })
        .catch((err) => {
            console.error(err);
        });
});

【问题讨论】:

    标签: javascript ecmascript-6 dom-manipulation swiperjs


    【解决方案1】:

    问题可能是因为以下部分代码的位置:

    document
        .getElementById("add-button")
        .addEventListener("click", () => {
            getMovies(searchText);
     
            UI.clearFields();
        });
    

    这段代码的 sn-p 向#add-button 元素添加一个事件侦听器每次运行,即在每次扫描之后。

    要使您的代码正常工作,请将其移至顶级 DOMContentLoaded 侦听器,并将其更改为以下内容:

    document
        .getElementById("add-button")
        .addEventListener("click", () => {
            const searchText = document.getElementById("search-input").value;
            if(!searchText) return;
            
            getMovies(searchText);
     
            UI.clearFields();
        });
    

    所以,你应该有这样的东西:

    //SWIPER SETTING
    document.addEventListener("DOMContentLoaded", () => {
        const swiper = new Swiper(".swiper-container", {
            effect: "coverflow",
            grabCursor: true,
            centeredSlides: true,
            slidesPerView: "auto",
            coverflowEffect: {
                rotate: 60,
                stretch: 0,
                depth: 150,
                modifier: 1,
                slideShadows: true,
            },
        });
    });
    //BOOK CLASS
     
    class Book {
        constructor(url, cover, title, author, pages, isbn) {
            this.url = url;
            this.cover = cover;
            this.title = title;
            this.author = author;
            this.pages = pages;
            this.isbn = isbn;
        }
    }
     
    //UI CLASS
    class UI {
        static displayBooks() {
            // let swiper = document.querySelector(".swiper-container").swiper;
            // swiper.removeAllSlides();
            const storedBooks = [
                {
                    url: "www.google.com",
                    title: "Test Title",
                    author: "Test Author",
                    pages: "230",
                    isbn: "9778621466124",
                },
                {
                    url: "www.isbndb.com",
                    title: "Test Title",
                    author: "Test Author",
                    pages: "100",
                    isbn: "9778621466124",
                },
            ];
     
            const books = storedBooks;
     
            books.forEach((book) => UI.addBookToList(book));
        }
     
        static addBookToList(book) {
            //INIT SWIPER ONLY AFTER ADDING BOOKS
            let swiper = document.querySelector(".swiper-container").swiper;
     
            swiper.appendSlide(`
            <div class="swiper-slide">
                <div class="book-cover">
                    <img src="${book.cover}" alt="" />
                </div>
                <div class="book-info">
                    <h2 class="book-title">${book.title}</h2>
                    <h3 class="book-author">By ${book.author}</h3>
                    <p class="book-pages">Pages: ${book.pages}</p>
                    <p>ISBN: ${book.isbn}</p>
                </div>
     
                <div class="cta-buttons">
                    <a href="${book.url}" class="read-more btn" target="_blank">Read More</a>
                    <a href="#" class="delete btn">Remove Book</a>
                </div>
            </div>
            `);
     
            swiper.update();
        }
     
        static deleteBook(element) {
            if (element.classList.contains("delete")) {
                element.parentElement.parentElement.remove();
            }
     
            //INIT SWIPER ONLY AFTER ADDING BOOKS
            let swiper = document.querySelector(".swiper-container").swiper;
            swiper.update();
        }
     
        static clearFields() {
            document.querySelector("#result-form").reset();
        }
    }
    // STORAGE CLASS
     
    //EVENT: DISPLAY BOOKS
    document.addEventListener("DOMContentLoaded", UI.displayBooks);
    //EVENT ADD A BOOK
    function getMovies(searchText) {
        axios
            .get(
                `https://openlibrary.org/api/books?bibkeys=ISBN:${searchText}&format=json&jscmd=data`
            )
            .then((response) => {
                console.log(response);
                let path = `ISBN:${searchText}`;
                let data = response.data[`${path}`];
     
                let cover;
                if (data.cover) {
                    cover = data.cover.medium;
                } else {
                    cover = "./imgs/book-cover-placeholder.png";
                }
                let url = data.url;
                let title = data.title;
                let author = data.authors[0].name;
                let pages = data.number_of_pages;
                let isbn = searchText;
     
                const book = new Book(url, cover, title, author, pages, isbn);
     
                UI.addBookToList(book);
            })
            .catch((err) => {
                console.log(err);
            });
    }
     
    // EVENT: REMOVE A BOOK
    document.querySelector(".swiper-wrapper").addEventListener("click", (e) => {
        UI.deleteBook(e.target);
    });
     
    //SCANNER CODE
    document.getElementById("start-button").addEventListener("click", function () {
        document.getElementById("search-input").value = "";
        let selectedDeviceId;
        const codeReader = new ZXing.BrowserBarcodeReader();
        console.log("ZXing code reader initialized");
     
        //GET THE VIDEO DEVICE
        codeReader
            .getVideoInputDevices()
            .then((videoInputDevices) => {
                const sourceSelect = document.getElementById("sourceSelect");
                selectedDeviceId = videoInputDevices[0].deviceId;
                if (videoInputDevices.length > 1) {
                    videoInputDevices.forEach((element) => {
                        const sourceOption = document.createElement("option");
                        sourceOption.text = element.label;
                        sourceOption.value = element.deviceId;
                        sourceSelect.appendChild(sourceOption);
                    });
     
                    sourceSelect.onchange = () => {
                        selectedDeviceId = sourceSelect.value;
                    };
     
                    // const sourceSelectPanel = document.getElementById("sourceSelectPanel");
                    // sourceSelectPanel.style.display = "block";
                }
     
                //DECODE BARCODE FROM CAMERA
                (() => {
                    codeReader
                        .decodeOnceFromVideoDevice(selectedDeviceId, "video")
                        .then((result) => {
                            let searchText = result.text;
     
                            console.log(result);
                            document.getElementById("search-input").value = searchText;
                        })
                        .catch((err) => {
                            console.error(err);
                        });
                })();
     
                document.getElementById("stop-button").addEventListener("click", () => {
                    codeReader.reset();
                    console.log("Reset.");
                });
            })
            .catch((err) => {
                console.error(err);
            });
    });
    
    document.addEventListener('DOMContentLoaded', () => {
        //GET MOVIES WHEN ADD BUTTON IS CLICKED
        document
            .getElementById("add-button")
            .addEventListener("click", () => {
                const searchText = document.getElementById("search-input").value;
                if(!searchText) return;
        
                getMovies(searchText);
        
                UI.clearFields();
            });
    });
    

    【讨论】:

    • 非常感谢!它工作得很好:D 我可以问你这行代码是做什么的吗? ----> if(!searchText) 返回;
    • @Zakaria 在您的代码中,在扫描第一本书时首次添加侦听器,因此文本字段中始终存在有效代码。但是,我的版本在加载时添加了侦听器,因此可以在文本框为空时触发侦听器。该行检查文本框是否为空,如果是,则立即从侦听器返回,避免因无效(空)代码而可能出现的错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 2015-09-14
    相关资源
    最近更新 更多