购物车案例(渲染+事件委托)

290 阅读2分钟

数据:

//数据 data.js文件
let data = [{
        id: 1, //任何数据都会有id号
        state: true,
        img: './images/01.jpg',
        name: '牛奶',
        price: 5,
        count: 2
    },
    {
        id: 2,
        state: true,
        img: './images/01.jpg',
        name: '奶牛',
        price: 10,
        count: 5
    },
    {
        id: 3,
        state: false,
        img: './images/01.jpg',
        name: '酸奶',
        price: 3,
        count: 1
    }
]

静态结构:

  <div class="car">
        <table>
            <thead>
                <tr>
                    <th><input type="checkbox" id="all" />全选</th>
                    <th>商品</th>
                    <th>单价</th>
                    <th>商品数量</th>
                    <th>小计</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody id="carBody">
​
                <tr>
                    <td>
                        <input class="s_ck" type="checkbox" />
                    </td>
                    <td>
                        <img src="./images/01.jpg" />
                        <p>黑马键盘</p>
                    </td>
                    <td class="price">800¥</td>
                    <td>
                        <div class="count-c clearfix">
                            <button class="reduce">-</button>
                            <input type="text" value="5" />
                            <button class="add">+</button>
                        </div>
                    </td>
                    <td class="total">1000¥</td>
                    <td>
                        <a href="javascript:" class="del">删除</a>
                    </td>
                </tr>
            </tbody>
        </table>
        <div class="controls clearfix">
            <a href="javascript:" class="del-all">删除所选商品</a>
            <a href="javascript:" class="clear">清理购物车</a>
            <a href="javascript:" class="pay">去结算</a>
            <p>
                已经选中<span id="totalCount">0</span>件商品;总价:<span id="totalPrice" class="total-price">0¥</span
          >
        </p>
      </div>
    </div>

渲染业务的规律:

前提:渲染必须需要 数据 和 静态结构

1.准备数据

2.准备好静态结构

3.数据一般是对象数组(),所以需要遍历拼接

定义一个字符串用于拼接

使用某种循环遍历数据源

拼接字符串,将数据进行替换

4.将拼接生成好的结构渲染到指定位置

     //  获取carBody元素
            let carBody = document.querySelector('#carBody')
            // 封装渲染
         let init = function(){
              // 数据动态渲染: 数据 +结构 : 遍历 + 拼接 + 赋值
              // 定义一个空字符串
               let htmlString = ''
               // 遍历数据
               data.forEach(function(v,i){
                 // 字符串拼接
                 htmlString += `<tr>
                       <td>
                           <input class="s_ck" type="checkbox" ${v.state?'checked':''} />
                       </td>
                       <td>
                           <img src="${v.img}" />
                           <p>${v.name}</p>
                       </td>
                       <td class="price">${v.price}</td>
                       <td>
                           <div class="count-c clearfix">
                               <button class="reduce" id="${i}">-</button>
                               <input type="text" value="${v.count}" />
                               <button class="add" id="${i}">+</button>
                           </div>
                       </td>
                       <td class="total">${v.price * v.count}</td>
                       <td>
                           <a href="javascript:" class="del" id="${v.id}">删除</a>
                       </td>
                   </tr>`
               })
               // 赋值
               carBody.innerHTML = htmlString
            }
         //调用封装渲染的函数
            init()

Snipaste_2022-01-22_22-33-09.png 事件委托:

1.将事件绑定给已存在的父容器,让子元素进行触发

2.它复用事件冒泡的原理,当子元素触发事件之后,会将事件冒泡给父容器

3.如果想对真正触发事件的元素进行处理,可以使用e.target获取当前真正触发事件的元素

4.如果子元素的操作不一样,需要通过判断,一般我们会对子元素添加一个标识,判断当前触发事件的元素是否有这个标识

使用场景:动态的渲染的元素的事件注册可以使用事件委托,动态渲染的事件的绑定只能使用事件委托

            // 加减是动态生成的元素,事件绑定需要使用事件委托
          // 事件委托 给父容器添加事件委托, 由子容器冒泡触发事件
            carBody.addEventListener('click',function(e){
           
                      //  加
                      if(e.target.className === 'add'){
                        // 元素操作一定要体现到数据,用户操作是的界面元素,但是本质上操作数据
                          // 获取单击元素所在对象的索引位置
                        let i = e.target.id
                        console.log(i);
                        // 修改数据
                              data[i].count++
                        // 重新渲染
                        init()
                      
                      }else if(e.target.className === 'reduce'){
                        // 减
                        let i = e.target.id
                        console.log(i);
                        // 判断数量是否为1,为1不允许进行减的操作
                        if( data[i].count == 1){
                            // 利用return在函数中的特性结束这个if分支语句中return后面代码的运行
                           return
                        }
                        // 修改数据
                              data[i].count--
                        // 重新渲染
                        init()          
                        //删除
                      }else if(e.target.className === 'del'){           
                        let id = e.target.id                 
                         // 删除数据
                        data.splice('id',1)
                         // 重新渲染
                        init()
                      }
            })

2.png

Snipaste_2022-01-22_22-36-58.png

Snipaste_2022-01-22_22-37-41.png