购物车和计划清单如何用vue实现呢???

360 阅读3分钟

前言

实现效果: 动画2.gif

正文

准备工作:

  • 在终端输入npm create vue@latest 创建vue项目文件;
  • 安装包,在终端输入npm i

文件布局:

image.png

新建的vue文件:

(因为样式我是用css写的,所以记得把style里的lang属性的值改为css)

  • 新建一个文件夹components用于存放vue文件;
  1. Shopping.vue

js

  • 引入文件
import { reactive, computed } from 'vue'; 
  • 引入书籍数组,用reactive来使其变成响应式的变量,因为需要改变书籍购买的数量
const books = reactive([
        {
          id: 1,
          name: '《算法导论》',
          date: '2006-9',
          price: 85.00,
          count: 1
        },
        {
          id: 2,
          name: '《UNIX编程艺术》',
          date: '2006-2',
          price: 59.00,
          count: 1
        },
        {
          id: 3,
          name: '《编程珠玑》',
          date: '2008-10',
          price: 39.00,
          count: 1
        },
        {
          id: 4,
          name: '《代码大全》',
          date: '2006-3',
          price: 128.00,
          count: 1
        },
      ]);
  • 定义一个计算属性computed来计算书籍的总价格,当数量发生变化时会触发该函数
const totalPrice = computed(() => {
    let total = 0;
    books.forEach(book => {
        total += book.price * book.count;
    });
    return total;
});
  • 定义两个函数addminus用户实现书籍数量的变化
const add = (index) => {
//   console.log(index);
  books[index].count++;
};

const minus = (index) => {
//   console.log(index);
  books[index].count--;
};

css

<style lang="css" scoped>
table{
    margin: 0 auto;
    border: 1px solid #e9e9e9;
    border-collapse: collapse;
    border-spacing: 0;
}
th, td{
    padding: 8px 16px;
    border: 1px solid #e9e9e9;
}
.counter{
    margin: 0 5px;
}
</style>

template

  • 通过table标签来渲染书籍的数据
  • 通过v-for来实现遍历渲染
  • 通过@click来绑定addminus
  • :disabled="book.count <= 0表示当数量减到小于或者等于0时,按钮失效
<template>
    <div>
        <table>
            <thead>
                <th>序号</th>
                <th>书籍名称</th>
                <th>出版日期</th>
                <th>价格</th>
                <th>购买数量</th>
                <th>操作</th>
            </thead>

            <tbody>
                <tr v-for="(book, index) in books" :key="index">
                    <td>{{index + 1}}</td>
                    <td>{{book.name}}</td>
                    <td>{{book.date}}</td>
                    <td>{{book.price}}</td>
                    <td>{{book.count}}</td>
                    <td>
                        <button :disabled="book.count <= 0" @click="minus(index)">-</button>
                        <span class="counter">{{book.count}}</span>
                        <button @click="add(index)">+</button>
                    </td>
                </tr>
            </tbody>
        </table>
        <h3>总价格:{{totalPrice}}</h3>
    </div>
</template>
  1. Todos.vue

js

  • 引入文件
import { reactive, ref } from 'vue';
  • 定义一个newTodo,初始值为null,用来获取input输入框的内容,来实现添加功能
const newTodo = ref(null);
  • 定义一个清单数组todos,通过reactive来使其变成响应式的,因为后面点击勾选需要改变里面的completed属性
const state = reactive({
    todos: [
        {
            id: 1,
            title: '学习',
            completed: false
        },
        {
            id: 2,
            title: '吃饭',
            completed: true
        },
        {
            id: 3,
            title: '睡觉',
            completed: false
        }
    ], 
});
  • 定义一个addTodo函数用来增加列表
// 1. 输入newTodo 增加列表
const addTodo = () => {
    state.todos.push({
        id: state.todos.length + 1,
        title: newTodo.value,
        completed: false
    });  
}
  • 定义一个函数com用于勾选和取消
// 2.勾选和取消某件事项
const com = () => {
 state.todos.completed = !state.todos.completed;
};

css

main.js引入一个todomvc-app-css里的css文件里包装好的类来实现

import "todomvc-app-css/index.css";

template

  • 通过v-for来实现列表渲染
  • @click来绑定函数
  • v-model来实现数据的双向绑定
<template>
    <section class="todoapp">
        <header class="header">
           <h1>todos</h1>
           <input type="text" class="new-todo" placeholder="想干的事" @keyup.enter="addTodo"  v-model="newTodo"> 
        </header>

       <section class="main">
        <input type="checkbox" class="toggle-all" id="toggle-all">
        <label for="toggle-all">Mark all as complete</label>

        <ul class="todo-list">
            <li class="todo" v-for="(item, index) in state.todos" :key="index">
                <div class="view">
                    <input type="checkbox" class="toggle" v-model="item.completed" @click="com">
                    <label>{{item.title}}</label>
                    <button class="destroy"></button>
                </div>
            </li>
        </ul>
       </section>
    </section>
</template>

App.vue文件:

js

  • 引入文件
import { ref } from 'vue';
import Shopping from './components/Shopping.vue'
import Todos from './components/Todos.vue';
  • 定义一个变量tabIndex来实现按购物车和计划清单页面的切换的判断,通过ref使其变成响应式的
let tabIndex = ref(1);
  • 定义一个changeTab函数来实现切换
const changeTab = (index) => {
  console.log(index);
  tabIndex.value = index;
}

css

<style lang="css" scoped>
.app{
  text-align: center;
}
.btn{
  font-size: 20px;
  width: 100px;
  height: 40px;
  margin: 20px;
}
</style>

template

  • 通过@click绑定函数
  • 通过v-if来实现两个页面的切换,如果变量tabIndex为1展示购物车页面
  • 反之为计划清单页面
<template>
  <div class="app">
     <button class="btn" @click="changeTab(1)">购物车</button>
     <button class="btn" @click="changeTab(2)">todos</button>


      <!-- shopping -->
      <Shopping v-if="tabIndex === 1"></Shopping>
      <!-- todos -->
      <Todos v-else></Todos>

  </div>
</template>

结语

image.png