Vue 实现 购物车 案例

成品展示Vue 实现 购物车 案例_第1张图片

案例分析

  1. 按照组件化方式实现业务需求
  • 根据业务功能进行组件化划分
    ① 标题组件(展示文本)
    ② 列表组件(列表展示、商品数量变更)
    ③ 结算组件(计算商品总额)
    Vue 实现 购物车 案例_第2张图片

实现步骤

第一步

  1. 静态布局
  2. 将静态数据重构为Vue组件化的形式(通过Vue.component实现 )
  3. 在全局组件内 使用局部组件将其三部分分开(components)
  4. 实现组件化重构

第二步

  1. 用data 和props 实现动态数据传递
  2. 实现计算功能(第三属性 computed)
  3. 计算公式 总价= 单价 *数量
  4. v-for 循环并填充列表
  5. 在子组件获取id 传递给 子组件(this.$emit() 并在父组件进行监听)
  6. 设置删除按钮 ( 找到id 对应的数据的索引 使用splice 来删除对应的数据 )

第三步

  1. 使 数量显示在页面中
  2. 通过$event 来获取 id 和值 (event.target.value)
  3. 判断是要修改那个索引的数据
  4. 数据加减
  5. 使用@click绑定事件并且禁止a标签跳转功能
  6. 给加号 减号 设置一个标志 来相互区别(输入域变更,加号变更,减号变更)

用专业术语讲就是

  • 实现整体布局和样式效果
  • 划分独立的功能组件
  • 组合所有的子组件形成和整体结构
  • 逐个实现各个组件功能
    • 标题组件
    • 列表组件
    • 结算组件

基本样式

#app {
     
            width: 700px;
            height: 800px;
            margin: 0 auto;
        }

        .container .cart {
     
            width: 300px;
            margin: auto;
        }

        .container .title {
     
            background-color: lightblue;
            height: 40px;
            line-height: 40px;
            text-align: center;
            /*color: #fff;*/
        }

        .container .total {
     
            background-color: #FFCE46;
            height: 50px;
            line-height: 50px;
            text-align: right;
        }

        .container .total button {
     
            margin: 0 10px;
            background-color: #DC4C40;
            height: 35px;
            width: 80px;
            border: 0;
        }

        .container .total span {
     
            color: red;
            font-weight: bold;
        }

        .container .item {
     
            height: 55px;
            line-height: 55px;
            position: relative;
            border-top: 1px solid #ADD8E6;
        }

        .container .item img {
     
            width: 45px;
            height: 45px;
            margin: 5px;
        }

        .container .item .name {
     
            position: absolute;
            width: 90px;
            top: 0;
            left: 55px;
            font-size: 16px;
        }

        .container .item .change {
     
            width: 100px;
            position: absolute;
            top: 0;
            right: 50px;
        }

        .container .item .change a {
     
            font-size: 20px;
            width: 30px;
            text-decoration: none;
            background-color: lightgray;
            vertical-align: middle;
        }

        .container .item .change .num {
     
            width: 40px;
            height: 25px;
        }

        .container .item .del {
     
            position: absolute;
            top: 0;
            right: 0px;
            width: 40px;
            text-align: center;
            font-size: 40px;
            cursor: pointer;
            color: red;
        }

        .container .item .del:hover {
     
            background-color: orange;
        }

实现功能主要代码

<div id="app">
        <my-cart>my-cart>
    div>

    <script type="text/javascript" src="../js/vue.js">script>
    <script type="text/javascript">
        var CarTitle = {
      
            props: ['uname'],
            template: `
        
{ {uname}}的商品
`
} var CarList = { props: ['list'], template: `
{ {item.name}}
+
x
`
, methods: { changeNum: function (id, event) { // console.log(id, event.target.value) // 触发自定义事件 this.$emit('change-num', { id: id, num: event.target.value, type: 'change' }) }, sub: function (id) { this.$emit('change-num', { id: id, type: 'sub' }) }, add: function (id) { this.$emit('change-num', { id: id, type: 'add' }) }, del: function (id) { // 把id传递给父组件 // console.log(id); this.$emit('cart-del', id); } }, } var CarTotal = { props: ['list'], template: `
总价:{ {total}}
`
, // 添加第三属性 computed: { total: function () { // 计算商品的总价 var t = 0; this.list.forEach((item) => { t += item.price * item.num; }) return t; } } } Vue.component('my-cart', { // 包含三个子属性 (局部属性) data: function () { return { uname: '张三', list: [ { id: 1, name: 'TCL彩电', price: 1000, num: 2, img: 'img/a.jpg' }, { id: 2, name: '机顶盒', price: 2000, num: 1, img: 'img/b.jpg' }, { id: 3, name: '海尔冰箱', price: 1000, num: 1, img: 'img/c.jpg' }, { id: 4, name: '小米手机', price: 1000, num: 1, img: 'img/d.jpg' }, { id: 5, name: '电视机', price: 1000, num: 1, img: 'img/e.jpg' } ] } }, template: `
`
, components: { 'cart-title': CarTitle, 'cart-list': CarList, 'cart-total': CarTotal, }, methods: { changeNum: function (val) { // 分为三种情况 : 输入域变更,加号变更,减号变更 if (val.type == 'change') { // 根据子组件传递过来的数据,跟新list中对应的数据 this.list.some(item => { if (item.id == val.id) { item.num = val.num; // // 终止遍历 console.log(item.num) return true; } }) } else if (val.type == 'sub') { // 减一操作 this.list.some(item => { if (item.id == val.id) { item.num = 1; // // 终止遍历 return true; } }) } else if (val.type == 'add') { // 加一操作 this.list.some(item => { if (item.id == val.id) { item.num += 1 // // 终止遍历 return true; } }) } }, delCart: function (id) { // 根据id删除list中对应的数据 // 1.根据id 所对应数据的索引 var index = this.list.findIndex(item => { return item.id == id; }); // 2.根据索引删除对应的数据 this.list.splice(index, 1) } } }) var vm = new Vue({ el: '#app', data: { } })
script>

自我激励

人生没有笔直路,当你感到迷茫、失落时,找几部这种充满正能量的电影,坐下来静静欣赏,去发现生命中真正重要的东西。

你可能感兴趣的:(前端,vue,列表)