项目题全解:购物车-灵析社区

懒人学前端

Step 1:安装Vue Cli3脚手架

  • 安装 Nodejs

保证 Node.js8.9 或更⾼版本

终端中输⼊ node -v ,保证已安装成功

  • 安装淘宝镜像源
  • npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 以后的 npm 可以⽤ cnpm 代替
  • 安装 Vue Cli3 脚⼿架

cnpm install -g @vue/cli

  • 检查其版本是否正确

vue --version

Step 2:提供项目模板&基础数据

页面效果:

具体代码:

App.vue

<template>
  <div id="App">
    <ul>
      <li v-for="index in cartList" :key="index.id">
        商品名字: {{ index.title }}
        <p>商品价格: {{ index.price }}</p>
      </li>
      <MyCart :toCart="cartList" />
    </ul>
  </div>
</template>

<script>
import MyCart from "./components/Cart.vue";
export default {
  name: "App",
  components: { MyCart },
  data() {
    return {
      cartList: [
        { id: 1, title: "夹克衫", price: 188, count: 1, active: false },
        { id: 2, title: "西装裤", price: 128, count: 1, active: false },
        { id: 3, title: "polo衫", price: 48, count: 1, active: false },
      ],
    };
  },
  methods: {},
};
</script>

<style scoped></style>

Cart.vue

<template>
  <div>
    <table border="1" class="mytab">
      <tr>
        <th>#</th>
        <th>编号</th>
        <th>单价</th>
        <th>数量</th>
        <th>总价</th>
      </tr>
      <tr v-for="(c, index) in toCart" :key="c.id">
        <th><input type="checkbox" v-model="c.active" /></th>

        <td>{{ index + 1 }}</td>
        <td>{{ c.title }}</td>
        <td>{{ c.price }}</td>
        <td>
          <button @click="substract(index)">-</button>
          {{ c.count }}
          <button @click="add(index)">+</button>
        </td>
        <td>¥{{ c.price * c.count }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      Cart: this.toCart,
    };
  },
  methods: {
    substract(index) {
      this.Cart[index].count = this.Cart[index].count - 1;
    },
    add(index) {
      this.Cart[index].count = this.Cart[index].count + 1;
    },
  },
  props: ["toCart"],
};
</script>


<style scoped>
.mytab {
  border-collapse: collapse;
}
.mytab tr,
.mytab td,
.mytab th {
  text-align: center;
  border: 1px solid #bbbbbb;
}
.mytab th {
  background-color: #e6e6e6;
}
.mytab tr:hover {
  background-color: #eeeeee;
}
.mytab td,
.mytab th {
  padding: 10px;
}
</style>

现在我们已经有了每一件商品的单价,该如何统计共选择了几件商品,总价是多少呢?

Step 3:计算选择商品数量和商品总价

1、计算被选择的商品数量和商品总量

基础操作:

第一步:新增一行 tr ,表格新的一行:

<tr>
    <td></td>
    <td colspan="2">{{ activeCount() }}/{{ count() }}</td>
</tr>

第二步:添加对应 count() 方法,判断 Cart 购物车中共有多少件物品

count() {
  return this.Cart.length;
},

第三步:添加对应 activeCount() 方法,判断 active 的属性有多少个为 true,计算长度

activeCount() {
  return this.Cart.filter((v) => v.active).length;
},

页面效果:

具体代码:

Cart.vue

<template>
  <div>
    <table border="1" class="mytab">
      <tr>
        <th>#</th>
        <th>编号</th>
        <th>单价</th>
        <th>数量</th>
        <th>总价</th>
      </tr>
      <tr v-for="(c, index) in toCart" :key="c.id">
        <th><input type="checkbox" v-model="c.active" /></th>

        <td>{{ index + 1 }}</td>
        <td>{{ c.title }}</td>
        <td>{{ c.price }}</td>
        <td>
          <button @click="substract(index)">-</button>
          {{ c.count }}
          <button @click="add(index)">+</button>
        </td>
        <td>¥{{ c.price * c.count }}</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">{{ activeCount() }}/{{ count() }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      Cart: this.toCart,
    };
  },
  methods: {
    substract(index) {
      this.Cart[index].count = this.Cart[index].count - 1;
    },
    add(index) {
      this.Cart[index].count = this.Cart[index].count + 1;
    },
    count() {
      return this.Cart.length;
    },
    activeCount() {
      return this.Cart.filter((v) => v.active).length;
    },
  },
  props: ["toCart"],
};
</script>

