购物车-实现步骤

474 阅读3分钟

购物车-实现步骤

所有操作都要基于数据:

dom操作的本质是数据操作,任何的dom操作一定要体现到数据

动态渲染

准备静态结构

准备好数据--模拟

遍历拼接

赋值

// 1.实现数据的渲染:后期所有的操作基本上都需要重新渲染,所以我将渲染写成一个函数
function init() {
    let htmlStr = ''
    // 遍历  + 拼接
    data.forEach(function(value, index) {
        htmlStr += `<tr>
                    <td>
                      <input class="s_ck" type="checkbox" ${
                        value.state ? 'checked' : ''
                      }/>
                    </td>
                    <td>
                      <img src="${value.img}" />
                      <p>${value.name}</p>
                    </td>
                    <td class="price">${value.price}</td>
                    <td>
                      <div class="count-c clearfix">
                        <button class="reduce">-</button>
                        <input type="text" value="${value.count}" />
                        <button class="add">+</button>
                      </div>
                    </td>
                    <td class="total">${value.price * value.count}¥</td>
                    <td>
                      <a href="javascript:" class="del">删除</a>
                    </td>
                  </tr>`
    })

    // 赋值
    carBody.innerHTML = htmlStr
}
init()

计算出总数和总价格

可以认为商品有没有选中,是由复选框的状态来决定,但是复选框的选中状态由  数据决定的
结论:商品到底有没有选中是由数据决定的
所以,我们可以直接从数据的角度出发。。。
dom元素只是一个载体,只是数据的一种呈现方式。。

细节:数量增减,选中状态的切换,删除  都需要重新计算总数和总价格,所以我们将计算总数和总价格的操作封装为一个函数
// 2.计算出总数和总价格
function calculateTotal() {
    // 所有计算都要参照数据
    let totalCount = 0 // 总数
    let totalPrice = 0 // 总价格
    // 遍历数据
    data.forEach(function(value, index) {
        // 并不是所有商品都要参与计算,只有state为true的商品才需要计算总数和总价格
        if (value.state == true) {
            totalCount++
            // totalCount += value.count
            totalPrice += value.count * value.price
        }
    })
    // 赋值
    totalCountEle.innerText = totalCount
    totalPriceEle.innerText = totalPrice + '¥'
}
calculateTotal()

数量增减

我们真正要做的操作是修改数据本身,而不是修改dom

因为只要修改了数据,我再根据数据进行渲染,那么dom就会有一个相应的变化

细节:动态生成的元素的事件绑定需要使用事件委托

dom元素变化 ,让数据发生改变 --- 双向数据绑定

 // 3.数量增减
carBody.addEventListener('click', function(e) {
    if (e.target.className == 'add') {
        // 获取数据索引
        let index = e.target.id
        // 修改对应数据的count
        data[index].count++
        // 重新渲染
        init()
        // 重新计算总数和总价格
        calculateTotal()
    } else if (e.target.className == 'reduce') {
        // 获取数据索引
        let index = e.target.id
        // 修改对应数据的count
        data[index].count--
        // 重新渲染
        init()
        // 重新计算总数和总价格
        calculateTotal()
    }
})

禁用减按钮

<button class="reduce" id='${index}' ${value.count == 1 ? 'disabled' : '' }>-</button>

全选

根据当前全选复选框的选中状态,修改数据中的state值,之后重新渲染和重新计算总价...

// 4.全选
all.addEventListener('click', function() {
    // 获取全选复选框的状态
    let state = all.checked
    // 修改所有数据中的state状态
    data.forEach(function(value) {
        value.state = state
    })
    init()
    calculateTotal()
})

列表中的复选框的单击操作

修改当前复选框所对应的数据对象的state值,再重新渲染和计算总价

// 5.列表中的复选框的单击操作
carBody.addEventListener('click', function(e) {
    if (e.target.className == 's_ck') {
        // 获取数据索引
        let index = e.target.id
        // 值:取反值
        data[index].state = !data[index].state

        init()
        calculateTotal()
    }
})

删除所选商品

所选的商品: state=true 的商品

细节:体验使用for进行删除的特点,找到bug以及解决bug的方式

filter方法的使用--新的数组的遍历操作

清理购物车

data = []

data.length = 0

数据删除

将当前的 删除按钮 所对应的数据从数组中删除

事件使用委托方式进行绑定

 // 8.数据删除
carBody.addEventListener('click', function(e) {
    if (e.target.className == 'del') {
        // 删除数组中的数据
        data.splice(e.target.id, 1)
        // 重新渲染和计算总价
        init()
        calculateTotal()
    }
})