Vue组件化开发——实现购物车和计划表

285 阅读3分钟

前言

什么是组件化开发?

Vue组件化开发是Vue.js框架的一个核心特性,它允许开发者将用户界面分解成一组可复用的、独立的组件,每个组件负责渲染视图的一部分,任何一个vue文件都是一个组件。

实现效果图:

动画.gif

创建Vue项目:

  • 在终端输入npm create vue@latest,取好项目名称然后一路否过去。

image.png

  • 将你创建的项目用编译器打开,打开终端,输入npm i 安装包。
  • 在src文件夹中创建一个component文件夹,再到该文件夹底下创建两个vue文件:shopping.vue和todos.vue,再将这两个文件引入App.vue。这样只需操作shopping.vue和todos.vue就能实现组件化开发。

image.png

App.vue

<template>
  <div class="app">
    <!-- changeTab(1) 直接传入实参 -->
    <button class="btn" @click="changeTab(1)">购物车</button>
    <button class="btn" @click="changeTab(2)">todos</button> 
    <!-- 购物车 -->
    <shopping v-if="tabIndex === 1"></shopping>

    <!-- todos -->
    <todos v-else></todos>

  </div>
</template>

<script setup>
import {ref} from 'vue' 
import shopping from './components/shopping.vue'
import todos from './components/todos.vue'

let tabIndex = ref(1)
const changeTab = (index) => {
  console.log(index);
  tabIndex.value = index
}
</script>

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

分析

创建并给button按钮绑定点击事件@click,函数名为changeTab,为其传入了实参,当标记为1,购物车生效,标记为2,todos生效。let tabIndex = ref(1)让tabIndex变为响应式数据,当tabIndex的值改变时,会被渲染到浏览器页面上。

shopping.vue

  • 首先引入书籍的数组
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
        },
      ])

      const totalPrice = computed(() => {
        let total = 0
        books.forEach(item => {
            total += item.price * item.count
        })
        return total
      })
  • 并且引入import { reactive, computed } from 'vue'将books变为响应式变量,reactive能帮我们把引用类型的数据变成响应式的。
  • 再通过computed来计算书籍的总价,每次当书籍变化时,会再次触发该函数,完成书籍价格的加减。并且定义函数addCount和decrementCount来实现书籍数量的变化。
 const totalPrice = computed(() => {
    let total = 0
    books.forEach(item => {
        total += item.price * item.count
    })
    return total
  })
const addCount = (index) => {
    books[index].count++
}
const decrementCount = (index) => {
    books[index].count--
}
  • 为购物车定义一些样式
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;
}
  • 在template标签中用table标签来包裹书籍的数据,在tr标签中使用v-for来实现遍历books数组,tr的数据不能写死,再到button按钮上分别绑定点击事件@click,绑定addCount和decrementCount。在-按钮写入:disabled="book.count <= 0当书籍的数量减为0时,该减号按钮失效。
<template>
    <div class="shopping">
        <table>
            <thead>
                <th>序号</th>
                <th>书籍名称</th>
                <th>出版日期</th>
                <th>价格</th>
                <th>购买数量</th>
                <th>操作</th>
            </thead>
            <tbody>
                <tr v-for="(book, index) in books">
                    <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="decrementCount(index)">-</button>
                        <span class="counter">{{ book.count }}</span>
                        <button @click="addCount(index)">+</button>
                    </td>
                </tr>
            </tbody>
        </table>
        <h3>总价格:{{ totalPrice }}</h3>
    </div>
</template>

todos.vue

  • 直接使用已经封装好的样式,就不用我们再写css,在终端输入npm i todomvc-app-css image.png
  • 下载好了之后在全局的main.js中引入该文件

image.png

  • 定义一个todos数组,使用reactive使其变为响应式变量。
const state = reactive({
    todos: [
        {
            id: 1,
            title: '学习',
            completed: false
        },
        {
            id: 2,
            title: '吃饭',
            completed: true
        },
        {
            id: 3,
            title: '睡觉',
            completed: false
        }
    ], 
});
  • 定义一个newTodo为null用于接收用户在输入框输入的数据,并且将newTodo变为响应式数据。const newTodo = ref(null);
  • 定义一个addTodo来用于增加列表
const addTodo = () => {
    state.todos.push({
        id: state.todos.length + 1,
        title: newTodo.value,
        completed: false
    });  
}
  • 定义一个com函数用于勾选和取消
const com = () => {
 state.todos.completed = !state.todos.completed;
};
  • 在template标签中的li标签使用v-for来实现列表渲染,再使用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>

总结

Vue组件化开发能够减少代码重复率,提高开发的效率。

qiuzan.jpg