<style scoped>
.mytab {
  border-collapse: collapse;
}
.mytab tr,
.mytab td,
.mytab th {
  text-align: center;
  border: 1px solid #bbbbbb;
}
.mytab th {
  background-color: #e6e6e6;
}
.mytab tr:hover {
  background-color: #eeeeee;
}
.mytab td,
.mytab th {
  padding: 10px;
}
</style>

2、计算商品总价

知识储备:

1、reduce() 方法

reduce() 方法会遍历数组中的每一个元素,每遍历一次就会执行一次回调函数。当遍历完之后会将最后的结果返回出去。

2、reduce() 函数的参数

reduce() 函数,包含四个参数:

previousValue:上一次调用 callbackFn 时的返回值。在第一次调用时,若指定了初始值 initialValue,其值则为 initialValue,否则为数组索引为 0 的元素 array[0]。

currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,其值则为数组索引为 0 的元素 array[0],否则为 array[1]。

currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。

array:用于遍历的数组。

3、举例说明

这里我们用到 reduce() 方法的两个参数,第一个参数是累加函数,第二个是函数的 previousValue 的初始值。

   const arr=[1,2,3,4,5]
    const newarr=arr.reduce((previousValue,current)=>{ 
        console.log(previousValue+'-----'+current);
        //结果为:
                //1-----2
                //3-----3
                //6-----4
                //10-----5
        return previousValue + current // 求和运用
    });
    console.log(newarr); //输出 15

如果设置为 0,则从 0 开始;不设置,默认从数组索引为 0 开始。

    const arr = [1, 2, 3, 4, 5]
    const newarr = arr.reduce((previousValue, current) => {
        console.log(previousValue + '-----' + current);
        //结果为:
        // 0-----1
        // 1-----2
        // 3-----3
        // 6-----4
        // 10-----5
        return previousValue + current // 求和运用
    }, 0);
    // 0 就是上文提及的 initialValue,其作用是设置累加的初始值
    console.log(newarr); //输出 15

基础操作:

第一步:新增一行展示总价

<tr>
    <td></td>
    <td colspan="2">{{ activeCount() }}/{{ count() }}</td>
    <td colspan="2">¥{{ total() }}</td>
  </tr>

第二步:添加对应 total() 方法,判断 Cart 购物车中共有多少件物品

total() {
  let sum = 0;
  this.Cart.forEach((c) => {
    if (c.active) {
      sum += c.price * c.count;
    }
  });
  return sum;
},

除此之外,也可以使用 reduce()

return this.Cart.reduce((sum, c) => {
    if (c.active) {
      sum += c.price * c.count;
    }
    return sum;
}, 0);

页面效果:

具体代码:

Cart.vue

<template>
  <div>
    <table border="1" class="mytab">
      <tr>
        <th>#</th>
        <th>编号</th>
        <th>单价</th>
        <th>数量</th>
        <th>总价</th>
      </tr>
      <tr v-for="(c, index) in toCart" :key="c.id">
        <th><input type="checkbox" v-model="c.active" /></th>

        <td>{{ index + 1 }}</td>
        <td>{{ c.title }}</td>
        <td>{{ c.price }}</td>
        <td>
          <button @click="substract(index)">-</button>
          {{ c.count }}
          <button @click="add(index)">+</button>
        </td>
        <td>¥{{ c.price * c.count }}</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">{{ activeCount() }}/{{ count() }}</td>
        <td colspan="2">¥{{ total() }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      Cart: this.toCart,
    };
  },
  methods: {
    substract(index) {
      this.Cart[index].count = this.Cart[index].count - 1;
    },
    add(index) {
      this.Cart[index].count = this.Cart[index].count + 1;
    },
    count() {
      return this.Cart.length;
    },
    activeCount() {
      return this.Cart.filter((v) => v.active).length;
    },
    // 此处可以进行性能优化
    total() {
      // let sum = 0;
      // this.Cart.forEach((c) => {
      //   if (c.active) {
      //     sum += c.price * c.count;
      //   }
      // });
      // return sum;

      return this.Cart.reduce((sum, c) => {
        if (c.active) {
          sum += c.price * c.count;
        }
        return sum;
      }, 0);
    },
  },
  props: ["toCart"],
};
</script>

<style scoped>
.mytab {
  border-collapse: collapse;
}
.mytab tr,
.mytab td,
.mytab th {
  text-align: center;
  border: 1px solid #bbbbbb;
}
.mytab th {
  background-color: #e6e6e6;
}
.mytab tr:hover {
  background-color: #eeeeee;
}
.mytab td,
.mytab th {
  padding: 10px;
}
</style>

注: 此处读者也可尝试使用 computed 属性对总金额 total 进行计算,性能更高。

Step 4:当商品减到 0 时,从购物车中删除,避免 -1

知识储备:

splice() 的用法

1、会改变原数组

2、splice() 共有三个参数,可以实现新增、删除和替换功能。

第一个参数是要修改的位置,第二个是删除的个数,第三个是要新增的元素。

3、举例说明

splice() 的删除功能,在这里使用两个参数。第一个参数为第一项位置,第二个参数为要删除几个。

array.splice(``index``,num),返回值为删除内容,array 为结果值。
let arr = ['1', '2', '3', '4'];
arr.splice(0, 2);
console.log(arr) // 3 4

随堂提问:

如果 index 超过了数组的长度,或者为负数会如何?

答:如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从 -1 计数,这意味着 -n 是倒数第 n 个元素并且等价于 array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第 0 位。

基础操作:

第一步:对 substract() 方法进行修改 <button @click="substract(index)">-</button>

第二步:添加对应方法,判断两种不同的情况,当数量小于 1 时,直接删除该行。

remove(index) {
  if (window.confirm("确定是否要删除?")) {
    this.Cart.splice(index, 1);
  }
},
substract(index) {
  if (this.Cart[index].count > 1) {
    this.Cart[index].count = this.Cart[index].count - 1;
  } else {
    return this.remove(index);
  }
},

页面效果:

具体代码:

Cart.vue

<template>
  <div>
    <table border="1" class="mytab">
      <tr>
        <th>#</th>
        <th>编号</th>
        <th>单价</th>
        <th>数量</th>
        <th>总价</th>
      </tr>
      <tr v-for="(c, index) in toCart" :key="c.id">
        <th><input type="checkbox" v-model="c.active" /></th>

        <td>{{ index + 1 }}</td>
        <td>{{ c.title }}</td>
        <td>{{ c.price }}</td>
        <td>
          <button @click="substract(index)">-</button>
          {{ c.count }}
          <button @click="add(index)">+</button>
        </td>
        <td>¥{{ c.price * c.count }}</td>
      </tr>
      <tr>
        <td></td>
        <td colspan="2">{{ activeCount() }}/{{ count() }}</td>
        <td colspan="2">¥{{ total() }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  name: "App",
  components: {},
  data() {
    return {
      Cart: this.toCart,
    };
  },
  methods: {
    remove(index) {
      if (window.confirm("确定是否要删除?")) {
        this.Cart.splice(index, 1);
      }
    },
    substract(index) {
      if (this.Cart[index].count > 1) {
        this.Cart[index].count = this.Cart[index].count - 1;
      } else {
        return this.remove(index);
      }
    },
    add(index) {
      this.Cart[index].count = this.Cart[index].count + 1;
    },
    count() {
      return this.Cart.length;
    },
    activeCount() {
      return this.Cart.filter((v) => v.active).length;
    },
    total() {
      // let sum = 0;
      // this.Cart.forEach((c) => {
      //   if (c.active) {
      //     sum += c.price * c.count;
      //   }
      // });
      // return sum;

      return this.Cart.reduce((sum, c) => {
        if (c.active) {
          sum += c.price * c.count;
        }
        return sum;
      }, 0);
    },
  },
  props: ["toCart"],
};
</script>

<style scoped>
.mytab {
  border-collapse: collapse;
}
.mytab tr,
.mytab td,
.mytab th {
  text-align: center;
  border: 1px solid #bbbbbb;
}
.mytab th {
  background-color: #e6e6e6;
}
.mytab tr:hover {
  background-color: #eeeeee;
}
.mytab td,
.mytab th {
  padding: 10px;
}
</style>


阅读量:1747

点赞量:0

收藏量:0